diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 5b0fa4979ab..4510e17f460 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -5,12 +5,12 @@ go 1.25.7
require (
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
github.com/gobwas/glob v0.2.3
- github.com/golangci/golangci-lint/v2 v2.11.4
+ github.com/golangci/golangci-lint/v2 v2.12.2
github.com/google/cel-go v0.26.1
- github.com/mikefarah/yq/v4 v4.44.5
+ github.com/mikefarah/yq/v4 v4.53.2
github.com/openshift/api/tools v0.0.0-20250915151906-94481d71bb6f
go.uber.org/mock v0.6.0
- golang.org/x/mod v0.35.0
+ golang.org/x/mod v0.36.0
gotest.tools/gotestsum v1.13.0
honnef.co/go/tools v0.7.0
k8s.io/apimachinery v0.34.3
@@ -25,6 +25,7 @@ require (
4d63.com/gocheckcompilerdirectives v1.3.0 // indirect
4d63.com/gochecknoglobals v0.2.2 // indirect
cel.dev/expr v0.25.1 // indirect
+ charm.land/lipgloss/v2 v2.0.3 // indirect
codeberg.org/chavacava/garif v0.2.0 // indirect
codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect
dario.cat/mergo v1.0.1 // indirect
@@ -38,47 +39,52 @@ require (
github.com/Antonboom/nilnil v1.1.1 // indirect
github.com/Antonboom/testifylint v1.6.4 // indirect
github.com/BurntSushi/toml v1.6.0 // indirect
+ github.com/ClickHouse/clickhouse-go-linter v1.2.0 // indirect
github.com/Djarvur/go-err113 v0.1.1 // indirect
- github.com/Masterminds/semver/v3 v3.4.0 // indirect
+ github.com/Masterminds/semver/v3 v3.5.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/MirrexOne/unqueryvet v1.5.4 // indirect
github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect
github.com/ProtonMail/go-crypto v1.1.6 // indirect
- github.com/a8m/envsubst v1.4.2 // indirect
- github.com/alecthomas/chroma/v2 v2.23.1 // indirect
+ github.com/a8m/envsubst v1.4.3 // indirect
+ github.com/agext/levenshtein v1.2.1 // indirect
+ github.com/alecthomas/chroma/v2 v2.24.1 // indirect
github.com/alecthomas/go-check-sumtype v0.3.1 // indirect
- github.com/alecthomas/participle/v2 v2.1.1 // indirect
+ github.com/alecthomas/participle/v2 v2.1.4 // indirect
github.com/alexkohler/nakedret/v2 v2.0.6 // indirect
github.com/alexkohler/prealloc v1.1.0 // indirect
github.com/alfatraining/structtag v1.0.0 // indirect
github.com/alingse/asasalint v0.0.11 // indirect
github.com/alingse/nilnesserr v0.2.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
- github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect
- github.com/ashanbrown/makezero/v2 v2.1.0 // indirect
- github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
+ github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
+ github.com/ashanbrown/forbidigo/v2 v2.3.1 // indirect
+ github.com/ashanbrown/makezero/v2 v2.2.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bitfield/gotestdox v0.2.2 // indirect
github.com/bkielbasa/cyclop v1.2.3 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/blizzy78/varnamelen v0.8.0 // indirect
github.com/bombsimon/wsl/v4 v4.7.0 // indirect
- github.com/bombsimon/wsl/v5 v5.6.0 // indirect
+ github.com/bombsimon/wsl/v5 v5.8.0 // indirect
github.com/breml/bidichk v0.3.3 // indirect
github.com/breml/errchkjson v0.4.1 // indirect
- github.com/butuzov/ireturn v0.4.0 // indirect
+ github.com/butuzov/ireturn v0.4.1 // indirect
github.com/butuzov/mirror v1.3.0 // indirect
github.com/catenacyber/perfsprint v0.10.1 // indirect
github.com/ccojocar/zxcvbn-go v1.0.4 // indirect
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charithe/durationcheck v0.0.11 // indirect
- github.com/charmbracelet/colorprofile v0.3.1 // indirect
- github.com/charmbracelet/lipgloss v1.1.0 // indirect
- github.com/charmbracelet/x/ansi v0.10.1 // indirect
- github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
- github.com/charmbracelet/x/term v0.2.1 // indirect
+ github.com/charmbracelet/colorprofile v0.4.3 // indirect
+ github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318 // indirect
+ github.com/charmbracelet/x/ansi v0.11.7 // indirect
+ github.com/charmbracelet/x/term v0.2.2 // indirect
+ github.com/charmbracelet/x/termios v0.1.1 // indirect
+ github.com/charmbracelet/x/windows v0.2.2 // indirect
github.com/ckaznocha/intrange v0.3.1 // indirect
+ github.com/clipperhouse/displaywidth v0.11.0 // indirect
+ github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
github.com/curioswitch/go-reassign v0.3.0 // indirect
@@ -88,9 +94,9 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/denis-tingaikin/go-header v0.5.0 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
- github.com/dlclark/regexp2 v1.11.5 // indirect
+ github.com/dlclark/regexp2 v1.12.0 // indirect
github.com/dnephin/pflag v1.0.7 // indirect
- github.com/elliotchance/orderedmap v1.6.0 // indirect
+ github.com/elliotchance/orderedmap v1.8.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/ettle/strcase v0.2.0 // indirect
@@ -107,6 +113,7 @@ require (
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.9.0 // indirect
github.com/go-git/go-git/v5 v5.19.0 // indirect
+ github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
@@ -123,20 +130,21 @@ require (
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
github.com/gobuffalo/flect v1.0.3 // indirect
- github.com/goccy/go-json v0.10.3 // indirect
- github.com/goccy/go-yaml v1.18.0 // indirect
+ github.com/goccy/go-json v0.10.6 // indirect
+ github.com/goccy/go-yaml v1.19.2 // indirect
github.com/godoc-lint/godoc-lint v0.11.2 // indirect
github.com/gofrs/flock v0.13.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golangci/asciicheck v0.5.0 // indirect
- github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect
+ github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202 // 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/golines v0.15.0 // indirect
github.com/golangci/misspell v0.8.0 // indirect
github.com/golangci/plugin-module-register v0.1.2 // indirect
github.com/golangci/revgrep v0.8.0 // indirect
+ github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba // indirect
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect
github.com/google/gnostic-models v0.7.0 // indirect
@@ -150,14 +158,14 @@ require (
github.com/gostaticanalysis/nilerr v0.1.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
- github.com/hashicorp/go-version v1.8.0 // indirect
+ github.com/hashicorp/go-version v1.9.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
+ github.com/hashicorp/hcl/v2 v2.24.0 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jessevdk/go-flags v1.6.1 // indirect
- github.com/jgautheron/goconst v1.8.2 // indirect
- github.com/jingyugao/rowserrcheck v1.1.1 // indirect
+ github.com/jgautheron/goconst v1.10.0 // indirect
github.com/jinzhu/copier v0.4.0 // indirect
github.com/jjti/go-spancheck v0.6.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
@@ -179,31 +187,32 @@ require (
github.com/ldez/tagliatelle v0.7.2 // indirect
github.com/ldez/usetesting v0.5.0 // indirect
github.com/leonklingele/grouper v1.1.2 // indirect
- github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
+ github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
github.com/macabu/inamedparam v0.2.0 // indirect
- github.com/magiconair/properties v1.8.7 // indirect
+ github.com/magiconair/properties v1.8.10 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect
- github.com/manuelarte/funcorder v0.5.0 // indirect
+ github.com/manuelarte/funcorder v0.6.0 // indirect
github.com/maratori/testableexamples v1.0.1 // indirect
github.com/maratori/testpackage v1.1.2 // indirect
github.com/matoous/godox v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/mattn/go-runewidth v0.0.16 // indirect
+ github.com/mattn/go-runewidth v0.0.23 // indirect
github.com/mgechev/revive v1.15.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/moricho/tparallel v0.3.2 // indirect
- github.com/muesli/termenv v0.16.0 // indirect
+ github.com/muesli/cancelreader v0.2.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nakabonne/nestif v0.3.1 // indirect
github.com/nishanths/exhaustive v0.12.0 // indirect
github.com/nishanths/predeclared v0.2.2 // indirect
github.com/nunnatsa/ginkgolinter v0.23.0 // indirect
github.com/openshift/crd-schema-checker v0.0.0-20250905140724-c313b6407231 // indirect
- github.com/pelletier/go-toml/v2 v2.2.4 // indirect
+ github.com/pelletier/go-toml/v2 v2.3.1 // indirect
github.com/pjbgf/sha1cd v0.6.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
@@ -222,13 +231,14 @@ require (
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ryancurrah/gomodguard v1.4.1 // indirect
+ github.com/ryancurrah/gomodguard/v2 v2.1.3 // indirect
github.com/ryanrolds/sqlclosecheck v0.6.0 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect
- github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08 // indirect
+ github.com/securego/gosec/v2 v2.26.1 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
@@ -236,7 +246,7 @@ require (
github.com/skeema/knownhosts v1.3.1 // indirect
github.com/sonatard/noctx v0.5.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
- github.com/sourcegraph/go-diff v0.7.0 // indirect
+ github.com/sourcegraph/go-diff v0.8.0 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/cobra v1.10.2 // indirect
@@ -248,15 +258,15 @@ require (
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
- github.com/tetafro/godot v1.5.4 // indirect
- github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect
+ github.com/tetafro/godot v1.5.6 // indirect
+ github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4 // indirect
github.com/timonwong/loggercheck v0.11.0 // indirect
github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
github.com/ultraware/funlen v0.2.0 // indirect
github.com/ultraware/whitespace v0.2.0 // indirect
github.com/uudashr/gocognit v1.2.1 // indirect
- github.com/uudashr/iface v1.4.1 // indirect
+ github.com/uudashr/iface v1.4.2 // indirect
github.com/vmware-archive/yaml-patch v0.0.11 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
@@ -265,10 +275,11 @@ require (
github.com/yagipy/maintidx v1.0.0 // indirect
github.com/yeya24/promlinter v0.3.0 // indirect
github.com/ykadowak/zerologlint v0.1.5 // indirect
- github.com/yuin/gopher-lua v1.1.1 // indirect
+ github.com/yuin/gopher-lua v1.1.2 // indirect
+ github.com/zclconf/go-cty v1.18.0 // indirect
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-simpler.org/sloglint v0.12.0 // indirect
go.augendre.info/arangolint v0.4.0 // indirect
go.augendre.info/fatcontext v0.9.0 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.8 // indirect
@@ -287,6 +298,7 @@ require (
go.uber.org/zap v1.27.1 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
+ go.yaml.in/yaml/v4 v4.0.0-rc.4 // indirect
golang.org/x/crypto v0.50.0 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect
@@ -303,7 +315,6 @@ require (
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
- gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index 6bac4750ba6..bec7deecc67 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -4,6 +4,8 @@
4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0=
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
+charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU=
+charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA=
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=
@@ -30,10 +32,12 @@ github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS8
github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4=
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/ClickHouse/clickhouse-go-linter v1.2.0 h1:zbm174up3hTKjp0wKZVnTzRiG7tSF5XZF0FJG/MuCBI=
+github.com/ClickHouse/clickhouse-go-linter v1.2.0/go.mod h1:pLorS7ffPTfuUV9M0SJgfHA/h/WQPQUk2FWG9x74cQ4=
github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g=
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/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE=
+github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
@@ -43,18 +47,20 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsu
github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo=
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
-github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg=
-github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
+github.com/a8m/envsubst v1.4.3 h1:kDF7paGK8QACWYaQo6KtyYBozY2jhQrTuNNuUxQkhJY=
+github.com/a8m/envsubst v1.4.3/go.mod h1:4jjHWQlZoaXPoLQUb7H2qT4iLkZDdmEQiOUogdUmqVU=
+github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
+github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 h1:+XfOU14S4bGuwyvCijJwhhBIjYN+YXS18jrCY2EzJaY=
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
-github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
-github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
+github.com/alecthomas/chroma/v2 v2.24.1 h1:m5ffpfZbIb++k8AqFEKy9uVgY12xIQtBsQlc6DfZJQM=
+github.com/alecthomas/chroma/v2 v2.24.1/go.mod h1:l+ohZ9xRXIbGe7cIW+YZgOGbvuVLjMps/FYN/CwuabI=
github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU=
github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E=
-github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8=
-github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c=
+github.com/alecthomas/participle/v2 v2.1.4 h1:W/H79S8Sat/krZ3el6sQMvMaahJ+XcM9WSI2naI7w2U=
+github.com/alecthomas/participle/v2 v2.1.4/go.mod h1:8tqVbpTX20Ru4NfYQgZf4mP18eXPTBViyMWiArNEgGI=
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=
@@ -71,14 +77,14 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
+github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
+github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/ashanbrown/forbidigo/v2 v2.3.0 h1:OZZDOchCgsX5gvToVtEBoV2UWbFfI6RKQTir2UZzSxo=
-github.com/ashanbrown/forbidigo/v2 v2.3.0/go.mod h1:5p6VmsG5/1xx3E785W9fouMxIOkvY2rRV9nMdWadd6c=
-github.com/ashanbrown/makezero/v2 v2.1.0 h1:snuKYMbqosNokUKm+R6/+vOPs8yVAi46La7Ck6QYSaE=
-github.com/ashanbrown/makezero/v2 v2.1.0/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY=
-github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
-github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
+github.com/ashanbrown/forbidigo/v2 v2.3.1 h1:KAZijvQ7zeIBKbhikT4jCm0TLYXC4u78bTiLh/8JROI=
+github.com/ashanbrown/forbidigo/v2 v2.3.1/go.mod h1:2QDkLTzU6TV937eFROamXrW92M3paehdae4HCDCOZCM=
+github.com/ashanbrown/makezero/v2 v2.2.1 h1:A7uU8dgB1PA9aelTxHMfHIQ8Qev8AB3JLxJUBUsejqM=
+github.com/ashanbrown/makezero/v2 v2.2.1/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bitfield/gotestdox v0.2.2 h1:x6RcPAbBbErKLnapz1QeAlf3ospg8efBsedU93CDsnE=
@@ -91,14 +97,14 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ
github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k=
github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ=
github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg=
-github.com/bombsimon/wsl/v5 v5.6.0 h1:4z+/sBqC5vUmSp1O0mS+czxwH9+LKXtCWtHH9rZGQL8=
-github.com/bombsimon/wsl/v5 v5.6.0/go.mod h1:Uqt2EfrMj2NV8UGoN1f1Y3m0NpUVCsUdrNCdet+8LvU=
+github.com/bombsimon/wsl/v5 v5.8.0 h1:JTkyfs4yl8SPejrCF2GdABXE+mO1WvM7iUYzRWlsxDs=
+github.com/bombsimon/wsl/v5 v5.8.0/go.mod h1:AbOLsulgkqP4ZnitHf9gwPtCOGlrzkk0jb0uNxRSY0o=
github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE=
github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE=
github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg=
github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s=
-github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E=
-github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70=
+github.com/butuzov/ireturn v0.4.1 h1:vWb3NO4t77iku/sjCQ/2pHTQeOmxEhjIriJqRLg1Y+I=
+github.com/butuzov/ireturn v0.4.1/go.mod h1:q+DXKzTDV5guNuXLnIab9fKXizTn2miZHLhxH7V/GB4=
github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc=
github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI=
github.com/catenacyber/perfsprint v0.10.1 h1:u7Riei30bk46XsG8nknMhKLXG9BcXz3+3tl/WpKm0PQ=
@@ -111,18 +117,24 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1DidBcABctk=
github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4=
-github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
-github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
-github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
-github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
-github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
-github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
-github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
-github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
-github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
-github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
+github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
+github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
+github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318 h1:OqDqxQZliC7C8adA7KjelW3OjtAxREfeHkNcd66wpeI=
+github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318/go.mod h1:Y6kE2GzHfkyQQVCSL9r2hwokSrIlHGzZG+71+wDYSZI=
+github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
+github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
+github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
+github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
+github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
+github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
+github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
+github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs=
github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk=
+github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
+github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
+github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
+github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
@@ -148,14 +160,14 @@ github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42
github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
-github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
-github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8=
+github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk=
github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE=
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
-github.com/elliotchance/orderedmap v1.6.0 h1:xjn+kbbKXeDq6v9RVE+WYwRbYfAZKvlWfcJNxM8pvEw=
-github.com/elliotchance/orderedmap v1.6.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys=
+github.com/elliotchance/orderedmap v1.8.0 h1:TrOREecvh3JbS+NCgwposXG5ZTFHtEsQiCGOhPElnMw=
+github.com/elliotchance/orderedmap v1.8.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
@@ -194,6 +206,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.19.0 h1:+WkVUQZSy/F1Gb13udrMKjIM2PrzsNfDKFSfo5tkMtc=
github.com/go-git/go-git/v5 v5.19.0/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
+github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
+github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -213,6 +227,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
+github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8=
github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU=
github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s=
@@ -240,10 +256,10 @@ github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
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/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
-github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
-github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
-github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
+github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU=
+github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
+github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
+github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godoc-lint/godoc-lint v0.11.2 h1:Bp0FkJWoSdNsBikdNgIcgtaoo+xz6I/Y9s5WSBQUeeM=
github.com/godoc-lint/godoc-lint v0.11.2/go.mod h1:iVpGdL1JCikNH2gGeAn3Hh+AgN5Gx/I/cxV+91L41jo=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
@@ -256,14 +272,14 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0=
github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ=
-github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw=
-github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E=
+github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202 h1:CbTB8KpqnViI6lIXxp03Oclc4VFHi3K4BWC1TacsZ+A=
+github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E=
github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U=
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.11.4 h1:GK+UlZBN5y7rh2PBnHA93XLSX6RaF7uhzJQ3JwU1wuA=
-github.com/golangci/golangci-lint/v2 v2.11.4/go.mod h1:ODQDCASMA3VqfZYIbbQLpTRTzV7O/vjmIRF6u8NyFwI=
+github.com/golangci/golangci-lint/v2 v2.12.2 h1:7+d1uY0bq1MU2UV3R5pW5Q7QWdcoq4naMRXM+gsJKrs=
+github.com/golangci/golangci-lint/v2 v2.12.2/go.mod h1:opqHHuIcTG2R+4akzWMd4o1BnD9/1LcjICWOujr91U8=
github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0=
github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10=
github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg=
@@ -272,6 +288,8 @@ github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3H
github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw=
github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s=
github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k=
+github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba h1:lqtcnSMDuuJdu/LrKWi5RJzpSNLOJXYe/nzQutTI5kg=
+github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba/go.mod h1:sCBNcpRmhJCtbFGz49+IM3ETTFf7QdJ30AeYCd43NKk=
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM=
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s=
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM=
@@ -319,10 +337,12 @@ github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1T
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
-github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
+github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE=
+github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -331,10 +351,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
-github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4=
-github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako=
-github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs=
-github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c=
+github.com/jgautheron/goconst v1.10.0 h1:Ptt+OoE4NaEWKhLrWrrN3IpZdGLiqaf7WLnEX/iv4Jw=
+github.com/jgautheron/goconst v1.10.0/go.mod h1:0p+wv1lFOiUr0IlNNT1nrm6+8DB8u2sU6KHGzFRXHDc=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8=
@@ -391,18 +409,18 @@ github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc
github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ=
github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY=
github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA=
-github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
-github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
+github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE=
github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
+github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww=
github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM=
-github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8=
-github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA=
+github.com/manuelarte/funcorder v0.6.0 h1:0hBngc4fa1IgNiI65A7sFGkMvoMCc878RjqB5V7rWP0=
+github.com/manuelarte/funcorder v0.6.0/go.mod h1:id3NDhXdQBmeqXH7eVC6Z89xS6JxvZ8kF9xUxpArU/g=
github.com/maratori/testableexamples v1.0.1 h1:HfOQXs+XgfeRBJ+Wz0XfH+FHnoY9TVqL6Fcevpzy4q8=
github.com/maratori/testableexamples v1.0.1/go.mod h1:XE2F/nQs7B9N08JgyRmdGjYVGqxWwClLPCGSQhXQSrQ=
github.com/maratori/testpackage v1.1.2 h1:ffDSh+AgqluCLMXhM19f/cpvQAKygKAJXFl9aUjmbqs=
@@ -415,14 +433,16 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
-github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
+github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mgechev/revive v1.15.0 h1:vJ0HzSBzfNyPbHKolgiFjHxLek9KUijhqh42yGoqZ8Q=
github.com/mgechev/revive v1.15.0/go.mod h1:LlAKO3QQe9OJ0pVZzI2GPa8CbXGZ/9lNpCGvK4T/a8A=
-github.com/mikefarah/yq/v4 v4.44.5 h1:/Xm1dM1BfyDJMg+yIpnl2AgpmLFQg3Lcm/kuyYgHEXE=
-github.com/mikefarah/yq/v4 v4.44.5/go.mod h1:rpn3xGVz+2pDuLJTlCvzatCwTmmUeHcm7MbkbtHdvkc=
+github.com/mikefarah/yq/v4 v4.53.2 h1:ZPIUjpgh4ACOKW98PXvr4o4dlaRjSOLLa6gS1t7FrAo=
+github.com/mikefarah/yq/v4 v4.53.2/go.mod h1:dKgedwimDBsgJO6zq8tQkiGoGmkRH9JWrl3G3na2z7M=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
+github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -431,8 +451,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
-github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
-github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
+github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
+github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U=
@@ -447,8 +467,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
-github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
+github.com/onsi/ginkgo/v2 v2.28.2 h1:DTrMfpqxiNUyQ3Y0zhn1n3cOO2euFgQPYIpkWwxVFps=
+github.com/onsi/ginkgo/v2 v2.28.2/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
github.com/openshift/api/tools v0.0.0-20250915151906-94481d71bb6f h1:dB/CgBKnKoxXMHPY6JDqoxAjd7SdRvjrMqtuAtLQpzQ=
@@ -464,8 +484,8 @@ github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJ
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
-github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
-github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
+github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc=
+github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU=
github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
@@ -496,7 +516,6 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4l
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI=
github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU=
-github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@@ -508,6 +527,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g=
github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I=
+github.com/ryancurrah/gomodguard/v2 v2.1.3 h1:E7sz3PJwE9Ba1reVxSpF6XLCPJZ74Kfw/LabTNM4GIA=
+github.com/ryancurrah/gomodguard/v2 v2.1.3/go.mod h1:CQicdLGatWMxLX53JzoBjYlsNZhHbmLv2AVa0s2aivU=
github.com/ryanrolds/sqlclosecheck v0.6.0 h1:pEyL9okISdg1F1SEpJNlrEotkTGerv5BMk7U4AG0eVg=
github.com/ryanrolds/sqlclosecheck v0.6.0/go.mod h1:xyX16hsDaCMXHrMJ3JMzGf5OpDfHTOTTQrT7HOFUmeU=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
@@ -520,12 +541,10 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM
github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ=
github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ=
github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8=
-github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08 h1:AoLtJX4WUtZkhhUUMFy3GgecAALp/Mb4S1iyQOA2s0U=
-github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08/go.mod h1:+XLCJiRE95ga77XInNELh2M6zQP+PdqiT9Zpm0D9Wpk=
+github.com/securego/gosec/v2 v2.26.1 h1:gdkttGhQFVehqRJ8grKH4DrpqM/QlPKNHBnl8QgcEC4=
+github.com/securego/gosec/v2 v2.26.1/go.mod h1:57UW4p0uoP3kxoTkhoo3axLdVAi+OWrLg/Ax/kdqtPE=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
-github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
-github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@@ -539,8 +558,8 @@ github.com/sonatard/noctx v0.5.1 h1:wklWg9c9ZYugOAk7qG4yP4PBrlQsmSLPTvW1K4PRQMs=
github.com/sonatard/noctx v0.5.1/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
-github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0=
-github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
+github.com/sourcegraph/go-diff v0.8.0 h1:ipIyu4cTsLbIrln4l0qtHA3r0a7gyK4ntKjtQytHhvY=
+github.com/sourcegraph/go-diff v0.8.0/go.mod h1:hWlcO7Al+UZStZAP8rBumHpCK5ZHQ5BXsMls8p4+F5E=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
@@ -579,10 +598,10 @@ github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA
github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
-github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg=
-github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU=
-github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk=
-github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460=
+github.com/tetafro/godot v1.5.6 h1:IEkrFCwXaYHlOn4mGzGS3F3dkP6m9t0jpwqBFPIkKiA=
+github.com/tetafro/godot v1.5.6/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU=
+github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4 h1:SiHe5XLTn9sFWJ5pBwJ5FN/4j34q9ZlOAD//kMoMYp0=
+github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4/go.mod h1:sDHLK7rb/59v/ZxZ7KtymgcoxuUMxjXq8gtu9VMOK8M=
github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M=
github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8=
github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVFL27Of9is=
@@ -595,8 +614,8 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW
github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8=
github.com/uudashr/gocognit v1.2.1 h1:CSJynt5txTnORn/DkhiB4mZjwPuifyASC8/6Q0I/QS4=
github.com/uudashr/gocognit v1.2.1/go.mod h1:acaubQc6xYlXFEMb9nWX2dYBzJ/bIjEkc1zzvyIZg5Q=
-github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU=
-github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg=
+github.com/uudashr/iface v1.4.2 h1:06Vq5RKVYThBsj0Bnw4oasMjD1r+7CE/bcKOA8dVSvg=
+github.com/uudashr/iface v1.4.2/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg=
github.com/vmware-archive/yaml-patch v0.0.11 h1:9o4FGgkpLD88A5O7BOOXs7UBeeymRT9atLsKmHJ2wWs=
github.com/vmware-archive/yaml-patch v0.0.11/go.mod h1:mHWEn1O1CU3yBnN6iPFeAwAqzUibF2X+9EltQ28w+Vs=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@@ -617,19 +636,22 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
-github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
+github.com/yuin/gopher-lua v1.1.2 h1:yF/FjE3hD65tBbt0VXLE13HWS9h34fdzJmrWRXwobGA=
+github.com/yuin/gopher-lua v1.1.2/go.mod h1:7aRmXIWl37SqRf0koeyylBEzJ+aPt8A+mmkQ4f1ntR8=
+github.com/zclconf/go-cty v1.18.0 h1:pJ8+HNI4gFoyRNqVE37wWbJWVw43BZczFo7KUoRczaA=
+github.com/zclconf/go-cty v1.18.0/go.mod h1:qpnV6EDNgC1sns/AleL1fvatHw72j+S+nS+MJ+T2CSg=
+github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
+github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo=
gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8=
go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ=
go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28=
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-simpler.org/sloglint v0.12.0 h1:UzWDlLWNE5FLqsvyq3tWYHuQMbqrervOhT8qPl4Mmw4=
+go-simpler.org/sloglint v0.12.0/go.mod h1:jBjjC2bm8rYrs88oTRlFX497kWjJsyZWYoNaXkGRI6I=
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=
@@ -674,13 +696,13 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
+go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U=
+go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
@@ -692,28 +714,21 @@ golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358/go.mod h1:4Mzdyp/
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
-golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
+golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
+golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
@@ -725,8 +740,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -736,9 +749,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -747,17 +758,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
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=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -766,8 +771,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
@@ -781,12 +784,9 @@ golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
@@ -815,8 +815,6 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE=
-gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/.editorconfig b/hack/tools/vendor/charm.land/lipgloss/v2/.editorconfig
new file mode 100644
index 00000000000..5de2df8c576
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/.editorconfig
@@ -0,0 +1,18 @@
+# https://editorconfig.org/
+
+root = true
+
+[*]
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = space
+indent_size = 2
+
+[*.go]
+indent_style = tab
+indent_size = 8
+
+[*.golden]
+insert_final_newline = false
+trim_trailing_whitespace = false
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/.gitattributes b/hack/tools/vendor/charm.land/lipgloss/v2/.gitattributes
new file mode 100644
index 00000000000..d5273520ad5
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/.gitattributes
@@ -0,0 +1 @@
+*.golden linguist-generated=true -text
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/.gitignore b/hack/tools/vendor/charm.land/lipgloss/v2/.gitignore
similarity index 53%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/.gitignore
rename to hack/tools/vendor/charm.land/lipgloss/v2/.gitignore
index db482015ddf..3b478f57593 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/.gitignore
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/.gitignore
@@ -1,2 +1,3 @@
ssh_example_ed25519*
-dist/
+/tmp
+**/.crush/**
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/.golangci.yml b/hack/tools/vendor/charm.land/lipgloss/v2/.golangci.yml
new file mode 100644
index 00000000000..c90f031611d
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/.golangci.yml
@@ -0,0 +1,47 @@
+version: "2"
+run:
+ tests: false
+linters:
+ enable:
+ - bodyclose
+ - exhaustive
+ - goconst
+ - godot
+ - gomoddirectives
+ - goprintffuncname
+ - gosec
+ - misspell
+ - nakedret
+ - nestif
+ - nilerr
+ - noctx
+ - nolintlint
+ - prealloc
+ - revive
+ - rowserrcheck
+ - sqlclosecheck
+ - tparallel
+ - unconvert
+ - unparam
+ - whitespace
+ - wrapcheck
+ exclusions:
+ rules:
+ - text: '(slog|log)\.\w+'
+ linters:
+ - noctx
+ generated: lax
+ presets:
+ - common-false-positives
+ settings:
+ exhaustive:
+ default-signifies-exhaustive: true
+issues:
+ max-issues-per-linter: 0
+ max-same-issues: 0
+formatters:
+ enable:
+ - gofumpt
+ - goimports
+ exclusions:
+ generated: lax
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/.goreleaser.yml b/hack/tools/vendor/charm.land/lipgloss/v2/.goreleaser.yml
new file mode 100644
index 00000000000..c61970e07a6
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/.goreleaser.yml
@@ -0,0 +1,5 @@
+includes:
+ - from_url:
+ url: charmbracelet/meta/main/goreleaser-lib.yaml
+# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
+
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/LICENSE b/hack/tools/vendor/charm.land/lipgloss/v2/LICENSE
new file mode 100644
index 00000000000..9f60dc1fcbd
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021-2026 Charmbracelet, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/README.md b/hack/tools/vendor/charm.land/lipgloss/v2/README.md
similarity index 61%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/README.md
rename to hack/tools/vendor/charm.land/lipgloss/v2/README.md
index cee2371ce15..4fda640039c 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/README.md
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/README.md
@@ -1,23 +1,21 @@
# Lip Gloss
-
- 
+
+ 
-
+
-
-Style definitions for nice terminal layouts. Built with TUIs in mind.
+Style definitions for nice terminal layouts. Built with TUIs in mind.
-
+
Lip Gloss takes an expressive, declarative approach to terminal rendering.
Users familiar with CSS will feel at home with Lip Gloss.
```go
-
-import "github.com/charmbracelet/lipgloss"
+import "charm.land/lipgloss/v2"
var style = lipgloss.NewStyle().
Bold(true).
@@ -27,9 +25,20 @@ var style = lipgloss.NewStyle().
PaddingLeft(4).
Width(22)
-fmt.Println(style.Render("Hello, kitty"))
+lipgloss.Println(style.Render("Hello, kitty"))
+```
+
+## Installation
+
+```bash
+go get charm.land/lipgloss/v2
```
+> [!TIP]
+>
+> Upgrading from v1? Check out the [upgrade guide](./UPGRADE_GUIDE_V2.md), or
+> point your LLM at it and let it go to town.
+
## Colors
Lip Gloss supports the following color profiles:
@@ -60,45 +69,58 @@ lipgloss.Color("#3C3C3C") // a dark gray
...as well as a 1-bit ASCII profile, which is black and white only.
-The terminal's color profile will be automatically detected, and colors outside
-the gamut of the current palette will be automatically coerced to their closest
-available value.
-
-### Adaptive Colors
-
-You can also specify color options for light and dark backgrounds:
+There are also named constants for the 16 standard ANSI colors:
```go
-lipgloss.AdaptiveColor{Light: "236", Dark: "248"}
+lipgloss.Black
+lipgloss.Red
+lipgloss.Green
+lipgloss.Yellow
+lipgloss.Blue
+lipgloss.Magenta
+lipgloss.Cyan
+lipgloss.White
+lipgloss.BrightBlack
+lipgloss.BrightRed
+lipgloss.BrightGreen
+lipgloss.BrightYellow
+lipgloss.BrightBlue
+lipgloss.BrightMagenta
+lipgloss.BrightCyan
+lipgloss.BrightWhite
```
-The terminal's background color will automatically be detected and the
-appropriate color will be chosen at runtime.
+### Automatically Downsampling Colors
-### Complete Colors
+Some users don't have Truecolor terminals. Other times, output might not
+support color at all (for example, in logs). Lip Gloss was designed to handle
+this gracefully by automatically downsampling colors to the best available
+profile.
-CompleteColor specifies exact values for True Color, ANSI256, and ANSI color
-profiles.
+If you're using Lip Gloss with Bubble Tea, there’s nothing to do. If you're
+using Lip Gloss standalone, just use `lipgloss.Println` or `lipgloss.Sprint`
+(and their variants).
-```go
-lipgloss.CompleteColor{TrueColor: "#0000FF", ANSI256: "86", ANSI: "5"}
-```
+For more, see [advanced color usage](#advanced-color-usage).
-Automatic color degradation will not be performed in this case and it will be
-based on the color specified.
+### Color Utilities
-### Complete Adaptive Colors
-
-You can use `CompleteColor` with `AdaptiveColor` to specify the exact values for
-light and dark backgrounds without automatic color degradation.
+Lip Gloss ships with a handful of handy tools for working with colors:
```go
-lipgloss.CompleteAdaptiveColor{
- Light: CompleteColor{TrueColor: "#d7ffae", ANSI256: "193", ANSI: "11"},
- Dark: CompleteColor{TrueColor: "#d75fee", ANSI256: "163", ANSI: "5"},
-}
+c := lipgloss.Color("#EB4268") // Sriracha sauce color
+dark := lipgloss.Darken(c, 0.5) // dark Sriracha sauce
+light := lipgloss.Lighten(c, 0.35) // light Sriracha sauce
+green := lipgloss.Complementary(c) // greenish Sriracha sauce
+withAlpha := lipgloss.Alpha(c, 0.2) // watered down Sriracha sauce
```
+### Advanced Color Tooling
+
+Lip Gloss also supports color blending, automatically choosing light or dark
+variants of colors at runtime, and a lot more. For details, see [Advanced Color
+Usage](#advanced-color-usage) and [the docs][docs].
+
## Inline Formatting
Lip Gloss supports the usual ANSI text formatting options:
@@ -114,6 +136,34 @@ var style = lipgloss.NewStyle().
Reverse(true)
```
+### Underline Styles
+
+Beyond simple on/off, underlines support multiple styles and custom colors:
+
+```go
+s := lipgloss.NewStyle().
+ UnderlineStyle(lipgloss.UnderlineCurly).
+ UnderlineColor(lipgloss.Color("#FF0000"))
+```
+
+Available styles: `UnderlineNone`, `UnderlineSingle`, `UnderlineDouble`,
+`UnderlineCurly`, `UnderlineDotted`, `UnderlineDashed`.
+
+### Hyperlinks
+
+Styles can render clickable hyperlinks in supporting terminals:
+
+```go
+s := lipgloss.NewStyle().
+ Foreground(lipgloss.Color("#7B2FBE")).
+ Hyperlink("https://charm.land")
+
+lipgloss.Println(s.Render("Visit Charm"))
+```
+
+In unsupported terminals this will degrade gracefully and hyperlinks will
+simply not render.
+
## Block-Level Formatting
Lip Gloss also supports rules for block-level formatting:
@@ -152,6 +202,16 @@ lipgloss.NewStyle().Padding(1, 4, 2)
lipgloss.NewStyle().Margin(2, 4, 3, 1)
```
+You can also customize the characters used for padding and margin fill:
+
+```go
+s := lipgloss.NewStyle().
+ Padding(1, 2).
+ PaddingChar('·').
+ Margin(1, 2).
+ MarginChar('░')
+```
+
## Aligning Text
You can align paragraphs of text to the left, right, or center.
@@ -221,7 +281,15 @@ lipgloss.NewStyle().
Border(lipgloss.DoubleBorder(), true, false, false, true)
```
-For more on borders see [the docs][docs].
+You can also pass multiple colors to a border for a gradient effect:
+
+```go
+s := lipgloss.NewStyle().
+ Border(lipgloss.RoundedBorder()).
+ BorderForegroundBlend(lipgloss.Color("#FF0000"), lipgloss.Color("#0000FF"))
+```
+
+For more on borders see [the docs](https://pkg.go.dev/charm.land/lipgloss/v2#Border).
## Copying Styles
@@ -233,12 +301,10 @@ style := lipgloss.NewStyle().Foreground(lipgloss.Color("219"))
copiedStyle := style // this is a true copy
wildStyle := style.Blink(true) // this is also true copy, with blink added
-
```
-Since `Style` data structures contains only primitive types, assigning a style
-to another effectively creates a new copy of the style without mutating the
-original.
+Since `Style` is a pure value type, assigning a style to another effectively
+creates a new copy of the style without mutating the original.
## Inheritance
@@ -269,7 +335,7 @@ var style = lipgloss.NewStyle().
UnsetBackground() // never mind
```
-When a rule is unset, it won't be inherited or copied.
+When a rule is unset, it won’t be inherited or copied.
## Enforcing Rules
@@ -302,50 +368,57 @@ style = style.TabWidth(0) // remove tabs entirely
style = style.TabWidth(lipgloss.NoTabConversion) // leave tabs intact
```
+## Wrapping
+
+The `Wrap` function wraps text while preserving ANSI styles and hyperlinks
+across line boundaries:
+
+```go
+wrapped := lipgloss.Wrap(styledText, 40, " ")
+```
+
## Rendering
Generally, you just call the `Render(string...)` method on a `lipgloss.Style`:
```go
style := lipgloss.NewStyle().Bold(true).SetString("Hello,")
-fmt.Println(style.Render("kitty.")) // Hello, kitty.
-fmt.Println(style.Render("puppy.")) // Hello, puppy.
+lipgloss.Println(style.Render("kitty.")) // Hello, kitty.
+lipgloss.Println(style.Render("puppy.")) // Hello, puppy.
```
But you could also use the Stringer interface:
```go
var style = lipgloss.NewStyle().SetString("你好,猫咪。").Bold(true)
-fmt.Println(style) // 你好,猫咪。
+lipgloss.Println(style) // 你好,猫咪。
```
-### Custom Renderers
+## Utilities
-Custom renderers allow you to render to a specific outputs. This is
-particularly important when you want to render to different outputs and
-correctly detect the color profile and dark background status for each, such as
-in a server-client situation.
+In addition to pure styling, Lip Gloss also ships with some utilities to help
+assemble your layouts.
-```go
-func myLittleHandler(sess ssh.Session) {
- // Create a renderer for the client.
- renderer := lipgloss.NewRenderer(sess)
+### Compositing
- // Create a new style on the renderer.
- style := renderer.NewStyle().Background(lipgloss.AdaptiveColor{Light: "63", Dark: "228"})
+
- // Render. The color profile and dark background state will be correctly detected.
- io.WriteString(sess, style.Render("Heyyyyyyy"))
-}
-```
+Lip Gloss includes a powerful, cell-based compositor for rendering layered
+content:
-For an example on using a custom renderer over SSH with [Wish][wish] see the
-[SSH example][ssh-example].
+```go
+// Create some layers.
+a := lipgloss.NewLayer(pickles).X(4).Y(2).Z(1)
+b := lipgloss.NewLayer(bitterMelon).X(22).Y(1)
+c := lipgloss.NewLayer(sriracha).X(11).Y(7)
-## Utilities
+// Composite 'em and render.
+output := compositor.Compose(a, b, c).Render()
+```
-In addition to pure styling, Lip Gloss also ships with some utilities to help
-assemble your layouts.
+For a more thorough example, see [the canvas
+example](./examples/canvas/main.go). For reference, including how to detect
+mouse clicks on layers, see [the docs][docs].
### Joining Paragraphs
@@ -383,9 +456,22 @@ height := lipgloss.Height(block)
w, h := lipgloss.Size(block)
```
+### Blending Colors
+
+You can blend colors in one or two dimensions for gradient effects:
+
+```go
+// 1-dimentinoal gradient
+colors := lipgloss.Blend1D(10, lipgloss.Color("#FF0000"), lipgloss.Color("#0000FF"))
+
+// 2-dimensional gradient with rotation
+colors := lipgloss.Blend2D(80, 24, 45.0, color1, color2, color3)
+```
+
### Placing Text in Whitespace
-Sometimes you’ll simply want to place a block of text in whitespace.
+Sometimes you’ll simply want to place a block of text in whitespace. This is
+a lightweight alternative to compositing.
```go
// Center a paragraph horizontally in a space 80 cells wide. The height of
@@ -407,7 +493,7 @@ You can also style the whitespace. For details, see [the docs][docs].
Lip Gloss ships with a table rendering sub-package.
```go
-import "github.com/charmbracelet/lipgloss/table"
+import "charm.land/lipgloss/v2/table"
```
Define some rows of data.
@@ -459,14 +545,11 @@ t.Row("English", "You look absolutely fabulous.", "How's it going?")
Print the table.
```go
-fmt.Println(t)
+lipgloss.Println(t)
```

-> [!WARNING]
-> Table `Rows` need to be declared before `Offset` otherwise it does nothing.
-
### Table Borders
There are helpers to generate tables in markdown or ASCII style:
@@ -503,14 +586,14 @@ table.New().Border(lipgloss.ASCIIBorder())
+----------+--------------+-----------+
```
-For more on tables see [the docs](https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc) and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table).
+For more on tables see [the docs][docs] and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table).
## Rendering Lists
Lip Gloss ships with a list rendering sub-package.
```go
-import "github.com/charmbracelet/lipgloss/list"
+import "charm.land/lipgloss/v2/list"
```
Define a new list.
@@ -522,7 +605,7 @@ l := list.New("A", "B", "C")
Print the list.
```go
-fmt.Println(l)
+lipgloss.Println(l)
// • A
// • B
@@ -548,7 +631,7 @@ l := list.New(
Print the list.
```go
-fmt.Println(l)
+lipgloss.Println(l)
```
@@ -564,7 +647,7 @@ itemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("212")).MarginRight(1
l := list.New(
"Glossier",
- "Claire’s Boutique",
+ "Claire's Boutique",
"Nyx",
"Mac",
"Milk",
@@ -617,7 +700,7 @@ for i := 0; i < repeat; i++ {
Lip Gloss ships with a tree rendering sub-package.
```go
-import "github.com/charmbracelet/lipgloss/tree"
+import "charm.land/lipgloss/v2/tree"
```
Define a new tree.
@@ -630,7 +713,7 @@ t := tree.Root(".").
Print the tree.
```go
-fmt.Println(t)
+lipgloss.Println(t)
// .
// ├── A
@@ -661,7 +744,7 @@ t := tree.Root(".").
Print the tree.
```go
-fmt.Println(t)
+lipgloss.Println(t)
```
@@ -713,49 +796,159 @@ for i := 0; i < repeat; i++ {
}
```
----
+## Advanced Color Usage
-## FAQ
+One of the most powerful features of Lip Gloss is the ability to render
+different colors at runtime depending on the user's terminal and environment,
+allowing you to present the best possible user experience.
-
-
-Why are things misaligning? Why are borders at the wrong widths?
-
-This is most likely due to your locale and encoding, particularly with
-regard to Chinese, Japanese, and Korean (for example, zh_CN.UTF-8
-or ja_JP.UTF-8). The most direct way to fix this is to set
-RUNEWIDTH_EASTASIAN=0 in your environment.
-
-For details see https://github.com/charmbracelet/lipgloss/issues/40.
-
+This section shows you how to do exactly that.
-
-Why isn't Lip Gloss displaying colors?
-
-Lip Gloss automatically degrades colors to the best available option in the
-given terminal, and if output's not a TTY it will remove color output entirely.
-This is common when running tests, CI, or when piping output elsewhere.
+Migrating from v1?
-If necessary, you can force a color profile in your tests with
-SetColorProfile.
+The `compat` package provides `AdaptiveColor`, `CompleteColor`, and
+`CompleteAdaptiveColor` for a quicker migration from v1. These work by
+looking at `stdin` and `stdout` on a global basis:
```go
-import (
- "github.com/charmbracelet/lipgloss"
- "github.com/muesli/termenv"
-)
+import "charm.land/lipgloss/v2/compat"
-lipgloss.SetColorProfile(termenv.TrueColor)
+color := compat.AdaptiveColor{
+ Light: lipgloss.Color("#f1f1f1"),
+ Dark: lipgloss.Color("#cccccc"),
+}
```
-_Note:_ this option limits the flexibility of your application and can cause
-ANSI escape codes to be output in cases where that might not be desired. Take
-careful note of your use case and environment before choosing to force a color
-profile.
+Note that we don't recommend this for new code as it removes the purity from
+Lip Gloss, computationally speaking, as it removes transparency around when
+I/O happens, which could cause Lip Gloss to compete for resources (like stdin)
+with other tools.
+### Adaptive Colors
+
+You can render different colors at runtime depending on whether the terminal
+has a light or dark background:
+
+```go
+hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+lightDark := lipgloss.LightDark(hasDarkBG)
+
+myColor := lightDark(lipgloss.Color("#D7FFAE"), lipgloss.Color("#D75FEE"))
+```
+
+#### With Bubble Tea
+
+In Bubble Tea, request the background color, listen for a
+`BackgroundColorMsg`, and respond accordingly:
+
+```go
+func (m model) Init() tea.Cmd {
+ // First, send a Cmd to request the terminal background color.
+ return tea.RequestBackgroundColor
+}
+
+func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+ switch msg := msg.(type) {
+ case tea.BackgroundColorMsg:
+ // Great, we have the background color. Now we can set up our styles
+ // against the color.
+ m.styles = newStyles(msg.IsDark())
+ return m, nil
+ }
+}
+
+func newStyles(bgIsDark bool) styles {
+ // A little ternary function that will return the appropriate color
+ // based on the background color.
+ lightDark := lipgloss.LightDark(bgIsDark)
+
+ return styles{
+ myHotStyle: lipgloss.NewStyle().Foreground(lightDark(
+ lipgloss.Color("#f1f1f1"),
+ lipgloss.Color("#333333"),
+ )),
+ }
+}
+```
+
+#### Standalone
+
+If you’re not using Bubble Tea you can perform the query manually:
+
+```go
+// What's the background color?
+hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stderr)
+
+// A helper function that will return the appropriate color based on the
+// background.
+lightDark := lipgloss.LightDark(hasDarkBG)
+
+// A couple colors with light and dark variants.
+thisColor := lightDark(lipgloss.Color("#C5ADF9"), lipgloss.Color("#864EFF"))
+thatColor := lightDark(lipgloss.Color("#37CD96"), lipgloss.Color("#22C78A"))
+
+a := lipgloss.NewStyle().Foreground(thisColor).Render("this")
+b := lipgloss.NewStyle().Foreground(thatColor).Render("that")
+
+// Render the appropriate colors at runtime:
+lipgloss.Fprintf(os.Stderr, "my fave colors are %s and %s", a, b)
+```
+
+### Complete Colors
+
+In some cases where you may want to specify exact values for each color profile
+(ANSI 16, ANSI 156, and TrueColor). For these cases, use the `Complete` helper:
+
+```go
+// You'll need the colorprofile package.
+import "github.com/charmbracelet/colorprofile"
+
+// Get the color profile.
+profile := colorprofile.Detect(os.Stdout, os.Environ())
+
+// Create a function for rendering the appropriate color based on the profile.
+var completeColor := lipgloss.Complete(profile)
+
+// Now we'll choose the appropriate color at runtime.
+myColor := completeColor(ansiColor, ansi256Color, trueColor)
+```
+
+### Color Downsampling
+
+One of the best things about Lip Gloss is that it can automatically downsample
+colors to the best available profile, stripping colors (and ANSI) entirely when
+output is not a TTY.
+
+If you’re using Lip Gloss with Bubble Tea there’s nothing to do here:
+downsampling is built into Bubble Tea v2. If you’re not using Bubble Tea, use
+the Lip Gloss writer functions, which are a drop-in replacement for the `fmt`
+package:
+
+```go
+s := lipgloss.NewStyle()
+ .Foreground(lipgloss.Color("#EB4268"))
+ .Render("Hello!")
+
+// Downsample if needed and print to stdout.
+lipgloss.Println(s)
+
+// Render to a variable.
+downsampled := lipgloss.Sprint(s)
+
+// Print to stderr.
+lipgloss.Fprint(os.Stderr, s)
+```
+
+The full set: `Print`, `Println`, `Printf`, `Fprint`, `Fprintln`, `Fprintf`,
+`Sprint`, `Sprintln`, `Sprintf`.
+
+Need more control? Check out
+[Colorprofile](https://github.com/charmbracelet/colorprofile), which Lip Gloss
+uses under the hood.
+
## What about [Bubble Tea][tea]?
Lip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea
@@ -765,16 +958,7 @@ instead of concerning yourself with low-level layout details.
In simple terms, you can use Lip Gloss to help build your Bubble Tea views.
-[tea]: https://github.com/charmbracelet/tea
-
-## Under the Hood
-
-Lip Gloss is built on the excellent [Termenv][termenv] and [Reflow][reflow]
-libraries which deal with color and ANSI-aware text operations, respectively.
-For many use cases Termenv and Reflow will be sufficient for your needs.
-
-[termenv]: https://github.com/muesli/termenv
-[reflow]: https://github.com/muesli/reflow
+[tea]: https://github.com/charmbracelet/bubbletea
## Rendering Markdown
@@ -794,9 +978,8 @@ See [contributing][contribute].
We’d love to hear your thoughts on this project. Feel free to drop us a note!
-- [Twitter](https://twitter.com/charmcli)
-- [The Fediverse](https://mastodon.social/@charmcli)
-- [Discord](https://charm.sh/chat)
+- [Discord](https://charm.land/chat)
+- [Matrix](https://charm.land/matrix)
## License
@@ -804,12 +987,10 @@ We’d love to hear your thoughts on this project. Feel free to drop us a note!
---
-Part of [Charm](https://charm.sh).
+Part of [Charm](https://charm.land).
-
+
Charm热爱开源 • Charm loves open source
-[docs]: https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc
-[wish]: https://github.com/charmbracelet/wish
-[ssh-example]: examples/ssh
+[docs]: https://pkg.go.dev/charm.land/lipgloss/v2?tab=doc
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml b/hack/tools/vendor/charm.land/lipgloss/v2/Taskfile.yaml
similarity index 72%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml
rename to hack/tools/vendor/charm.land/lipgloss/v2/Taskfile.yaml
index 0b4a7711a87..84fcf6c66bf 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/Taskfile.yaml
@@ -1,6 +1,6 @@
# https://taskfile.dev
-version: '3'
+version: "3"
tasks:
lint:
@@ -17,3 +17,8 @@ tasks:
desc: Run table tests
cmds:
- go test ./table {{.CLI_ARGS}}
+
+ test:tree:
+ desc: Run tree tests
+ cmds:
+ - go test ./tree {{.CLI_ARGS}}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md b/hack/tools/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md
new file mode 100644
index 00000000000..8f123f19df9
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md
@@ -0,0 +1,504 @@
+# Lip Gloss v2 Upgrade Guide
+
+This guide covers migrating from Lip Gloss v1 (`github.com/charmbracelet/lipgloss`)
+to Lip Gloss v2 (`charm.land/lipgloss/v2`). It is written for both humans and
+LLMs performing automated migrations.
+
+---
+
+## Table of Contents
+
+1. [Quick Start](#quick-start)
+2. [Module Path](#module-path)
+3. [Color System](#color-system)
+4. [Renderer Removal](#renderer-removal)
+5. [Printing and Color Downsampling](#printing-and-color-downsampling)
+6. [Background Detection and Adaptive Colors](#background-detection-and-adaptive-colors)
+7. [Whitespace Options](#whitespace-options)
+8. [Underline](#underline)
+9. [Style API Changes](#style-api-changes)
+10. [Tree Subpackage](#tree-subpackage)
+11. [Removed APIs](#removed-apis)
+12. [Quick Reference Table](#quick-reference-table)
+
+---
+
+## Quick Start
+
+For the fastest possible upgrade, do these two things:
+
+### 1. Use the `compat` package for adaptive/complete colors
+
+```go
+import "charm.land/lipgloss/v2/compat"
+
+// v1
+color := lipgloss.AdaptiveColor{Light: "#f1f1f1", Dark: "#cccccc"}
+
+// v2
+color := compat.AdaptiveColor{Light: lipgloss.Color("#f1f1f1"), Dark: lipgloss.Color("#cccccc")}
+```
+
+The `compat` package reads `stdin`/`stdout` globally, just like v1. To
+customize:
+
+```go
+import (
+ "charm.land/lipgloss/v2/compat"
+ "github.com/charmbracelet/colorprofile"
+)
+
+func init() {
+ compat.HasDarkBackground = lipgloss.HasDarkBackground(os.Stdin, os.Stderr)
+ compat.Profile = colorprofile.Detect(os.Stderr, os.Environ())
+}
+```
+
+### 2. Use Lip Gloss writers for output
+
+```go
+// v1
+fmt.Println(s)
+
+// v2
+lipgloss.Println(s)
+```
+
+This ensures colors are automatically downsampled. If you're using Bubble Tea
+v2, this step is unnecessary — Bubble Tea handles it for you.
+
+**That's the quick path.** Read on for the full migration details.
+
+---
+
+## Module Path
+
+The import path has changed.
+
+```go
+// v1
+import "github.com/charmbracelet/lipgloss"
+
+// v2
+import "charm.land/lipgloss/v2"
+```
+
+**Install:**
+
+```bash
+go get charm.land/lipgloss/v2
+```
+
+All subpackages follow the same pattern:
+
+```go
+// v1
+import "github.com/charmbracelet/lipgloss/table"
+import "github.com/charmbracelet/lipgloss/tree"
+import "github.com/charmbracelet/lipgloss/list"
+
+// v2
+import "charm.land/lipgloss/v2/table"
+import "charm.land/lipgloss/v2/tree"
+import "charm.land/lipgloss/v2/list"
+```
+
+**Search-and-replace pattern:**
+
+```
+github.com/charmbracelet/lipgloss → charm.land/lipgloss/v2
+```
+
+---
+
+## Color System
+
+This is the most significant API change.
+
+### `Color` is now a function, not a type
+
+```go
+// v1 — Color is a string type
+var c lipgloss.Color = "21"
+var c lipgloss.Color = "#ff00ff"
+
+// v2 — Color is a function returning color.Color
+var c color.Color = lipgloss.Color("21")
+var c color.Color = lipgloss.Color("#ff00ff")
+```
+
+The return type is `image/color.Color` (from the standard library).
+
+### `TerminalColor` interface is removed
+
+All methods that accepted `lipgloss.TerminalColor` now accept
+`image/color.Color`:
+
+```go
+// v1
+func (s Style) Foreground(c TerminalColor) Style
+func (s Style) Background(c TerminalColor) Style
+func (s Style) BorderForeground(c ...TerminalColor) Style
+
+// v2
+func (s Style) Foreground(c color.Color) Style
+func (s Style) Background(c color.Color) Style
+func (s Style) BorderForeground(c ...color.Color) Style
+```
+
+**Migration:** Replace every `lipgloss.TerminalColor` with `color.Color` and
+add `import "image/color"`.
+
+### `ANSIColor` is now an alias
+
+```go
+// v1 — custom uint type
+type ANSIColor uint
+
+// v2 — alias for ansi.IndexedColor
+type ANSIColor = ansi.IndexedColor
+```
+
+v2 also exports named constants for the 16 basic ANSI colors:
+
+```go
+lipgloss.Black, lipgloss.Red, lipgloss.Green, lipgloss.Yellow,
+lipgloss.Blue, lipgloss.Magenta, lipgloss.Cyan, lipgloss.White,
+lipgloss.BrightBlack, lipgloss.BrightRed, lipgloss.BrightGreen,
+lipgloss.BrightYellow, lipgloss.BrightBlue, lipgloss.BrightMagenta,
+lipgloss.BrightCyan, lipgloss.BrightWhite
+```
+
+### `AdaptiveColor`, `CompleteColor`, `CompleteAdaptiveColor`
+
+These types have been moved out of the root package. Use the `compat` package
+for a drop-in replacement, or use the new `LightDark` and `Complete` helpers
+for explicit control:
+
+```go
+// v1
+color := lipgloss.AdaptiveColor{Light: "#0000ff", Dark: "#000099"}
+
+// v2 — using compat (quick path)
+color := compat.AdaptiveColor{
+ Light: lipgloss.Color("#0000ff"),
+ Dark: lipgloss.Color("#000099"),
+}
+
+// v2 — using LightDark (recommended)
+hasDark := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+lightDark := lipgloss.LightDark(hasDark)
+color := lightDark(lipgloss.Color("#0000ff"), lipgloss.Color("#000099"))
+```
+
+```go
+// v1
+color := lipgloss.CompleteColor{TrueColor: "#ff00ff", ANSI256: "200", ANSI: "5"}
+
+// v2 — using compat
+color := compat.CompleteColor{
+ TrueColor: lipgloss.Color("#ff00ff"),
+ ANSI256: lipgloss.Color("200"),
+ ANSI: lipgloss.Color("5"),
+}
+
+// v2 — using Complete (recommended)
+profile := colorprofile.Detect(os.Stdout, os.Environ())
+complete := lipgloss.Complete(profile)
+color := complete(lipgloss.Color("5"), lipgloss.Color("200"), lipgloss.Color("#ff00ff"))
+```
+
+Note that `compat.AdaptiveColor` and friends take `color.Color` values for
+their fields, not strings.
+
+---
+
+## Renderer Removal
+
+The `Renderer` type and all associated functions are removed. In v1, every
+`Style` carried a `*Renderer` pointer and the package maintained a global
+default renderer.
+
+```go
+// v1 — these no longer exist
+lipgloss.DefaultRenderer()
+lipgloss.SetDefaultRenderer(r)
+lipgloss.NewRenderer(w, opts...)
+lipgloss.ColorProfile()
+lipgloss.SetColorProfile(p)
+renderer.NewStyle()
+```
+
+**In v2, `Style` is a plain value type.** There is no renderer. Color
+downsampling is handled at the output layer (see next section).
+
+**Migration:**
+
+- Replace `lipgloss.DefaultRenderer().NewStyle()` with `lipgloss.NewStyle()`.
+- Replace `renderer.NewStyle()` with `lipgloss.NewStyle()`.
+- Remove any `*Renderer` fields from your types.
+- Remove calls to `SetColorProfile` — use `colorprofile.Detect` at the output
+ layer instead.
+
+---
+
+## Printing and Color Downsampling
+
+In v1, color downsampling happened inside `Style.Render()` via the renderer. In
+v2, `Render()` always emits full-fidelity ANSI. Downsampling happens when you
+print.
+
+### Standalone Usage
+
+Use the Lip Gloss writer functions:
+
+```go
+s := someStyle.Render("Hello!")
+
+// Print to stdout with automatic downsampling
+lipgloss.Println(s)
+
+// Print to stderr
+lipgloss.Fprintln(os.Stderr, s)
+
+// Render to a string (downsampled for stdout's profile)
+str := lipgloss.Sprint(s)
+```
+
+The default writer targets `stdout`. To customize:
+
+```go
+lipgloss.Writer = colorprofile.NewWriter(os.Stderr, os.Environ())
+```
+
+### With Bubble Tea
+
+No changes needed. Bubble Tea v2 handles downsampling internally.
+
+---
+
+## Background Detection and Adaptive Colors
+
+### Standalone
+
+v1 detected the background color automatically via the global renderer. v2
+requires explicit queries:
+
+```go
+// v1
+hasDark := lipgloss.HasDarkBackground()
+
+// v2 — specify the input and output
+hasDark := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+```
+
+Then use `LightDark` to pick colors:
+
+```go
+lightDark := lipgloss.LightDark(hasDark)
+fg := lightDark(lipgloss.Color("#333333"), lipgloss.Color("#f1f1f1"))
+
+s := lipgloss.NewStyle().Foreground(fg)
+```
+
+### With Bubble Tea
+
+Request the background color in `Init` and listen for the response:
+
+```go
+func (m model) Init() tea.Cmd {
+ return tea.RequestBackgroundColor
+}
+
+func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+ switch msg := msg.(type) {
+ case tea.BackgroundColorMsg:
+ m.styles = newStyles(msg.IsDark())
+ }
+ // ...
+}
+
+func newStyles(bgIsDark bool) styles {
+ lightDark := lipgloss.LightDark(bgIsDark)
+ return styles{
+ title: lipgloss.NewStyle().Foreground(lightDark(
+ lipgloss.Color("#333333"),
+ lipgloss.Color("#f1f1f1"),
+ )),
+ }
+}
+```
+
+---
+
+## Whitespace Options
+
+The separate foreground/background whitespace options have been replaced by a
+single style option:
+
+```go
+// v1
+lipgloss.Place(width, height, hPos, vPos, str,
+ lipgloss.WithWhitespaceForeground(lipgloss.Color("#333")),
+ lipgloss.WithWhitespaceBackground(lipgloss.Color("#000")),
+)
+
+// v2
+lipgloss.Place(width, height, hPos, vPos, str,
+ lipgloss.WithWhitespaceStyle(lipgloss.NewStyle().
+ Foreground(lipgloss.Color("#333")).
+ Background(lipgloss.Color("#000")),
+ ),
+)
+```
+
+---
+
+## Underline
+
+`Underline(bool)` still works for basic on/off. v2 adds fine-grained control:
+
+```go
+// v1
+s := lipgloss.NewStyle().Underline(true)
+
+// v2 — still works
+s := lipgloss.NewStyle().Underline(true)
+
+// v2 — new: specific styles
+s := lipgloss.NewStyle().UnderlineStyle(lipgloss.UnderlineCurly)
+
+// v2 — new: colored underlines
+s := lipgloss.NewStyle().
+ UnderlineStyle(lipgloss.UnderlineSingle).
+ UnderlineColor(lipgloss.Color("#FF0000"))
+```
+
+Internally, `Underline(true)` is equivalent to `UnderlineStyle(UnderlineSingle)`
+and `Underline(false)` is equivalent to `UnderlineStyle(UnderlineNone)`.
+
+---
+
+## Style API Changes
+
+### `NewStyle()` is no longer tied to a Renderer
+
+```go
+// v1
+s := lipgloss.NewStyle() // uses global renderer
+s := renderer.NewStyle() // uses specific renderer
+
+// v2
+s := lipgloss.NewStyle() // pure value, no renderer
+```
+
+### Color getters return `color.Color`
+
+```go
+// v1
+fg := s.GetForeground() // returns TerminalColor
+
+// v2
+fg := s.GetForeground() // returns color.Color
+```
+
+### New style methods
+
+| Method | Description |
+|---|---|
+| `UnderlineStyle(Underline)` | Set underline style (single, double, curly, etc.) |
+| `UnderlineColor(color.Color)` | Set underline color |
+| `PaddingChar(rune)` | Set the character used for padding fill |
+| `MarginChar(rune)` | Set the character used for margin fill |
+| `Hyperlink(link, params...)` | Set a clickable hyperlink |
+| `BorderForegroundBlend(...color.Color)` | Apply gradient colors to borders |
+| `BorderForegroundBlendOffset(int)` | Set the offset for border gradient |
+
+Each has a corresponding `Get*`, `Unset*`, and where applicable `Get*`
+accessor.
+
+---
+
+## Tree Subpackage
+
+The import path changes and there are new styling options:
+
+```go
+// v1
+import "github.com/charmbracelet/lipgloss/tree"
+
+// v2
+import "charm.land/lipgloss/v2/tree"
+```
+
+New methods:
+
+- `IndenterStyle(lipgloss.Style)` — set a static style for tree indentation.
+- `IndenterStyleFunc(func(Children, int) lipgloss.Style)` — conditionally style
+ indentation.
+- `Width(int)` — set tree width for padding.
+
+---
+
+## Removed APIs
+
+The following types and functions no longer exist in v2. This table shows each
+removed symbol and its replacement.
+
+| v1 Symbol | v2 Replacement |
+|---|---|
+| `type Renderer` | Removed entirely |
+| `DefaultRenderer()` | Not needed |
+| `SetDefaultRenderer(r)` | Not needed |
+| `NewRenderer(w, opts...)` | Not needed |
+| `ColorProfile()` | `colorprofile.Detect(w, env)` |
+| `SetColorProfile(p)` | Set `lipgloss.Writer.Profile` |
+| `HasDarkBackground()` (no args) | `lipgloss.HasDarkBackground(in, out)` |
+| `SetHasDarkBackground(b)` | Not needed — pass bool to `LightDark` |
+| `type TerminalColor` | `image/color.Color` |
+| `type Color string` | `func Color(string) color.Color` |
+| `type ANSIColor uint` | `type ANSIColor = ansi.IndexedColor` |
+| `type AdaptiveColor` | `compat.AdaptiveColor` or `LightDark` |
+| `type CompleteColor` | `compat.CompleteColor` or `Complete` |
+| `type CompleteAdaptiveColor` | `compat.CompleteAdaptiveColor` |
+| `WithWhitespaceForeground(c)` | `WithWhitespaceStyle(s)` |
+| `WithWhitespaceBackground(c)` | `WithWhitespaceStyle(s)` |
+| `renderer.NewStyle()` | `lipgloss.NewStyle()` |
+
+---
+
+## Quick Reference Table
+
+A side-by-side summary for common patterns:
+
+| Task | v1 | v2 |
+|---|---|---|
+| Import | `"github.com/charmbracelet/lipgloss"` | `"charm.land/lipgloss/v2"` |
+| Create style | `lipgloss.NewStyle()` | `lipgloss.NewStyle()` |
+| Hex color | `lipgloss.Color("#ff00ff")` | `lipgloss.Color("#ff00ff")` |
+| ANSI color | `lipgloss.Color("5")` | `lipgloss.Color("5")` or `lipgloss.Magenta` |
+| Adaptive color | `lipgloss.AdaptiveColor{Light: "#fff", Dark: "#000"}` | `compat.AdaptiveColor{Light: lipgloss.Color("#fff"), Dark: lipgloss.Color("#000")}` |
+| Set foreground | `s.Foreground(lipgloss.Color("5"))` | `s.Foreground(lipgloss.Color("5"))` |
+| Print with downsampling | `fmt.Println(s.Render("hi"))` | `lipgloss.Println(s.Render("hi"))` |
+| Detect dark bg | `lipgloss.HasDarkBackground()` | `lipgloss.HasDarkBackground(os.Stdin, os.Stdout)` |
+| Light/dark color | `lipgloss.AdaptiveColor{...}` | `lipgloss.LightDark(isDark)(light, dark)` |
+| Whitespace styling | `WithWhitespaceForeground(c)` | `WithWhitespaceStyle(lipgloss.NewStyle().Foreground(c))` |
+| Underline | `s.Underline(true)` | `s.Underline(true)` or `s.UnderlineStyle(lipgloss.UnderlineCurly)` |
+
+---
+
+## Feedback
+
+Questions, issues, or feedback:
+
+- [Discord](https://charm.land/discord)
+- [Matrix](https://charm.land/matrix)
+- [Email](mailto:vt100@charm.land)
+
+---
+
+Part of [Charm](https://charm.land).
+
+
+
+Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/align.go b/hack/tools/vendor/charm.land/lipgloss/v2/align.go
similarity index 89%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/align.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/align.go
index ce654b232ac..d196213b77b 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/align.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/align.go
@@ -4,13 +4,12 @@ import (
"strings"
"github.com/charmbracelet/x/ansi"
- "github.com/muesli/termenv"
)
// Perform text alignment. If the string is multi-lined, we also make all lines
-// the same width by padding them with spaces. If a termenv style is passed,
-// use that to style the spaces added.
-func alignTextHorizontal(str string, pos Position, width int, style *termenv.Style) string {
+// the same width by padding them with spaces. If a style is passed, use that
+// to style the spaces added.
+func alignTextHorizontal(str string, pos Position, width int, style *ansi.Style) string {
lines, widestLine := getLines(str)
var b strings.Builder
@@ -21,7 +20,7 @@ func alignTextHorizontal(str string, pos Position, width int, style *termenv.Sty
shortAmount += max(0, width-(shortAmount+lineWidth)) // difference from the total width, if set
if shortAmount > 0 {
- switch pos { //nolint:exhaustive
+ switch pos {
case Right:
s := strings.Repeat(" ", shortAmount)
if style != nil {
@@ -59,7 +58,7 @@ func alignTextHorizontal(str string, pos Position, width int, style *termenv.Sty
return b.String()
}
-func alignTextVertical(str string, pos Position, height int, _ *termenv.Style) string {
+func alignTextVertical(str string, pos Position, height int, _ *ansi.Style) string {
strHeight := strings.Count(str, "\n") + 1
if height < strHeight {
return str
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/ansi_unix.go b/hack/tools/vendor/charm.land/lipgloss/v2/ansi_unix.go
new file mode 100644
index 00000000000..b4fca7d197c
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/ansi_unix.go
@@ -0,0 +1,8 @@
+//go:build !windows
+
+package lipgloss
+
+import "os"
+
+// EnableLegacyWindowsANSI is only needed on Windows.
+func EnableLegacyWindowsANSI(*os.File) {}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/ansi_windows.go b/hack/tools/vendor/charm.land/lipgloss/v2/ansi_windows.go
new file mode 100644
index 00000000000..8a1ef00eba7
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/ansi_windows.go
@@ -0,0 +1,30 @@
+//go:build windows
+
+package lipgloss
+
+import (
+ "os"
+
+ "golang.org/x/sys/windows"
+)
+
+// EnableLegacyWindowsANSI enables support for ANSI color sequences in the
+// Windows default console (cmd.exe and the PowerShell application). Note that
+// this only works with Windows 10 and greater. Also note that Windows Terminal
+// supports colors by default.
+func EnableLegacyWindowsANSI(f *os.File) {
+ var mode uint32
+ handle := windows.Handle(f.Fd())
+ err := windows.GetConsoleMode(handle, &mode)
+ if err != nil {
+ return
+ }
+
+ // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
+ vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
+ if err := windows.SetConsoleMode(handle, vtpmode); err != nil {
+ return
+ }
+ }
+}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/blending.go b/hack/tools/vendor/charm.land/lipgloss/v2/blending.go
new file mode 100644
index 00000000000..82830f3e4c5
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/blending.go
@@ -0,0 +1,196 @@
+package lipgloss
+
+import (
+ "image/color"
+ "math"
+ "slices"
+
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+// Blend1D blends a series of colors together in one linear dimension using multiple
+// stops, into the provided number of steps. Uses the "CIE L*, a*, b*" (CIELAB) color-space.
+//
+// Note that if any of the provided colors are completely transparent, we will
+// assume that the alpha value was lost in conversion from RGB -> RGBA, and we
+// will set the alpha to opaque, as it's not possible to blend something completely
+// transparent.
+func Blend1D(steps int, stops ...color.Color) []color.Color {
+ if steps < 0 {
+ steps = 0
+ }
+
+ if steps <= len(stops) {
+ return stops[:steps]
+ }
+
+ // Ensure they didn't provide any nil colors.
+ stops = slices.DeleteFunc(stops, func(c color.Color) bool {
+ return c == nil
+ })
+
+ if len(stops) == 0 {
+ return nil // We can't safely fallback.
+ }
+
+ // If they only provided one valid color (or some nil colors), we will just return
+ // an array of that color, for the amount of steps they requested.
+ if len(stops) == 1 {
+ singleColor := stops[0]
+ result := make([]color.Color, steps)
+ for i := range result {
+ result[i] = singleColor
+ }
+ return result
+ }
+
+ blended := make([]color.Color, steps)
+
+ // Convert stops to colorful.Color once
+ cstops := make([]colorful.Color, len(stops))
+ for i, k := range stops {
+ cstops[i], _ = colorful.MakeColor(ensureNotTransparent(k))
+ }
+
+ numSegments := len(cstops) - 1
+ defaultSize := steps / numSegments
+ remainingSteps := steps % numSegments
+
+ resultIndex := 0
+ for i := range numSegments {
+ from := cstops[i]
+ to := cstops[i+1]
+
+ // Calculate segment size.
+ segmentSize := defaultSize
+ if i < remainingSteps {
+ segmentSize++
+ }
+
+ divisor := float64(segmentSize - 1)
+
+ // Generate colors for this segment.
+ for j := 0; j < segmentSize; j++ {
+ var blendingFactor float64
+ if segmentSize > 1 {
+ blendingFactor = float64(j) / divisor
+ }
+ blended[resultIndex] = from.BlendLab(to, blendingFactor).Clamped()
+ resultIndex++
+ }
+ }
+
+ return blended
+}
+
+// Blend2D blends a series of colors together in two linear dimensions using
+// multiple stops, into the provided width/height. Uses the "CIE L*, a*, b*" (CIELAB)
+// color-space. The angle parameter controls the rotation of the gradient (0-360°),
+// where 0° is left-to-right, 45° is bottom-left to top-right (diagonal). The function
+// returns colors in a 1D row-major order ([row1, row2, row3, ...]).
+//
+// Example of how to iterate over the result:
+//
+// gradient := colors.Blend2D(width, height, 180, color1, color2, color3, ...)
+// gradientContent := strings.Builder{}
+// for y := range height {
+// for x := range width {
+// index := y*width + x
+// gradientContent.WriteString(
+// lipgloss.NewStyle().
+// Background(gradient[index]).
+// Render(" "),
+// )
+// }
+// if y < height-1 { // End of row.
+// gradientContent.WriteString("\n")
+// }
+// }
+//
+// Note that if any of the provided colors are completely transparent, we will
+// assume that the alpha value was lost in conversion from RGB -> RGBA, and we
+// will set the alpha to opaque, as it's not possible to blend something completely
+// transparent.
+func Blend2D(width, height int, angle float64, stops ...color.Color) []color.Color {
+ if width < 1 {
+ width = 1
+ }
+ if height < 1 {
+ height = 1
+ }
+
+ // Normalize angle to 0-360.
+ angle = math.Mod(angle, 360)
+ if angle < 0 {
+ angle += 360
+ }
+
+ // Ensure they didn't provide any nil colors.
+ stops = slices.DeleteFunc(stops, func(c color.Color) bool {
+ return c == nil
+ })
+
+ if len(stops) == 0 {
+ return nil // We can't safely fallback.
+ }
+
+ // If they only provided one valid color (or some nil colors), we will just return
+ // an array of that color, for the amount of pixels they requested.
+ if len(stops) == 1 {
+ singleColor := stops[0]
+ result := make([]color.Color, width*height)
+ for i := range result {
+ result[i] = singleColor
+ }
+ return result
+ }
+
+ // For 2D blending, we'll create a gradient along the diagonal and then sample
+ // from it based on the angle. We'll use the maximum dimension to ensure we have
+ // enough resolution for the gradient.
+ diagonalGradient := Blend1D(max(width, height), stops...)
+
+ result := make([]color.Color, width*height)
+
+ // Calculate center point for rotation.
+ centerX := float64(width-1) / 2.0
+ centerY := float64(height-1) / 2.0
+
+ angleRad := angle * math.Pi / 180.0 // -> radians.
+
+ // Pre-calculate sin and cos.
+ cosAngle := math.Cos(angleRad)
+ sinAngle := math.Sin(angleRad)
+
+ // Calculate diagonal length for proper gradient mapping.
+ diagonalLength := math.Sqrt(float64(width*width + height*height))
+
+ // Pre-calculate gradient length for index calculation.
+ gradientLen := float64(len(diagonalGradient) - 1)
+
+ for y := range height {
+ // Calculate the distance from center along the gradient direction.
+ dy := float64(y) - centerY
+
+ for x := 0; x < width; x++ {
+ // Calculate the distance from center along the gradient direction.
+ dx := float64(x) - centerX
+
+ rotX := dx*cosAngle - dy*sinAngle // Rotate the point by the angle.
+
+ // Map the rotated position to the gradient. Normalize to 0-1 range based on
+ // the diagonal length.
+ gradientPos := clamp((rotX+diagonalLength/2.0)/diagonalLength, 0, 1)
+
+ // Calculate the index in the gradient.
+ gradientIndex := int(gradientPos * gradientLen)
+ if gradientIndex >= len(diagonalGradient) {
+ gradientIndex = len(diagonalGradient) - 1
+ }
+
+ result[y*width+x] = diagonalGradient[gradientIndex] // -> row-major order.
+ }
+ }
+
+ return result
+}
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/borders.go b/hack/tools/vendor/charm.land/lipgloss/v2/borders.go
similarity index 73%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/borders.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/borders.go
index b36f874388a..7f12360f627 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/borders.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/borders.go
@@ -1,10 +1,13 @@
package lipgloss
import (
+ "image/color"
+ "slices"
"strings"
+ "unicode/utf8"
"github.com/charmbracelet/x/ansi"
- "github.com/muesli/termenv"
+ "github.com/clipperhouse/displaywidth"
"github.com/rivo/uniseg"
)
@@ -56,10 +59,7 @@ func (b Border) GetLeftSize() int {
func getBorderEdgeWidth(borderParts ...string) (maxWidth int) {
for _, piece := range borderParts {
- w := maxRuneWidth(piece)
- if w > maxWidth {
- maxWidth = w
- }
+ maxWidth = max(maxWidth, maxRuneWidth(piece))
}
return maxWidth
}
@@ -278,6 +278,52 @@ func ASCIIBorder() Border {
return asciiBorder
}
+type borderBlend struct {
+ topGradient []color.Color
+ rightGradient []color.Color
+ bottomGradient []color.Color
+ leftGradient []color.Color
+}
+
+func (s Style) borderBlend(width, height int, colors ...color.Color) *borderBlend {
+ gradient := Blend1D(
+ (height+width+2)*2,
+ colors...,
+ )
+
+ // Rotate array forward or reverse based on the offset if provided.
+ if r := -s.getAsInt(borderForegroundBlendOffsetKey); r != 0 {
+ n := len(gradient)
+ r %= n
+ if r < 0 {
+ r += n
+ }
+ slices.Reverse(gradient[:r])
+ slices.Reverse(gradient[r:])
+ slices.Reverse(gradient)
+ }
+
+ offset := 0
+ getFromOffset := func(size int) (s []color.Color) {
+ s = gradient[offset : offset+size]
+ offset += size
+ return s
+ }
+
+ blend := &borderBlend{
+ topGradient: getFromOffset(width + 2),
+ rightGradient: getFromOffset(height),
+ bottomGradient: getFromOffset(width + 2),
+ leftGradient: getFromOffset(height),
+ }
+
+ // bottom and left gradients are reversed because they are drawn in reverse order.
+ slices.Reverse(blend.bottomGradient)
+ slices.Reverse(blend.leftGradient)
+
+ return blend
+}
+
func (s Style) applyBorder(str string) string {
var (
border = s.getBorderStyle()
@@ -285,21 +331,11 @@ func (s Style) applyBorder(str string) string {
hasRight = s.getAsBool(borderRightKey, false)
hasBottom = s.getAsBool(borderBottomKey, false)
hasLeft = s.getAsBool(borderLeftKey, false)
-
- topFG = s.getAsColor(borderTopForegroundKey)
- rightFG = s.getAsColor(borderRightForegroundKey)
- bottomFG = s.getAsColor(borderBottomForegroundKey)
- leftFG = s.getAsColor(borderLeftForegroundKey)
-
- topBG = s.getAsColor(borderTopBackgroundKey)
- rightBG = s.getAsColor(borderRightBackgroundKey)
- bottomBG = s.getAsColor(borderBottomBackgroundKey)
- leftBG = s.getAsColor(borderLeftBackgroundKey)
)
// If a border is set and no sides have been specifically turned on or off
// render borders on all sides.
- if s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
hasTop = true
hasRight = true
hasBottom = true
@@ -320,8 +356,11 @@ func (s Style) applyBorder(str string) string {
width += maxRuneWidth(border.Left)
}
- if hasRight && border.Right == "" {
- border.Right = " "
+ if hasRight {
+ if border.Right == "" {
+ border.Right = " "
+ }
+ width += maxRuneWidth(border.Right)
}
// If corners should be rendered but are set with the empty string, fill them
@@ -370,13 +409,35 @@ func (s Style) applyBorder(str string) string {
border.BottomRight = getFirstRuneAsString(border.BottomRight)
border.BottomLeft = getFirstRuneAsString(border.BottomLeft)
+ var topFG, rightFG, bottomFG, leftFG color.Color
+ var (
+ blendFG = s.getAsColors(borderForegroundBlendKey)
+ topBG = s.getAsColor(borderTopBackgroundKey)
+ rightBG = s.getAsColor(borderRightBackgroundKey)
+ bottomBG = s.getAsColor(borderBottomBackgroundKey)
+ leftBG = s.getAsColor(borderLeftBackgroundKey)
+ )
+
+ var blend *borderBlend
+ if len(blendFG) > 0 {
+ blend = s.borderBlend(width, len(lines), blendFG...)
+ } else {
+ topFG = s.getAsColor(borderTopForegroundKey)
+ rightFG = s.getAsColor(borderRightForegroundKey)
+ bottomFG = s.getAsColor(borderBottomForegroundKey)
+ leftFG = s.getAsColor(borderLeftForegroundKey)
+ }
+
var out strings.Builder
// Render top
if hasTop {
top := renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width)
- top = s.styleBorder(top, topFG, topBG)
- out.WriteString(top)
+ if blend != nil {
+ out.WriteString(s.styleBorderBlend(top, blend.topGradient, topBG))
+ } else {
+ out.WriteString(s.styleBorder(top, topFG, topBG))
+ }
out.WriteRune('\n')
}
@@ -387,23 +448,32 @@ func (s Style) applyBorder(str string) string {
rightIndex := 0
// Render sides
+ var r string
for i, l := range lines {
if hasLeft {
- r := string(leftRunes[leftIndex])
+ r = string(leftRunes[leftIndex])
leftIndex++
if leftIndex >= len(leftRunes) {
leftIndex = 0
}
- out.WriteString(s.styleBorder(r, leftFG, leftBG))
+ if blend != nil {
+ out.WriteString(s.styleBorder(r, blend.leftGradient[i], leftBG))
+ } else {
+ out.WriteString(s.styleBorder(r, leftFG, leftBG))
+ }
}
out.WriteString(l)
if hasRight {
- r := string(rightRunes[rightIndex])
+ r = string(rightRunes[rightIndex])
rightIndex++
if rightIndex >= len(rightRunes) {
rightIndex = 0
}
- out.WriteString(s.styleBorder(r, rightFG, rightBG))
+ if blend != nil {
+ out.WriteString(s.styleBorder(r, blend.rightGradient[i], rightBG))
+ } else {
+ out.WriteString(s.styleBorder(r, rightFG, rightBG))
+ }
}
if i < len(lines)-1 {
out.WriteRune('\n')
@@ -413,9 +483,12 @@ func (s Style) applyBorder(str string) string {
// Render bottom
if hasBottom {
bottom := renderHorizontalEdge(border.BottomLeft, border.Bottom, border.BottomRight, width)
- bottom = s.styleBorder(bottom, bottomFG, bottomBG)
out.WriteRune('\n')
- out.WriteString(bottom)
+ if blend != nil {
+ out.WriteString(s.styleBorderBlend(bottom, blend.bottomGradient, bottomBG))
+ } else {
+ out.WriteString(s.styleBorder(bottom, bottomFG, bottomBG))
+ }
}
return out.String()
@@ -435,49 +508,73 @@ func renderHorizontalEdge(left, middle, right string, width int) string {
out := strings.Builder{}
out.WriteString(left)
- for i := leftWidth + rightWidth; i < width+rightWidth; {
- out.WriteRune(runes[j])
+
+ for i := 0; i < width-leftWidth-rightWidth; {
+ r := runes[j]
+ out.WriteRune(r)
+ i += ansi.StringWidth(string(r))
j++
if j >= len(runes) {
j = 0
}
- i += ansi.StringWidth(string(runes[j]))
}
- out.WriteString(right)
+ out.WriteString(right)
return out.String()
}
-// Apply foreground and background styling to a border.
-func (s Style) styleBorder(border string, fg, bg TerminalColor) string {
+// styleBorder applies foreground and background styling to a border.
+func (s Style) styleBorder(border string, fg, bg color.Color) string {
if fg == noColor && bg == noColor {
return border
}
-
- style := termenv.Style{}
-
+ var style ansi.Style
if fg != noColor {
- style = style.Foreground(fg.color(s.r))
+ style = style.ForegroundColor(fg)
}
if bg != noColor {
- style = style.Background(bg.color(s.r))
+ style = style.BackgroundColor(bg)
}
-
return style.Styled(border)
}
+// styleBorderBlend applies foreground and background styling to a border, using blending.
+func (s Style) styleBorderBlend(border string, fg []color.Color, bg color.Color) string {
+ var out strings.Builder
+ var style ansi.Style
+ var i int
+
+ gr := uniseg.NewGraphemes(border)
+ for gr.Next() {
+ style = style[:0]
+ if fg[i] != noColor {
+ style = style.ForegroundColor(fg[i])
+ }
+ if bg != noColor {
+ style = style.BackgroundColor(bg)
+ }
+ _, _ = out.WriteString(style.String())
+ _, _ = out.Write(gr.Bytes())
+ i++
+ }
+ _, _ = out.WriteString(ansi.ResetStyle)
+ return out.String()
+}
+
func maxRuneWidth(str string) int {
+ switch len(str) {
+ case 0:
+ return 0
+ case 1:
+ return displaywidth.String(str)
+ }
+
var width int
- state := -1
- for len(str) > 0 {
- var w int
- _, str, w, state = uniseg.FirstGraphemeClusterInString(str, state)
- if w > width {
- width = w
- }
+ g := displaywidth.StringGraphemes(str)
+ for g.Next() {
+ width = max(width, g.Width())
}
-
return width
}
@@ -485,6 +582,6 @@ func getFirstRuneAsString(str string) string {
if str == "" {
return str
}
- r := []rune(str)
- return string(r[0])
+ _, size := utf8.DecodeRuneInString(str)
+ return str[:size]
}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/canvas.go b/hack/tools/vendor/charm.land/lipgloss/v2/canvas.go
new file mode 100644
index 00000000000..396defb8bde
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/canvas.go
@@ -0,0 +1,88 @@
+package lipgloss
+
+import (
+ uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/x/ansi"
+)
+
+// Canvas is a cell-buffer that can be used to compose and draw [uv.Drawable]s
+// like [Layer]s.
+//
+// Composed drawables are drawn onto the canvas in the order they were
+// composed, meaning later drawables will appear "on top" of earlier ones.
+//
+// A canvas can read, modify, and render its cell contents.
+//
+// It implements [uv.Screen] and [uv.Drawable].
+type Canvas struct {
+ scr uv.ScreenBuffer
+}
+
+var _ uv.Screen = (*Canvas)(nil)
+
+// NewCanvas creates a new [Canvas] with the given size.
+func NewCanvas(width, height int) *Canvas {
+ c := new(Canvas)
+ c.scr = uv.NewScreenBuffer(width, height)
+ c.scr.Method = ansi.GraphemeWidth
+ return c
+}
+
+// Resize resizes the canvas to the given width and height.
+func (c *Canvas) Resize(width, height int) {
+ c.scr.Resize(width, height)
+}
+
+// Clear clears the canvas.
+func (c *Canvas) Clear() {
+ c.scr.Clear()
+}
+
+// Bounds implements [uv.Screen].
+func (c *Canvas) Bounds() uv.Rectangle {
+ return c.scr.Bounds()
+}
+
+// Width returns the width of the canvas.
+func (c *Canvas) Width() int {
+ return c.scr.Width()
+}
+
+// Height returns the height of the canvas.
+func (c *Canvas) Height() int {
+ return c.scr.Height()
+}
+
+// CellAt implements [uv.Screen].
+func (c *Canvas) CellAt(x int, y int) *uv.Cell {
+ return c.scr.CellAt(x, y)
+}
+
+// SetCell implements [uv.Screen].
+func (c *Canvas) SetCell(x int, y int, cell *uv.Cell) {
+ c.scr.SetCell(x, y, cell)
+}
+
+// WidthMethod implements [uv.Screen].
+func (c *Canvas) WidthMethod() uv.WidthMethod {
+ return c.scr.WidthMethod()
+}
+
+// Compose composes a [Layer] or any [uv.Drawable] onto the [Canvas].
+func (c *Canvas) Compose(drawer uv.Drawable) *Canvas {
+ drawer.Draw(c, c.Bounds())
+ return c
+}
+
+// Draw draws the [Canvas] onto the given [uv.Screen] within the specified
+// area.
+//
+// It implements [uv.Drawable].
+func (c *Canvas) Draw(scr uv.Screen, area uv.Rectangle) {
+ c.scr.Draw(scr, area)
+}
+
+// Render renders the canvas into a styled string.
+func (c *Canvas) Render() string {
+ return c.scr.Render()
+}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/color.go b/hack/tools/vendor/charm.land/lipgloss/v2/color.go
new file mode 100644
index 00000000000..7443dc10bb0
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/color.go
@@ -0,0 +1,359 @@
+package lipgloss
+
+import (
+ "cmp"
+ "errors"
+ "image/color"
+ "strconv"
+ "strings"
+
+ "github.com/charmbracelet/colorprofile"
+ "github.com/charmbracelet/x/ansi"
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+func clamp[T cmp.Ordered](v, low, high T) T {
+ if high < low {
+ high, low = low, high
+ }
+ return min(high, max(low, v))
+}
+
+// 4-bit color constants.
+const (
+ Black ansi.BasicColor = iota
+ Red
+ Green
+ Yellow
+ Blue
+ Magenta
+ Cyan
+ White
+
+ BrightBlack
+ BrightRed
+ BrightGreen
+ BrightYellow
+ BrightBlue
+ BrightMagenta
+ BrightCyan
+ BrightWhite
+)
+
+var noColor = NoColor{}
+
+// NoColor is used to specify the absence of color styling. When this is active
+// foreground colors will be rendered with the terminal's default text color,
+// and background colors will not be drawn at all.
+//
+// Example usage:
+//
+// var style = someStyle.Background(lipgloss.NoColor{})
+type NoColor struct{}
+
+// RGBA returns the RGBA value of this color. Because we have to return
+// something, despite this color being the absence of color, we're returning
+// black with 100% opacity.
+//
+// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF.
+func (n NoColor) RGBA() (r, g, b, a uint32) {
+ return 0x0, 0x0, 0x0, 0xFFFF //nolint:mnd
+}
+
+// Color specifies a color by hex or ANSI256 value. For example:
+//
+// ansiColor := lipgloss.Color("1") // The same as lipgloss.Red
+// ansi256Color := lipgloss.Color("21")
+// hexColor := lipgloss.Color("#0000ff")
+func Color(s string) color.Color {
+ if strings.HasPrefix(s, "#") {
+ c, err := parseHex(s)
+ if err != nil {
+ return noColor
+ }
+ return c
+ }
+
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ return noColor
+ }
+
+ if i < 0 {
+ // Only positive numbers
+ i = -i
+ }
+
+ if i < 16 {
+ return ansi.BasicColor(i) //nolint:gosec
+ } else if i < 256 {
+ return ANSIColor(i) //nolint:gosec
+ }
+
+ r, g, b := uint8((i>>16)&0xff), uint8(i>>8&0xff), uint8(i&0xff) //nolint:gosec
+ return color.RGBA{R: r, G: g, B: b, A: 0xff}
+}
+
+var errInvalidFormat = errors.New("invalid hex format") // pre-allocated.
+
+// parseHex parses a hex color string and returns a color.RGBA. The string can be
+// in the format #RRGGBB or #RGB. This is a more performant implementation of
+// [colorful.Hex].
+func parseHex(s string) (c color.RGBA, err error) {
+ c.A = 0xff
+
+ if len(s) == 0 || s[0] != '#' {
+ return c, errInvalidFormat
+ }
+
+ hexToByte := func(b byte) byte {
+ switch {
+ case b >= '0' && b <= '9':
+ return b - '0'
+ case b >= 'a' && b <= 'f':
+ return b - 'a' + 10
+ case b >= 'A' && b <= 'F':
+ return b - 'A' + 10
+ }
+ err = errInvalidFormat
+ return 0
+ }
+
+ switch len(s) {
+ case 7:
+ c.R = hexToByte(s[1])<<4 + hexToByte(s[2])
+ c.G = hexToByte(s[3])<<4 + hexToByte(s[4])
+ c.B = hexToByte(s[5])<<4 + hexToByte(s[6])
+ case 4:
+ c.R = hexToByte(s[1]) * 17
+ c.G = hexToByte(s[2]) * 17
+ c.B = hexToByte(s[3]) * 17
+ default:
+ err = errInvalidFormat
+ }
+ return c, err
+}
+
+// RGBColor is a color specified by red, green, and blue values.
+type RGBColor struct {
+ R uint8
+ G uint8
+ B uint8
+}
+
+// RGBA returns the RGBA value of this color. This satisfies the Go Color
+// interface.
+func (c RGBColor) RGBA() (r, g, b, a uint32) {
+ const shift = 8
+ r |= uint32(c.R) << shift
+ g |= uint32(c.G) << shift
+ b |= uint32(c.B) << shift
+ a = 0xFFFF
+ return
+}
+
+// ANSIColor is a color specified by an ANSI256 color value.
+//
+// Example usage:
+//
+// colorA := lipgloss.ANSIColor(8)
+// colorB := lipgloss.ANSIColor(134)
+type ANSIColor = ansi.IndexedColor
+
+// LightDarkFunc is a function that returns a color based on whether the
+// terminal has a light or dark background. You can create one of these with
+// [LightDark].
+//
+// Example:
+//
+// lightDark := lipgloss.LightDark(hasDarkBackground)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+//
+// For more info see [LightDark].
+type LightDarkFunc func(light, dark color.Color) color.Color
+
+// LightDark is a simple helper type that can be used to choose the appropriate
+// color based on whether the terminal has a light or dark background.
+//
+// lightDark := lipgloss.LightDark(hasDarkBackground)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+//
+// In practice, there are slightly different workflows between Bubble Tea and
+// Lip Gloss standalone.
+//
+// In Bubble Tea, listen for tea.BackgroundColorMsg, which automatically
+// flows through Update on start. This message will be received whenever the
+// background color changes:
+//
+// case tea.BackgroundColorMsg:
+// m.hasDarkBackground = msg.IsDark()
+//
+// Later, when you're rendering use:
+//
+// lightDark := lipgloss.LightDark(m.hasDarkBackground)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+//
+// In standalone Lip Gloss, the workflow is simpler:
+//
+// hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+// lightDark := lipgloss.LightDark(hasDarkBG)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+func LightDark(isDark bool) LightDarkFunc {
+ return func(light, dark color.Color) color.Color {
+ if isDark {
+ return dark
+ }
+ return light
+ }
+}
+
+// isDarkColor returns whether the given color is dark (based on the luminance
+// portion of the color as interpreted as HSL).
+//
+// Example usage:
+//
+// color := lipgloss.Color("#0000ff")
+// if lipgloss.isDarkColor(color) {
+// fmt.Println("It's dark! I love darkness!")
+// } else {
+// fmt.Println("It's light! Cover your eyes!")
+// }
+func isDarkColor(c color.Color) bool {
+ col, ok := colorful.MakeColor(c)
+ if !ok {
+ return true
+ }
+
+ _, _, l := col.Hsl()
+ return l < 0.5 //nolint:mnd
+}
+
+// CompleteFunc is a function that returns the appropriate color based on the
+// given color profile.
+//
+// Example usage:
+//
+// p := colorprofile.Detect(os.Stderr, os.Environ())
+// complete := lipgloss.Complete(p)
+// color := complete(
+// lipgloss.Color(1), // ANSI
+// lipgloss.Color(124), // ANSI256
+// lipgloss.Color("#ff34ac"), // TrueColor
+// )
+// fmt.Println("Ooh, pretty color: ", color)
+//
+// For more info see [Complete].
+type CompleteFunc func(ansi, ansi256, truecolor color.Color) color.Color
+
+// Complete returns a function that will return the appropriate color based on
+// the given color profile.
+//
+// Example usage:
+//
+// p := colorprofile.Detect(os.Stderr, os.Environ())
+// complete := lipgloss.Complete(p)
+// color := complete(
+// lipgloss.Color(1), // ANSI
+// lipgloss.Color(124), // ANSI256
+// lipgloss.Color("#ff34ac"), // TrueColor
+// )
+// fmt.Println("Ooh, pretty color: ", color)
+func Complete(p colorprofile.Profile) CompleteFunc {
+ return func(ansi, ansi256, truecolor color.Color) color.Color {
+ switch p { //nolint:exhaustive
+ case colorprofile.ANSI:
+ return ansi
+ case colorprofile.ANSI256:
+ return ansi256
+ case colorprofile.TrueColor:
+ return truecolor
+ }
+ return noColor
+ }
+}
+
+// ensureNotTransparent ensures that the alpha value of a color is not 0, and if
+// it is, we will set it to 1. This is useful for when we are converting from
+// RGB -> RGBA, and the alpha value is lost in the conversion for gradient purposes.
+func ensureNotTransparent(c color.Color) color.Color {
+ _, _, _, a := c.RGBA()
+ if a == 0 {
+ return Alpha(c, 1)
+ }
+ return c
+}
+
+// Alpha adjusts the alpha value of a color using a 0-1 (clamped) float scale
+// 0 = transparent, 1 = opaque.
+func Alpha(c color.Color, alpha float64) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ r, g, b, _ := c.RGBA()
+ return color.RGBA{
+ R: uint8(min(255, float64(r>>8))),
+ G: uint8(min(255, float64(g>>8))),
+ B: uint8(min(255, float64(b>>8))),
+ A: uint8(clamp(alpha, 0, 1) * 255),
+ }
+}
+
+// Complementary returns the complementary color (180° away on color wheel) of
+// the given color. This is useful for creating a contrasting color.
+func Complementary(c color.Color) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ // Offset hue by 180°.
+ cf, _ := colorful.MakeColor(ensureNotTransparent(c))
+
+ h, s, v := cf.Hsv()
+ h += 180
+ if h >= 360 {
+ h -= 360
+ } else if h < 0 {
+ h += 360
+ }
+
+ return colorful.Hsv(h, s, v).Clamped()
+}
+
+// Darken takes a color and makes it darker by a specific percentage (0-1, clamped).
+func Darken(c color.Color, percent float64) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ mult := 1.0 - clamp(percent, 0, 1)
+
+ r, g, b, a := c.RGBA()
+ return color.RGBA{
+ R: uint8(float64(r>>8) * mult),
+ G: uint8(float64(g>>8) * mult),
+ B: uint8(float64(b>>8) * mult),
+ A: uint8(min(255, float64(a>>8))),
+ }
+}
+
+// Lighten makes a color lighter by a specific percentage (0-1, clamped).
+func Lighten(c color.Color, percent float64) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ add := 255 * (clamp(percent, 0, 1))
+
+ r, g, b, a := c.RGBA()
+ return color.RGBA{
+ R: uint8(min(255, float64(r>>8)+add)),
+ G: uint8(min(255, float64(g>>8)+add)),
+ B: uint8(min(255, float64(b>>8)+add)),
+ A: uint8(min(255, float64(a>>8))),
+ }
+}
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/get.go b/hack/tools/vendor/charm.land/lipgloss/v2/get.go
similarity index 80%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/get.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/get.go
index 422b4ce9551..d1fe1d66911 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/get.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/get.go
@@ -1,6 +1,7 @@
package lipgloss
import (
+ "image/color"
"strings"
"github.com/charmbracelet/x/ansi"
@@ -20,7 +21,19 @@ func (s Style) GetItalic() bool {
// GetUnderline returns the style's underline value. If no value is set false is
// returned.
func (s Style) GetUnderline() bool {
- return s.getAsBool(underlineKey, false)
+ return s.ul != UnderlineNone
+}
+
+// GetUnderlineStyle returns the style's underline style. If no value is set
+// UnderlineNone is returned.
+func (s Style) GetUnderlineStyle() Underline {
+ return s.ul
+}
+
+// GetUnderlineColor returns the style's underline color. If no value is set
+// NoColor{} is returned.
+func (s Style) GetUnderlineColor() color.Color {
+ return s.getAsColor(underlineColorKey)
}
// GetStrikethrough returns the style's strikethrough value. If no value is set false
@@ -49,13 +62,13 @@ func (s Style) GetFaint() bool {
// GetForeground returns the style's foreground color. If no value is set
// NoColor{} is returned.
-func (s Style) GetForeground() TerminalColor {
+func (s Style) GetForeground() color.Color {
return s.getAsColor(foregroundKey)
}
// GetBackground returns the style's background color. If no value is set
// NoColor{} is returned.
-func (s Style) GetBackground() TerminalColor {
+func (s Style) GetBackground() color.Color {
return s.getAsColor(backgroundKey)
}
@@ -134,6 +147,16 @@ func (s Style) GetPaddingLeft() int {
return s.getAsInt(paddingLeftKey)
}
+// GetPaddingChar returns the style's padding character. If no value is set a
+// space is returned.
+func (s Style) GetPaddingChar() rune {
+ char := s.getAsRune(paddingCharKey)
+ if char == 0 {
+ return ' '
+ }
+ return char
+}
+
// GetHorizontalPadding returns the style's left and right padding. Unset
// values are measured as 0.
func (s Style) GetHorizontalPadding() int {
@@ -185,6 +208,16 @@ func (s Style) GetMarginLeft() int {
return s.getAsInt(marginLeftKey)
}
+// GetMarginChar returns the style's padding character. If no value is set a
+// space is returned.
+func (s Style) GetMarginChar() rune {
+ char := s.getAsRune(marginCharKey)
+ if char == 0 {
+ return ' '
+ }
+ return char
+}
+
// GetHorizontalMargins returns the style's left and right margins. Unset
// values are measured as 0.
func (s Style) GetHorizontalMargins() int {
@@ -241,49 +274,61 @@ func (s Style) GetBorderLeft() bool {
// GetBorderTopForeground returns the style's border top foreground color. If
// no value is set NoColor{} is returned.
-func (s Style) GetBorderTopForeground() TerminalColor {
+func (s Style) GetBorderTopForeground() color.Color {
return s.getAsColor(borderTopForegroundKey)
}
// GetBorderRightForeground returns the style's border right foreground color.
// If no value is set NoColor{} is returned.
-func (s Style) GetBorderRightForeground() TerminalColor {
+func (s Style) GetBorderRightForeground() color.Color {
return s.getAsColor(borderRightForegroundKey)
}
// GetBorderBottomForeground returns the style's border bottom foreground
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderBottomForeground() TerminalColor {
+func (s Style) GetBorderBottomForeground() color.Color {
return s.getAsColor(borderBottomForegroundKey)
}
// GetBorderLeftForeground returns the style's border left foreground
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderLeftForeground() TerminalColor {
+func (s Style) GetBorderLeftForeground() color.Color {
return s.getAsColor(borderLeftForegroundKey)
}
+// GetBorderForegroundBlend returns the style's border blend foreground
+// colors. If no value is set, nil is returned.
+func (s Style) GetBorderForegroundBlend() []color.Color {
+ return s.getAsColors(borderForegroundBlendKey)
+}
+
+// GetBorderForegroundBlendOffset returns the style's border blend offset. If no
+// value is set, 0 is returned.
+func (s Style) GetBorderForegroundBlendOffset() int {
+ return s.getAsInt(borderForegroundBlendOffsetKey)
+}
+
// GetBorderTopBackground returns the style's border top background color. If
// no value is set NoColor{} is returned.
-func (s Style) GetBorderTopBackground() TerminalColor {
+func (s Style) GetBorderTopBackground() color.Color {
return s.getAsColor(borderTopBackgroundKey)
}
// GetBorderRightBackground returns the style's border right background color.
// If no value is set NoColor{} is returned.
-func (s Style) GetBorderRightBackground() TerminalColor {
+func (s Style) GetBorderRightBackground() color.Color {
return s.getAsColor(borderRightBackgroundKey)
}
// GetBorderBottomBackground returns the style's border bottom background
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderBottomBackground() TerminalColor {
+func (s Style) GetBorderBottomBackground() color.Color {
return s.getAsColor(borderBottomBackgroundKey)
}
// GetBorderLeftBackground returns the style's border left background
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderLeftBackground() TerminalColor {
+func (s Style) GetBorderLeftBackground() color.Color {
return s.getAsColor(borderLeftBackgroundKey)
}
@@ -300,7 +345,10 @@ func (s Style) GetBorderTopWidth() int {
// runes of varying widths, the widest rune is returned. If no border exists on
// the top edge, 0 is returned.
func (s Style) GetBorderTopSize() int {
- if !s.getAsBool(borderTopKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderTopKey, false) {
return 0
}
return s.getBorderStyle().GetTopSize()
@@ -310,7 +358,10 @@ func (s Style) GetBorderTopSize() int {
// runes of varying widths, the widest rune is returned. If no border exists on
// the left edge, 0 is returned.
func (s Style) GetBorderLeftSize() int {
- if !s.getAsBool(borderLeftKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderLeftKey, false) {
return 0
}
return s.getBorderStyle().GetLeftSize()
@@ -320,7 +371,10 @@ func (s Style) GetBorderLeftSize() int {
// contain runes of varying widths, the widest rune is returned. If no border
// exists on the left edge, 0 is returned.
func (s Style) GetBorderBottomSize() int {
- if !s.getAsBool(borderBottomKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderBottomKey, false) {
return 0
}
return s.getBorderStyle().GetBottomSize()
@@ -330,7 +384,10 @@ func (s Style) GetBorderBottomSize() int {
// contain runes of varying widths, the widest rune is returned. If no border
// exists on the right edge, 0 is returned.
func (s Style) GetBorderRightSize() int {
- if !s.getAsBool(borderRightKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderRightKey, false) {
return 0
}
return s.getBorderStyle().GetRightSize()
@@ -414,11 +471,36 @@ func (s Style) GetTransform() func(string) string {
return s.getAsTransform(transformKey)
}
+// GetHyperlink returns the hyperlink along with its parameters. If no
+// hyperlink is set, empty strings are returned.
+func (s Style) GetHyperlink() (link, params string) {
+ if s.isSet(linkKey) {
+ link = s.link
+ }
+ if s.isSet(linkParamsKey) {
+ params = s.linkParams
+ }
+ return
+}
+
// Returns whether or not the given property is set.
func (s Style) isSet(k propKey) bool {
return s.props.has(k)
}
+func (s Style) getAsRune(k propKey) rune {
+ if !s.isSet(k) {
+ return 0
+ }
+ switch k { //nolint:exhaustive
+ case paddingCharKey:
+ return s.paddingChar
+ case marginCharKey:
+ return s.marginChar
+ }
+ return 0
+}
+
func (s Style) getAsBool(k propKey, defaultVal bool) bool {
if !s.isSet(k) {
return defaultVal
@@ -426,12 +508,25 @@ func (s Style) getAsBool(k propKey, defaultVal bool) bool {
return s.attrs&int(k) != 0
}
-func (s Style) getAsColor(k propKey) TerminalColor {
+func (s Style) getAsColors(k propKey) (colors []color.Color) {
+ if !s.isSet(k) {
+ return nil
+ }
+
+ switch k { //nolint:exhaustive
+ case borderForegroundBlendKey:
+ return s.borderBlendFgColor
+ }
+
+ return nil
+}
+
+func (s Style) getAsColor(k propKey) color.Color {
if !s.isSet(k) {
return noColor
}
- var c TerminalColor
+ var c color.Color
switch k { //nolint:exhaustive
case foregroundKey:
c = s.fgColor
@@ -455,6 +550,8 @@ func (s Style) getAsColor(k propKey) TerminalColor {
c = s.borderBottomBgColor
case borderLeftBackgroundKey:
c = s.borderLeftBgColor
+ case underlineColorKey:
+ c = s.ulColor
}
if c != nil {
@@ -489,6 +586,8 @@ func (s Style) getAsInt(k propKey) int {
return s.marginBottom
case marginLeftKey:
return s.marginLeft
+ case borderForegroundBlendOffsetKey:
+ return s.borderForegroundBlendOffset
case maxWidthKey:
return s.maxWidth
case maxHeightKey:
@@ -519,20 +618,6 @@ func (s Style) getBorderStyle() Border {
return s.borderStyle
}
-// Returns whether or not the style has implicit borders. This happens when
-// a border style has been set but no border sides have been explicitly turned
-// on or off.
-func (s Style) implicitBorders() bool {
- var (
- borderStyle = s.getBorderStyle()
- topSet = s.isSet(borderTopKey)
- rightSet = s.isSet(borderRightKey)
- bottomSet = s.isSet(borderBottomKey)
- leftSet = s.isSet(borderLeftKey)
- )
- return borderStyle != noBorder && !(topSet || rightSet || bottomSet || leftSet)
-}
-
func (s Style) getAsTransform(propKey) func(string) string {
if !s.isSet(transformKey) {
return nil
@@ -543,6 +628,8 @@ func (s Style) getAsTransform(propKey) func(string) string {
// Split a string into lines, additionally returning the size of the widest
// line.
func getLines(s string) (lines []string, widest int) {
+ s = strings.ReplaceAll(s, "\t", " ")
+ s = strings.ReplaceAll(s, "\r\n", "\n")
lines = strings.Split(s, "\n")
for _, l := range lines {
@@ -554,3 +641,17 @@ func getLines(s string) (lines []string, widest int) {
return lines, widest
}
+
+// isBorderStyleSetWithoutSides returns true if the border style is set but no
+// sides are set. This is used to determine if the border should be rendered by
+// default.
+func (s Style) isBorderStyleSetWithoutSides() bool {
+ var (
+ border = s.getBorderStyle()
+ topSet = s.isSet(borderTopKey)
+ rightSet = s.isSet(borderRightKey)
+ bottomSet = s.isSet(borderBottomKey)
+ leftSet = s.isSet(borderLeftKey)
+ )
+ return border != noBorder && !(topSet || rightSet || bottomSet || leftSet) //nolint:staticcheck
+}
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/join.go b/hack/tools/vendor/charm.land/lipgloss/v2/join.go
similarity index 97%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/join.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/join.go
index b0a23a54615..349ae552fa5 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/join.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/join.go
@@ -60,7 +60,7 @@ func JoinHorizontal(pos Position, strs ...string) string {
extraLines := make([]string, maxHeight-len(blocks[i]))
- switch pos { //nolint:exhaustive
+ switch pos {
case Top:
blocks[i] = append(blocks[i], extraLines...)
@@ -139,7 +139,7 @@ func JoinVertical(pos Position, strs ...string) string {
for j, line := range block {
w := maxWidth - ansi.StringWidth(line)
- switch pos { //nolint:exhaustive
+ switch pos {
case Left:
b.WriteString(line)
b.WriteString(strings.Repeat(" ", w))
@@ -165,7 +165,7 @@ func JoinVertical(pos Position, strs ...string) string {
// Write a newline as long as we're not on the last line of the
// last block.
- if !(i == len(blocks)-1 && j == len(block)-1) {
+ if !(i == len(blocks)-1 && j == len(block)-1) { //nolint:staticcheck
b.WriteRune('\n')
}
}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/layer.go b/hack/tools/vendor/charm.land/lipgloss/v2/layer.go
new file mode 100644
index 00000000000..e30d1ef2a06
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/layer.go
@@ -0,0 +1,327 @@
+package lipgloss
+
+import (
+ "fmt"
+ "image"
+ "slices"
+
+ uv "github.com/charmbracelet/ultraviolet"
+)
+
+// Layer represents a visual layer with content and positioning. It's a pure
+// data structure that defines the layer hierarchy without any computation.
+type Layer struct {
+ id string
+ content string
+ width, height int
+ x, y, z int
+ layers []*Layer
+}
+
+// NewLayer creates a new [Layer] with the given content and optional child layers.
+func NewLayer(content string, layers ...*Layer) *Layer {
+ l := &Layer{
+ content: content,
+ }
+ l.AddLayers(layers...)
+ return l
+}
+
+// GetContent returns the content of the Layer.
+func (l *Layer) GetContent() string {
+ return l.content
+}
+
+// Width returns the width of the Layer.
+func (l *Layer) Width() int {
+ return l.width
+}
+
+// Height returns the height of the Layer.
+func (l *Layer) Height() int {
+ return l.height
+}
+
+// GetID returns the ID of the Layer.
+func (l *Layer) GetID() string {
+ return l.id
+}
+
+// ID sets the ID of the Layer.
+func (l *Layer) ID(id string) *Layer {
+ l.id = id
+ return l
+}
+
+// X sets the x-coordinate of the Layer relative to its parent.
+func (l *Layer) X(x int) *Layer {
+ l.x = x
+ return l
+}
+
+// Y sets the y-coordinate of the Layer relative to its parent.
+func (l *Layer) Y(y int) *Layer {
+ l.y = y
+ return l
+}
+
+// Z sets the z-index of the Layer relative to its parent.
+func (l *Layer) Z(z int) *Layer {
+ l.z = z
+ return l
+}
+
+// GetX returns the x-coordinate of the Layer relative to its parent.
+func (l *Layer) GetX() int {
+ return l.x
+}
+
+// GetY returns the y-coordinate of the Layer relative to its parent.
+func (l *Layer) GetY() int {
+ return l.y
+}
+
+// GetZ returns the z-index of the Layer relative to its parent.
+func (l *Layer) GetZ() int {
+ return l.z
+}
+
+// AddLayers adds child layers to the Layer.
+func (l *Layer) AddLayers(layers ...*Layer) *Layer {
+ for i, layer := range layers {
+ if layer == nil {
+ panic(fmt.Sprintf("layer at index %d is nil", i))
+ }
+ l.layers = append(l.layers, layer)
+ }
+ area := l.boundsWithOffset(0, 0)
+ l.width = area.Dx()
+ l.height = area.Dy()
+ return l
+}
+
+// GetLayer returns a descendant layer by its ID, or nil if not found.
+// Layers with empty IDs are skipped.
+func (l *Layer) GetLayer(id string) *Layer {
+ if id == "" {
+ return nil
+ }
+ if l.id == id {
+ return l
+ }
+ for _, child := range l.layers {
+ if found := child.GetLayer(id); found != nil {
+ return found
+ }
+ }
+ return nil
+}
+
+// MaxZ returns the maximum z-index among this layer and all its descendants.
+func (l *Layer) MaxZ() int {
+ maxZ := l.z
+ for _, child := range l.layers {
+ childMaxZ := child.MaxZ()
+ if childMaxZ > maxZ {
+ maxZ = childMaxZ
+ }
+ }
+ return maxZ
+}
+
+// boundsWithOffset calculates bounds with parent offset applied.
+func (l *Layer) boundsWithOffset(parentX, parentY int) image.Rectangle {
+ absX := l.x + parentX
+ absY := l.y + parentY
+
+ width, height := Width(l.content), Height(l.content)
+ bounds := image.Rectangle{
+ Min: image.Pt(absX, absY),
+ Max: image.Pt(absX+width, absY+height),
+ }
+
+ for _, child := range l.layers {
+ bounds = bounds.Union(child.boundsWithOffset(absX, absY))
+ }
+
+ return bounds
+}
+
+var _ uv.Drawable = (*Layer)(nil)
+
+// Draw draws the content of the layer on the screen at the specified area.
+func (l *Layer) Draw(scr uv.Screen, area uv.Rectangle) {
+ content := uv.NewStyledString(l.content)
+ content.Draw(scr, area)
+}
+
+// LayerHit represents the result of a hit test on a [Layer].
+type LayerHit struct {
+ id string
+ layer *Layer
+ bounds image.Rectangle
+}
+
+// Empty returns true if the LayerHit represents no hit.
+func (lh LayerHit) Empty() bool {
+ return lh.layer == nil
+}
+
+// ID returns the ID of the hit Layer.
+func (lh LayerHit) ID() string {
+ return lh.id
+}
+
+// Layer returns the layer that was hit.
+func (lh LayerHit) Layer() *Layer {
+ return lh.layer
+}
+
+// Bounds returns the bounds of the LayerHit.
+func (lh LayerHit) Bounds() image.Rectangle {
+ return lh.bounds
+}
+
+// Compositor manages the composition of layers. It flattens a layer hierarchy
+// once and provides efficient drawing and hit testing operations. All computation
+// related to layers happens in the Compositor.
+type Compositor struct {
+ root *Layer
+ layers []compositeLayer
+ index map[string]*Layer
+ bounds image.Rectangle
+}
+
+// compositeLayer holds a flattened layer with its calculated absolute position and bounds.
+type compositeLayer struct {
+ layer *Layer
+ absX int
+ absY int
+ bounds image.Rectangle
+}
+
+// NewCompositor creates a new Compositor with an internal root layer. Optional
+// layers can be provided which will be added as children of the root. The layer
+// hierarchy is flattened and sorted by z-index for efficient rendering and hit testing.
+func NewCompositor(layers ...*Layer) *Compositor {
+ root := NewLayer("")
+ root.AddLayers(layers...)
+ c := &Compositor{
+ root: root,
+ index: make(map[string]*Layer),
+ }
+ c.flatten()
+ return c
+}
+
+// AddLayers adds layers to the compositor's root and refreshes the internal state.
+func (c *Compositor) AddLayers(layers ...*Layer) *Compositor {
+ c.root.AddLayers(layers...)
+ c.flatten()
+ return c
+}
+
+// flatten builds the internal flattened layer list and calculates overall bounds.
+func (c *Compositor) flatten() {
+ c.layers = nil
+ c.index = make(map[string]*Layer)
+ c.flattenRecursive(c.root, 0, 0)
+
+ // Sort by absolute z-index (lowest to highest for drawing)
+ slices.SortFunc(c.layers, func(a, b compositeLayer) int {
+ return a.layer.z - b.layer.z
+ })
+
+ // Calculate overall bounds
+ if len(c.layers) > 0 {
+ c.bounds = c.layers[0].bounds
+ for i := 1; i < len(c.layers); i++ {
+ c.bounds = c.bounds.Union(c.layers[i].bounds)
+ }
+ }
+}
+
+// flattenRecursive recursively collects all layers with their absolute positions.
+func (c *Compositor) flattenRecursive(layer *Layer, parentX, parentY int) {
+ absX := layer.x + parentX
+ absY := layer.y + parentY
+
+ width, height := Width(layer.content), Height(layer.content)
+ bounds := image.Rectangle{
+ Min: image.Pt(absX, absY),
+ Max: image.Pt(absX+width, absY+height),
+ }
+
+ c.layers = append(c.layers, compositeLayer{
+ layer: layer,
+ absX: absX,
+ absY: absY,
+ bounds: bounds,
+ })
+
+ // Index layer by ID if it has one
+ if layer.id != "" {
+ c.index[layer.id] = layer
+ }
+
+ for _, child := range layer.layers {
+ c.flattenRecursive(child, absX, absY)
+ }
+}
+
+// Bounds returns the overall bounds of all layers in the compositor.
+func (c *Compositor) Bounds() image.Rectangle {
+ return c.bounds
+}
+
+// Draw draws all layers onto the given [uv.Screen] in z-index order.
+func (c *Compositor) Draw(scr uv.Screen, area image.Rectangle) {
+ for _, cl := range c.layers {
+ if cl.bounds.Overlaps(area) {
+ cl.layer.Draw(scr, cl.bounds)
+ }
+ }
+}
+
+// Hit performs a hit test at the given (x, y) coordinates. If a layer is hit,
+// it returns the ID of the top-most layer at that point. Layers with empty IDs
+// are ignored. If no layer is hit, it returns an empty [LayerHit].
+func (c *Compositor) Hit(x, y int) LayerHit {
+ var hit LayerHit
+ pt := image.Pt(x, y)
+ // Check from highest z to lowest (reverse order)
+ for i := len(c.layers) - 1; i >= 0; i-- {
+ cl := c.layers[i]
+ if cl.layer.id != "" && pt.In(cl.bounds) {
+ hit.id = cl.layer.id
+ hit.layer = cl.layer
+ hit.bounds = cl.bounds
+ return hit
+ }
+ }
+ return hit
+}
+
+// GetLayer returns a layer by its ID, or nil if not found.
+// Layers with empty IDs are not indexed and cannot be retrieved.
+func (c *Compositor) GetLayer(id string) *Layer {
+ if id == "" {
+ return nil
+ }
+ return c.index[id]
+}
+
+// Refresh re-flattens the layer hierarchy. Call this after modifying the layer
+// tree structure or positions to update the compositor's internal state.
+func (c *Compositor) Refresh() {
+ c.flatten()
+}
+
+// Render renders the compositor into a styled string. This is a helper
+// function that creates a temporary canvas, draws the compositor onto it, and
+// returns the resulting string.
+func (c *Compositor) Render() string {
+ width, height := c.bounds.Dx(), c.bounds.Dy()
+ canvas := NewCanvas(width, height)
+ return canvas.Compose(c).Render()
+}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/lipgloss.go b/hack/tools/vendor/charm.land/lipgloss/v2/lipgloss.go
new file mode 100644
index 00000000000..3fb4e6f26c3
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/lipgloss.go
@@ -0,0 +1,3 @@
+// Package lipgloss provides style definitions for nice terminal layouts. Built
+// with TUIs in mind.
+package lipgloss
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/position.go b/hack/tools/vendor/charm.land/lipgloss/v2/position.go
similarity index 69%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/position.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/position.go
index 185f5af3bd3..cea67763fbf 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/position.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/position.go
@@ -34,26 +34,13 @@ const (
// Place places a string or text block vertically in an unstyled box of a given
// width or height.
func Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string {
- return renderer.Place(width, height, hPos, vPos, str, opts...)
-}
-
-// Place places a string or text block vertically in an unstyled box of a given
-// width or height.
-func (r *Renderer) Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string {
- return r.PlaceVertical(height, vPos, r.PlaceHorizontal(width, hPos, str, opts...), opts...)
+ return PlaceVertical(height, vPos, PlaceHorizontal(width, hPos, str, opts...), opts...)
}
// PlaceHorizontal places a string or text block horizontally in an unstyled
// block of a given width. If the given width is shorter than the max width of
// the string (measured by its longest line) this will be a noop.
func PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string {
- return renderer.PlaceHorizontal(width, pos, str, opts...)
-}
-
-// PlaceHorizontal places a string or text block horizontally in an unstyled
-// block of a given width. If the given width is shorter than the max width of
-// the string (measured by its longest line) this will be a noöp.
-func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string {
lines, contentWidth := getLines(str)
gap := width - contentWidth
@@ -61,14 +48,14 @@ func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...
return str
}
- ws := newWhitespace(r, opts...)
+ ws := newWhitespace(opts...)
var b strings.Builder
for i, l := range lines {
// Is this line shorter than the longest line?
short := max(0, contentWidth-ansi.StringWidth(l))
- switch pos { //nolint:exhaustive
+ switch pos {
case Left:
b.WriteString(l)
b.WriteString(ws.render(gap + short))
@@ -101,13 +88,6 @@ func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...
// of a given height. If the given height is shorter than the height of the
// string (measured by its newlines) then this will be a noop.
func PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string {
- return renderer.PlaceVertical(height, pos, str, opts...)
-}
-
-// PlaceVertical places a string or text block vertically in an unstyled block
-// of a given height. If the given height is shorter than the height of the
-// string (measured by its newlines) then this will be a noöp.
-func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string {
contentHeight := strings.Count(str, "\n") + 1
gap := height - contentHeight
@@ -115,17 +95,17 @@ func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...W
return str
}
- ws := newWhitespace(r, opts...)
+ ws := newWhitespace(opts...)
_, width := getLines(str)
emptyLine := ws.render(width)
b := strings.Builder{}
- switch pos { //nolint:exhaustive
+ switch pos {
case Top:
b.WriteString(str)
b.WriteRune('\n')
- for i := 0; i < gap; i++ {
+ for i := range gap {
b.WriteString(emptyLine)
if i < gap-1 {
b.WriteRune('\n')
@@ -144,7 +124,7 @@ func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...W
b.WriteString(strings.Repeat(emptyLine+"\n", top))
b.WriteString(str)
- for i := 0; i < bottom; i++ {
+ for range bottom {
b.WriteRune('\n')
b.WriteString(emptyLine)
}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/query.go b/hack/tools/vendor/charm.land/lipgloss/v2/query.go
new file mode 100644
index 00000000000..96cd5b94549
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/query.go
@@ -0,0 +1,92 @@
+package lipgloss
+
+import (
+ "fmt"
+ "image/color"
+ "os"
+ "runtime"
+
+ "github.com/charmbracelet/x/term"
+)
+
+func backgroundColor(in term.File, out term.File) (color.Color, error) {
+ state, err := term.MakeRaw(in.Fd())
+ if err != nil {
+ return nil, fmt.Errorf("error setting raw state to detect background color: %w", err)
+ }
+
+ defer term.Restore(in.Fd(), state) //nolint:errcheck
+
+ bg, err := queryBackgroundColor(in, out)
+ if err != nil {
+ return nil, err
+ }
+
+ return bg, nil
+}
+
+// BackgroundColor queries the terminal's background color. Typically, you'll
+// want to query against stdin and either stdout or stderr, depending on what
+// you're writing to.
+//
+// This function is intended for standalone Lip Gloss use only. If you're using
+// Bubble Tea, listen for tea.BackgroundColorMsg in your update function.
+func BackgroundColor(in term.File, out term.File) (bg color.Color, err error) {
+ if runtime.GOOS == "windows" { //nolint:nestif
+ // On Windows, when the input/output is redirected or piped, we need to
+ // open the console explicitly.
+ // See https://learn.microsoft.com/en-us/windows/console/getstdhandle#remarks
+ if !term.IsTerminal(in.Fd()) {
+ f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644) //nolint:gosec
+ if err != nil {
+ return nil, fmt.Errorf("error opening CONIN$: %w", err)
+ }
+ in = f
+ }
+ if !term.IsTerminal(out.Fd()) {
+ f, err := os.OpenFile("CONOUT$", os.O_RDWR, 0o644) //nolint:gosec
+ if err != nil {
+ return nil, fmt.Errorf("error opening CONOUT$: %w", err)
+ }
+ out = f
+ }
+ return backgroundColor(in, out)
+ }
+
+ // NOTE: On Unix, one of the given files must be a tty.
+ if !term.IsTerminal(in.Fd()) || !term.IsTerminal(out.Fd()) {
+ return nil, fmt.Errorf("input/output is not a terminal")
+ }
+ for _, f := range []term.File{in, out} {
+ if bg, err = backgroundColor(f, f); err == nil {
+ return bg, nil
+ }
+ }
+
+ return bg, err
+}
+
+// HasDarkBackground detects whether the terminal has a light or dark
+// background.
+//
+// Typically, you'll want to query against stdin and either stdout or stderr
+// depending on what you're writing to.
+//
+// hasDarkBG := HasDarkBackground(os.Stdin, os.Stdout)
+// lightDark := LightDark(hasDarkBG)
+// myHotColor := lightDark("#ff0000", "#0000ff")
+//
+// This is intended for use in standalone Lip Gloss only. In Bubble Tea, listen
+// for tea.BackgroundColorMsg in your Update function.
+//
+// case tea.BackgroundColorMsg:
+// hasDarkBackground = msg.IsDark()
+//
+// By default, this function will return true if it encounters an error.
+func HasDarkBackground(in term.File, out term.File) bool {
+ bg, err := BackgroundColor(in, out)
+ if err != nil || bg == nil {
+ return true
+ }
+ return isDarkColor(bg)
+}
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/ranges.go b/hack/tools/vendor/charm.land/lipgloss/v2/ranges.go
similarity index 75%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/ranges.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/ranges.go
index d1716998781..bb209f0eadd 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/ranges.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/ranges.go
@@ -6,9 +6,8 @@ import (
"github.com/charmbracelet/x/ansi"
)
-// StyleRanges allows to, given a string, style ranges of it differently.
-// The function will take into account existing styles.
-// Ranges should not overlap.
+// StyleRanges applying styling to ranges in a string. Existing styles will be
+// taken into account. Ranges should not overlap.
func StyleRanges(s string, ranges ...Range) string {
if len(ranges) == 0 {
return s
@@ -36,12 +35,13 @@ func StyleRanges(s string, ranges ...Range) string {
return buf.String()
}
-// NewRange returns a range that can be used with [StyleRanges].
+// NewRange returns a range and style that can be used with [StyleRanges].
func NewRange(start, end int, style Style) Range {
return Range{start, end, style}
}
-// Range to be used with [StyleRanges].
+// Range is a range of text and associated styling to be used with
+// [StyleRanges].
type Range struct {
Start, End int
Style Style
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/runes.go b/hack/tools/vendor/charm.land/lipgloss/v2/runes.go
similarity index 100%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/runes.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/runes.go
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/set.go b/hack/tools/vendor/charm.land/lipgloss/v2/set.go
similarity index 78%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/set.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/set.go
index fde38faecc9..f10b4538a69 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/set.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/set.go
@@ -1,16 +1,25 @@
package lipgloss
+import (
+ "image/color"
+ "strings"
+)
+
// Set a value on the underlying rules map.
-func (s *Style) set(key propKey, value interface{}) {
+func (s *Style) set(key propKey, value any) {
// We don't allow negative integers on any of our other values, so just keep
// them at zero or above. We could use uints instead, but the
// conversions are a little tedious, so we're sticking with ints for
// sake of usability.
- switch key { //nolint:exhaustive
+ switch key {
case foregroundKey:
s.fgColor = colorOrNil(value)
case backgroundKey:
s.bgColor = colorOrNil(value)
+ case underlineColorKey:
+ s.ulColor = colorOrNil(value)
+ case underlineKey:
+ s.ul = value.(Underline)
case widthKey:
s.width = max(0, value.(int))
case heightKey:
@@ -27,6 +36,8 @@ func (s *Style) set(key propKey, value interface{}) {
s.paddingBottom = max(0, value.(int))
case paddingLeftKey:
s.paddingLeft = max(0, value.(int))
+ case paddingCharKey:
+ s.paddingChar = value.(rune)
case marginTopKey:
s.marginTop = max(0, value.(int))
case marginRightKey:
@@ -37,6 +48,8 @@ func (s *Style) set(key propKey, value interface{}) {
s.marginLeft = max(0, value.(int))
case marginBackgroundKey:
s.marginBgColor = colorOrNil(value)
+ case marginCharKey:
+ s.marginChar = value.(rune)
case borderStyleKey:
s.borderStyle = value.(Border)
case borderTopForegroundKey:
@@ -47,6 +60,10 @@ func (s *Style) set(key propKey, value interface{}) {
s.borderBottomFgColor = colorOrNil(value)
case borderLeftForegroundKey:
s.borderLeftFgColor = colorOrNil(value)
+ case borderForegroundBlendKey:
+ s.borderBlendFgColor = value.([]color.Color)
+ case borderForegroundBlendOffsetKey:
+ s.borderForegroundBlendOffset = value.(int)
case borderTopBackgroundKey:
s.borderTopBgColor = colorOrNil(value)
case borderRightBackgroundKey:
@@ -65,6 +82,10 @@ func (s *Style) set(key propKey, value interface{}) {
s.tabWidth = value.(int)
case transformKey:
s.transform = value.(func(string) string)
+ case linkKey:
+ s.link = value.(string)
+ case linkParamsKey:
+ s.linkParams = value.(string)
default:
if v, ok := value.(bool); ok { //nolint:nestif
if v {
@@ -88,11 +109,15 @@ func (s *Style) set(key propKey, value interface{}) {
// setFrom sets the property from another style.
func (s *Style) setFrom(key propKey, i Style) {
- switch key { //nolint:exhaustive
+ switch key {
case foregroundKey:
s.set(foregroundKey, i.fgColor)
case backgroundKey:
s.set(backgroundKey, i.bgColor)
+ case underlineColorKey:
+ s.set(underlineColorKey, i.ulColor)
+ case underlineKey:
+ s.set(underlineKey, i.ul)
case widthKey:
s.set(widthKey, i.width)
case heightKey:
@@ -109,6 +134,8 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(paddingBottomKey, i.paddingBottom)
case paddingLeftKey:
s.set(paddingLeftKey, i.paddingLeft)
+ case paddingCharKey:
+ s.set(paddingCharKey, i.paddingChar)
case marginTopKey:
s.set(marginTopKey, i.marginTop)
case marginRightKey:
@@ -119,6 +146,8 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(marginLeftKey, i.marginLeft)
case marginBackgroundKey:
s.set(marginBackgroundKey, i.marginBgColor)
+ case marginCharKey:
+ s.set(marginCharKey, i.marginChar)
case borderStyleKey:
s.set(borderStyleKey, i.borderStyle)
case borderTopForegroundKey:
@@ -129,6 +158,10 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(borderBottomForegroundKey, i.borderBottomFgColor)
case borderLeftForegroundKey:
s.set(borderLeftForegroundKey, i.borderLeftFgColor)
+ case borderForegroundBlendKey:
+ s.set(borderForegroundBlendKey, i.borderBlendFgColor)
+ case borderForegroundBlendOffsetKey:
+ s.set(borderForegroundBlendOffsetKey, i.borderForegroundBlendOffset)
case borderTopBackgroundKey:
s.set(borderTopBackgroundKey, i.borderTopBgColor)
case borderRightBackgroundKey:
@@ -151,8 +184,8 @@ func (s *Style) setFrom(key propKey, i Style) {
}
}
-func colorOrNil(c interface{}) TerminalColor {
- if c, ok := c.(TerminalColor); ok {
+func colorOrNil(c any) color.Color {
+ if c, ok := c.(color.Color); ok {
return c
}
return nil
@@ -173,9 +206,33 @@ func (s Style) Italic(v bool) Style {
// Underline sets an underline rule. By default, underlines will not be drawn on
// whitespace like margins and padding. To change this behavior set
-// UnderlineSpaces.
+// [Style.UnderlineSpaces].
func (s Style) Underline(v bool) Style {
- s.set(underlineKey, v)
+ if v {
+ return s.UnderlineStyle(UnderlineSingle)
+ }
+ return s.UnderlineStyle(UnderlineNone)
+}
+
+// UnderlineStyle sets the underline style. This can be used to set the underline
+// to be a single, double, curly, dotted, or dashed line.
+//
+// Note that not all terminal emulators support underline styles. If a style is
+// not supported, it will typically fall back to a single underline but this is
+// not guaranteed. This depends on the terminal emulator being used.
+func (s Style) UnderlineStyle(u Underline) Style {
+ s.set(underlineKey, u)
+ return s
+}
+
+// UnderlineColor sets the color of the underline. By default, the underline
+// will be the same color as the foreground.
+//
+// Note that not all terminal emulators support colored underlines. If color is
+// not supported, it might produce unexpected results. This depends on the
+// terminal emulator being used.
+func (s Style) UnderlineColor(c color.Color) Style {
+ s.set(underlineColorKey, c)
return s
}
@@ -212,19 +269,20 @@ func (s Style) Faint(v bool) Style {
//
// // Removes the foreground color
// s.Foreground(lipgloss.NoColor)
-func (s Style) Foreground(c TerminalColor) Style {
+func (s Style) Foreground(c color.Color) Style {
s.set(foregroundKey, c)
return s
}
// Background sets a background color.
-func (s Style) Background(c TerminalColor) Style {
+func (s Style) Background(c color.Color) Style {
s.set(backgroundKey, c)
return s
}
-// Width sets the width of the block before applying margins. The width, if
-// set, also determines where text will wrap.
+// Width sets the width of the block before applying margins. This means your
+// styled content will exactly equal the size set here. Text will wrap based on
+// Padding and Borders set on the style.
func (s Style) Width(i int) Style {
s.set(widthKey, i)
return s
@@ -317,6 +375,18 @@ func (s Style) PaddingBottom(i int) Style {
return s
}
+// PaddingChar sets the character used for padding. This is useful for
+// rendering blocks with a specific character, such as a space or a dot.
+// Example of using [NBSP] as padding to prevent line breaks:
+//
+// ```go
+// s := lipgloss.NewStyle().PaddingChar(lipgloss.NBSP)
+// ```
+func (s Style) PaddingChar(r rune) Style {
+ s.set(paddingCharKey, r)
+ return s
+}
+
// ColorWhitespace determines whether or not the background color should be
// applied to the padding. This is true by default as it's more than likely the
// desired and expected behavior, but it can be disabled for certain graphic
@@ -382,11 +452,18 @@ func (s Style) MarginBottom(i int) Style {
// MarginBackground sets the background color of the margin. Note that this is
// also set when inheriting from a style with a background color. In that case
// the background color on that style will set the margin color on this style.
-func (s Style) MarginBackground(c TerminalColor) Style {
+func (s Style) MarginBackground(c color.Color) Style {
s.set(marginBackgroundKey, c)
return s
}
+// MarginChar sets the character used for the margin. This is useful for
+// rendering blocks with a specific character, such as a space or a dot.
+func (s Style) MarginChar(r rune) Style {
+ s.set(marginCharKey, r)
+ return s
+}
+
// Border is shorthand for setting the border style and which sides should
// have a border at once. The variadic argument sides works as follows:
//
@@ -487,7 +564,7 @@ func (s Style) BorderLeft(v bool) Style {
// top side, followed by the right side, then the bottom, and finally the left.
//
// With more than four arguments nothing will be set.
-func (s Style) BorderForeground(c ...TerminalColor) Style {
+func (s Style) BorderForeground(c ...color.Color) Style {
if len(c) == 0 {
return s
}
@@ -506,32 +583,80 @@ func (s Style) BorderForeground(c ...TerminalColor) Style {
}
// BorderTopForeground set the foreground color for the top of the border.
-func (s Style) BorderTopForeground(c TerminalColor) Style {
+func (s Style) BorderTopForeground(c color.Color) Style {
s.set(borderTopForegroundKey, c)
return s
}
// BorderRightForeground sets the foreground color for the right side of the
// border.
-func (s Style) BorderRightForeground(c TerminalColor) Style {
+func (s Style) BorderRightForeground(c color.Color) Style {
s.set(borderRightForegroundKey, c)
return s
}
// BorderBottomForeground sets the foreground color for the bottom of the
// border.
-func (s Style) BorderBottomForeground(c TerminalColor) Style {
+func (s Style) BorderBottomForeground(c color.Color) Style {
s.set(borderBottomForegroundKey, c)
return s
}
// BorderLeftForeground sets the foreground color for the left side of the
// border.
-func (s Style) BorderLeftForeground(c TerminalColor) Style {
+func (s Style) BorderLeftForeground(c color.Color) Style {
s.set(borderLeftForegroundKey, c)
return s
}
+// BorderForegroundBlend sets the foreground colors for the border blend. At least
+// 2 colors are required to use blending, otherwise this will no-op with 0 colors,
+// and pass to BorderForeground with 1 color. This will override all other border
+// foreground colors when used.
+//
+// When providing colors, in most cases (e.g. when all border sides are enabled),
+// you will want to provide a wrapping-set of colors, so the start and end color
+// are either the same, or very similar. For example:
+//
+// lipgloss.NewStyle().BorderForegroundBlend(
+// lipgloss.Color("#00FA68"),
+// lipgloss.Color("#9900FF"),
+// lipgloss.Color("#ED5353"),
+// lipgloss.Color("#9900FF"),
+// lipgloss.Color("#00FA68"),
+// )
+func (s Style) BorderForegroundBlend(c ...color.Color) Style {
+ if len(c) == 0 {
+ return s
+ }
+
+ // Insufficient colors to use blending, pass to BorderForeground.
+ if len(c) == 1 {
+ return s.BorderForeground(c...)
+ }
+
+ s.set(borderForegroundBlendKey, c)
+ return s
+}
+
+// BorderForegroundBlendOffset sets the border blend offset cells, starting from
+// the top left corner. Value can be positive or negative, and does not need to
+// equal the dimensions of the border region. Direction (when positive) is as
+// follows ("o" is starting point):
+//
+// o -------->
+// ┌──────────┐
+// ^ │ │ |
+// | │ │ |
+// | │ │ |
+// | │ │ v
+// └──────────┘
+// <---------
+func (s Style) BorderForegroundBlendOffset(v int) Style {
+ s.set(borderForegroundBlendOffsetKey, v)
+ return s
+}
+
// BorderBackground is a shorthand function for setting all of the
// background colors of the borders at once. The arguments work as follows:
//
@@ -547,7 +672,7 @@ func (s Style) BorderLeftForeground(c TerminalColor) Style {
// top side, followed by the right side, then the bottom, and finally the left.
//
// With more than four arguments nothing will be set.
-func (s Style) BorderBackground(c ...TerminalColor) Style {
+func (s Style) BorderBackground(c ...color.Color) Style {
if len(c) == 0 {
return s
}
@@ -566,27 +691,27 @@ func (s Style) BorderBackground(c ...TerminalColor) Style {
}
// BorderTopBackground sets the background color of the top of the border.
-func (s Style) BorderTopBackground(c TerminalColor) Style {
+func (s Style) BorderTopBackground(c color.Color) Style {
s.set(borderTopBackgroundKey, c)
return s
}
// BorderRightBackground sets the background color of right side the border.
-func (s Style) BorderRightBackground(c TerminalColor) Style {
+func (s Style) BorderRightBackground(c color.Color) Style {
s.set(borderRightBackgroundKey, c)
return s
}
// BorderBottomBackground sets the background color of the bottom of the
// border.
-func (s Style) BorderBottomBackground(c TerminalColor) Style {
+func (s Style) BorderBottomBackground(c color.Color) Style {
s.set(borderBottomBackgroundKey, c)
return s
}
// BorderLeftBackground set the background color of the left side of the
// border.
-func (s Style) BorderLeftBackground(c TerminalColor) Style {
+func (s Style) BorderLeftBackground(c color.Color) Style {
s.set(borderLeftBackgroundKey, c)
return s
}
@@ -685,10 +810,18 @@ func (s Style) Transform(fn func(string) string) Style {
return s
}
-// Renderer sets the renderer for the style. This is useful for changing the
-// renderer for a style that is being used in a different context.
-func (s Style) Renderer(r *Renderer) Style {
- s.r = r
+// Hyperlink sets a hyperlink on a style. This is useful for rendering text that
+// can be clicked on in a terminal emulator that supports hyperlinks.
+//
+// Example:
+//
+// s := lipgloss.NewStyle().Hyperlink("https://charm.sh")
+// s := lipgloss.NewStyle().Hyperlink("https://charm.sh", "id=1")
+func (s Style) Hyperlink(link string, params ...string) Style {
+ s.set(linkKey, link)
+ if len(params) > 0 {
+ s.set(linkParamsKey, strings.Join(params, ":"))
+ }
return s
}
@@ -768,7 +901,7 @@ func whichSidesBool(i ...bool) (top, right, bottom, left bool, ok bool) {
// whichSidesColor is like whichSides, except it operates on a series of
// boolean values. See the comment on whichSidesInt for details on how this
// works.
-func whichSidesColor(i ...TerminalColor) (top, right, bottom, left TerminalColor, ok bool) {
+func whichSidesColor(i ...color.Color) (top, right, bottom, left color.Color, ok bool) {
switch len(i) {
case 1:
top = i[0]
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/size.go b/hack/tools/vendor/charm.land/lipgloss/v2/size.go
similarity index 75%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/size.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/size.go
index e169ff5e23e..e0384d035f3 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/size.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/size.go
@@ -10,10 +10,10 @@ import (
// ignored and characters wider than one cell (such as Chinese characters and
// emojis) are appropriately measured.
//
-// You should use this instead of len(string) len([]rune(string) as neither
+// You should use this instead of len(string) or len([]rune(string) as neither
// will give you accurate results.
func Width(str string) (width int) {
- for _, l := range strings.Split(str, "\n") {
+ for l := range strings.SplitSeq(str, "\n") {
w := ansi.StringWidth(l)
if w > width {
width = w
@@ -24,9 +24,8 @@ func Width(str string) (width int) {
}
// Height returns height of a string in cells. This is done simply by
-// counting \n characters. If your strings use \r\n for newlines you should
-// convert them to \n first, or simply write a separate function for measuring
-// height.
+// counting \n characters. If your output has \r\n, that sequence will be
+// replaced with a \n in [Style.Render].
func Height(str string) int {
return strings.Count(str, "\n") + 1
}
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/style.go b/hack/tools/vendor/charm.land/lipgloss/v2/style.go
similarity index 68%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/style.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/style.go
index 59fa3ab216f..3cd65952676 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/style.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/style.go
@@ -1,15 +1,18 @@
package lipgloss
import (
+ "image/color"
"strings"
"unicode"
"github.com/charmbracelet/x/ansi"
- "github.com/charmbracelet/x/cellbuf"
- "github.com/muesli/termenv"
)
-const tabWidthDefault = 4
+const (
+ // NBSP is the non-breaking space rune.
+ NBSP = '\u00A0'
+ tabWidthDefault = 4
+)
// Property for a key.
type propKey int64
@@ -19,7 +22,6 @@ const (
// Boolean props come first.
boldKey propKey = 1 << iota
italicKey
- underlineKey
strikethroughKey
reverseKey
blinkKey
@@ -29,8 +31,10 @@ const (
colorWhitespaceKey
// Non-boolean props.
+ underlineKey
foregroundKey
backgroundKey
+ underlineColorKey
widthKey
heightKey
alignHorizontalKey
@@ -41,6 +45,7 @@ const (
paddingRightKey
paddingBottomKey
paddingLeftKey
+ paddingCharKey
// Margins.
marginTopKey
@@ -48,6 +53,7 @@ const (
marginBottomKey
marginLeftKey
marginBackgroundKey
+ marginCharKey
// Border runes.
borderStyleKey
@@ -63,6 +69,8 @@ const (
borderRightForegroundKey
borderBottomForegroundKey
borderLeftForegroundKey
+ borderForegroundBlendKey
+ borderForegroundBlendOffsetKey
// Border background colors.
borderTopBackgroundKey
@@ -76,6 +84,10 @@ const (
tabWidthKey
transformKey
+
+ // Hyperlink.
+ linkKey
+ linkParamsKey
)
// props is a set of properties.
@@ -96,35 +108,53 @@ func (p props) has(k propKey) bool {
return p&props(k) != 0
}
-// NewStyle returns a new, empty Style. While it's syntactic sugar for the
-// Style{} primitive, it's recommended to use this function for creating styles
-// in case the underlying implementation changes. It takes an optional string
-// value to be set as the underlying string value for this style.
-func NewStyle() Style {
- return renderer.NewStyle()
-}
+// Underline is the style of the underline.
+//
+// Caveats:
+// - Not all terminals support all underline styles.
+// - Some terminals may render unsupported styles as standard underlines.
+// - Terminal themes may affect the visibility of different underline styles.
+type Underline = ansi.Underline
+
+const (
+ // UnderlineNone is no underline.
+ UnderlineNone = ansi.UnderlineNone
+ // UnderlineSingle is a single underline. This is the default when underline is enabled.
+ UnderlineSingle = ansi.UnderlineSingle
+ // UnderlineDouble is a double underline.
+ UnderlineDouble = ansi.UnderlineDouble
+ // UnderlineCurly is a curly underline.
+ UnderlineCurly = ansi.UnderlineCurly
+ // UnderlineDotted is a dotted underline.
+ UnderlineDotted = ansi.UnderlineDotted
+ // UnderlineDashed is a dashed underline.
+ UnderlineDashed = ansi.UnderlineDashed
+)
// NewStyle returns a new, empty Style. While it's syntactic sugar for the
-// Style{} primitive, it's recommended to use this function for creating styles
-// in case the underlying implementation changes. It takes an optional string
-// value to be set as the underlying string value for this style.
-func (r *Renderer) NewStyle() Style {
- s := Style{r: r}
- return s
+// [Style]{} primitive, it's recommended to use this function for creating styles
+// in case the underlying implementation changes.
+func NewStyle() Style {
+ return Style{}
}
// Style contains a set of rules that comprise a style as a whole.
type Style struct {
- r *Renderer
props props
value string
+ // hyperlink
+ link, linkParams string
+
// we store bool props values here
attrs int
// props that have values
- fgColor TerminalColor
- bgColor TerminalColor
+ fgColor color.Color
+ bgColor color.Color
+ ulColor color.Color
+
+ ul Underline
width int
height int
@@ -136,22 +166,26 @@ type Style struct {
paddingRight int
paddingBottom int
paddingLeft int
+ paddingChar rune
marginTop int
marginRight int
marginBottom int
marginLeft int
- marginBgColor TerminalColor
-
- borderStyle Border
- borderTopFgColor TerminalColor
- borderRightFgColor TerminalColor
- borderBottomFgColor TerminalColor
- borderLeftFgColor TerminalColor
- borderTopBgColor TerminalColor
- borderRightBgColor TerminalColor
- borderBottomBgColor TerminalColor
- borderLeftBgColor TerminalColor
+ marginBgColor color.Color
+ marginChar rune
+
+ borderStyle Border
+ borderTopFgColor color.Color
+ borderRightFgColor color.Color
+ borderBottomFgColor color.Color
+ borderLeftFgColor color.Color
+ borderBlendFgColor []color.Color
+ borderForegroundBlendOffset int
+ borderTopBgColor color.Color
+ borderRightBgColor color.Color
+ borderBottomBgColor color.Color
+ borderLeftBgColor color.Color
maxWidth int
maxHeight int
@@ -167,10 +201,10 @@ func joinString(strs ...string) string {
}
// SetString sets the underlying string value for this style. To render once
-// the underlying string is set, use the Style.String. This method is
+// the underlying string is set, use the [Style.String]. This method is
// a convenience for cases when having a stringer implementation is handy, such
// as when using fmt.Sprintf. You can also simply define a style and render out
-// strings directly with Style.Render.
+// strings directly with [Style.Render].
func (s Style) SetString(strs ...string) Style {
s.value = joinString(strs...)
return s
@@ -232,9 +266,6 @@ func (s Style) Inherit(i Style) Style {
// Render applies the defined style formatting to a given string.
func (s Style) Render(strs ...string) string {
- if s.r == nil {
- s.r = renderer
- }
if s.value != "" {
strs = append([]string{s.value}, strs...)
}
@@ -242,14 +273,12 @@ func (s Style) Render(strs ...string) string {
var (
str = joinString(strs...)
- p = s.r.ColorProfile()
- te = p.String()
- teSpace = p.String()
- teWhitespace = p.String()
+ te ansi.Style
+ teSpace ansi.Style
+ teWhitespace ansi.Style
bold = s.getAsBool(boldKey, false)
italic = s.getAsBool(italicKey, false)
- underline = s.getAsBool(underlineKey, false)
strikethrough = s.getAsBool(strikethroughKey, false)
reverse = s.getAsBool(reverseKey, false)
blink = s.getAsBool(blinkKey, false)
@@ -257,7 +286,9 @@ func (s Style) Render(strs ...string) string {
fg = s.getAsColor(foregroundKey)
bg = s.getAsColor(backgroundKey)
+ ul = s.getAsColor(underlineColorKey)
+ underline = s.ul != UnderlineNone
width = s.getAsInt(widthKey)
height = s.getAsInt(heightKey)
horizontalAlign = s.getAsPosition(alignHorizontalKey)
@@ -268,6 +299,9 @@ func (s Style) Render(strs ...string) string {
bottomPadding = s.getAsInt(paddingBottomKey)
leftPadding = s.getAsInt(paddingLeftKey)
+ horizontalBorderSize = s.GetHorizontalBorderSize()
+ verticalBorderSize = s.GetVerticalBorderSize()
+
colorWhitespace = s.getAsBool(colorWhitespaceKey, true)
inline = s.getAsBool(inlineKey, false)
maxWidth = s.getAsInt(maxWidthKey)
@@ -284,6 +318,8 @@ func (s Style) Render(strs ...string) string {
useSpaceStyler = (underline && !underlineSpaces) || (strikethrough && !strikethroughSpaces) || underlineSpaces || strikethroughSpaces
transform = s.getAsTransform(transformKey)
+
+ link, linkParams = s.GetHyperlink()
)
if transform != nil {
@@ -294,62 +330,68 @@ func (s Style) Render(strs ...string) string {
return s.maybeConvertTabs(str)
}
- // Enable support for ANSI on the legacy Windows cmd.exe console. This is a
- // no-op on non-Windows systems and on Windows runs only once.
- enableLegacyWindowsANSI()
-
if bold {
te = te.Bold()
}
if italic {
- te = te.Italic()
+ te = te.Italic(true)
}
if underline {
- te = te.Underline()
+ te = te.Underline(true)
}
if reverse {
- teWhitespace = teWhitespace.Reverse()
- te = te.Reverse()
+ teWhitespace = teWhitespace.Reverse(true)
+ te = te.Reverse(true)
}
if blink {
- te = te.Blink()
+ te = te.Blink(true)
}
if faint {
te = te.Faint()
}
if fg != noColor {
- te = te.Foreground(fg.color(s.r))
+ te = te.ForegroundColor(fg)
if styleWhitespace {
- teWhitespace = teWhitespace.Foreground(fg.color(s.r))
+ teWhitespace = teWhitespace.ForegroundColor(fg)
}
if useSpaceStyler {
- teSpace = teSpace.Foreground(fg.color(s.r))
+ teSpace = teSpace.ForegroundColor(fg)
}
}
if bg != noColor {
- te = te.Background(bg.color(s.r))
+ te = te.BackgroundColor(bg)
+ if colorWhitespace {
+ teWhitespace = teWhitespace.BackgroundColor(bg)
+ }
+ if useSpaceStyler {
+ teSpace = teSpace.BackgroundColor(bg)
+ }
+ }
+
+ if ul != noColor {
+ te = te.UnderlineColor(ul)
if colorWhitespace {
- teWhitespace = teWhitespace.Background(bg.color(s.r))
+ teWhitespace = teWhitespace.UnderlineColor(ul)
}
if useSpaceStyler {
- teSpace = teSpace.Background(bg.color(s.r))
+ teSpace = teSpace.UnderlineColor(ul)
}
}
if underline {
- te = te.Underline()
+ te = te.UnderlineStyle(s.ul)
}
if strikethrough {
- te = te.CrossOut()
+ te = te.Strikethrough(true)
}
if underlineSpaces {
- teSpace = teSpace.Underline()
+ teSpace = teSpace.Underline(true)
}
if strikethroughSpaces {
- teSpace = teSpace.CrossOut()
+ teSpace = teSpace.Strikethrough(true)
}
// Potentially convert tabs to spaces
@@ -362,21 +404,30 @@ func (s Style) Render(strs ...string) string {
str = strings.ReplaceAll(str, "\n", "")
}
+ // Include borders in block size.
+ width -= horizontalBorderSize
+ height -= verticalBorderSize
+
// Word wrap
if !inline && width > 0 {
wrapAt := width - leftPadding - rightPadding
- str = cellbuf.Wrap(str, wrapAt, "")
+ str = Wrap(str, wrapAt, "")
}
// Render core text
{
var b strings.Builder
- l := strings.Split(str, "\n")
- for i := range l {
+ isFirst := true
+ for line := range strings.SplitSeq(str, "\n") {
+ if isFirst {
+ isFirst = false
+ } else {
+ b.WriteRune('\n')
+ }
if useSpaceStyler {
// Look for spaces and apply a different styler
- for _, r := range l[i] {
+ for _, r := range line {
if unicode.IsSpace(r) {
b.WriteString(teSpace.Styled(string(r)))
continue
@@ -384,32 +435,37 @@ func (s Style) Render(strs ...string) string {
b.WriteString(te.Styled(string(r)))
}
} else {
- b.WriteString(te.Styled(l[i]))
- }
- if i != len(l)-1 {
- b.WriteRune('\n')
+ b.WriteString(te.Styled(line))
}
}
str = b.String()
+
+ if len(link) > 0 {
+ str = ansi.SetHyperlink(link, linkParams) + str + ansi.ResetHyperlink()
+ }
}
// Padding
if !inline { //nolint:nestif
+ padChar := s.paddingChar
+ if padChar == 0 {
+ padChar = ' '
+ }
if leftPadding > 0 {
- var st *termenv.Style
+ var st *ansi.Style
if colorWhitespace || styleWhitespace {
st = &teWhitespace
}
- str = padLeft(str, leftPadding, st)
+ str = padLeft(str, leftPadding, st, padChar)
}
if rightPadding > 0 {
- var st *termenv.Style
+ var st *ansi.Style
if colorWhitespace || styleWhitespace {
st = &teWhitespace
}
- str = padRight(str, rightPadding, st)
+ str = padRight(str, rightPadding, st, padChar)
}
if topPadding > 0 {
@@ -433,7 +489,7 @@ func (s Style) Render(strs ...string) string {
numLines := strings.Count(str, "\n")
if numLines != 0 || width != 0 {
- var st *termenv.Style
+ var st *ansi.Style
if colorWhitespace || styleWhitespace {
st = &teWhitespace
}
@@ -491,17 +547,21 @@ func (s Style) applyMargins(str string, inline bool) string {
bottomMargin = s.getAsInt(marginBottomKey)
leftMargin = s.getAsInt(marginLeftKey)
- styler termenv.Style
+ style ansi.Style
)
bgc := s.getAsColor(marginBackgroundKey)
if bgc != noColor {
- styler = styler.Background(bgc.color(s.r))
+ style = style.BackgroundColor(bgc)
}
// Add left and right margin
- str = padLeft(str, leftMargin, &styler)
- str = padRight(str, rightMargin, &styler)
+ marginChar := s.marginChar
+ if marginChar == 0 {
+ marginChar = ' '
+ }
+ str = padLeft(str, leftMargin, &style, marginChar)
+ str = padRight(str, rightMargin, &style, marginChar)
// Top/bottom margin
if !inline {
@@ -509,10 +569,10 @@ func (s Style) applyMargins(str string, inline bool) string {
spaces := strings.Repeat(" ", width)
if topMargin > 0 {
- str = styler.Styled(strings.Repeat(spaces+"\n", topMargin)) + str
+ str = style.Styled(strings.Repeat(spaces+"\n", topMargin)) + str
}
if bottomMargin > 0 {
- str += styler.Styled(strings.Repeat("\n"+spaces, bottomMargin))
+ str += style.Styled(strings.Repeat("\n"+spaces, bottomMargin))
}
}
@@ -520,65 +580,54 @@ func (s Style) applyMargins(str string, inline bool) string {
}
// Apply left padding.
-func padLeft(str string, n int, style *termenv.Style) string {
- return pad(str, -n, style)
+func padLeft(str string, n int, style *ansi.Style, r rune) string {
+ return pad(str, -n, style, r)
}
// Apply right padding.
-func padRight(str string, n int, style *termenv.Style) string {
- return pad(str, n, style)
+func padRight(str string, n int, style *ansi.Style, r rune) string {
+ return pad(str, n, style, r)
}
// pad adds padding to either the left or right side of a string.
// Positive values add to the right side while negative values
// add to the left side.
-func pad(str string, n int, style *termenv.Style) string {
+// r is the rune to use for padding. We use " " for margins and
+// "\u00A0" for padding so that the padding is preserved when the
+// string is copied and pasted.
+func pad(str string, n int, style *ansi.Style, r rune) string {
if n == 0 {
return str
}
- sp := strings.Repeat(" ", abs(n))
+ sp := strings.Repeat(string(r), abs(n))
if style != nil {
sp = style.Styled(sp)
}
b := strings.Builder{}
- l := strings.Split(str, "\n")
-
- for i := range l {
+ isFirst := true
+ for line := range strings.SplitSeq(str, "\n") {
+ if isFirst {
+ isFirst = false
+ } else {
+ b.WriteRune('\n')
+ }
switch {
// pad right
case n > 0:
- b.WriteString(l[i])
+ b.WriteString(line)
b.WriteString(sp)
// pad left
default:
b.WriteString(sp)
- b.WriteString(l[i])
- }
-
- if i != len(l)-1 {
- b.WriteRune('\n')
+ b.WriteString(line)
}
}
return b.String()
}
-func max(a, b int) int { //nolint:unparam,predeclared
- if a > b {
- return a
- }
- return b
-}
-
-func min(a, b int) int { //nolint:predeclared
- if a < b {
- return a
- }
- return b
-}
-
func abs(a int) int {
if a < 0 {
return -a
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/terminal.go b/hack/tools/vendor/charm.land/lipgloss/v2/terminal.go
new file mode 100644
index 00000000000..a336abc7708
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/terminal.go
@@ -0,0 +1,124 @@
+package lipgloss
+
+import (
+ "fmt"
+ "image/color"
+ "io"
+ "strings"
+ "time"
+
+ uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/x/ansi"
+)
+
+// queryBackgroundColor queries the terminal for the background color.
+// If the terminal does not support querying the background color, nil is
+// returned.
+//
+// Note: you will need to set the input to raw mode before calling this
+// function.
+//
+// state, _ := term.MakeRaw(in.Fd())
+// defer term.Restore(in.Fd(), state)
+//
+// copied from x/term@v0.1.3.
+func queryBackgroundColor(in io.Reader, out io.Writer) (c color.Color, err error) {
+ err = queryTerminal(in, out, defaultQueryTimeout,
+ func(seq string, pa *ansi.Parser) bool {
+ switch {
+ case ansi.HasOscPrefix(seq):
+ switch pa.Command() {
+ case 11: // OSC 11
+ parts := strings.Split(string(pa.Data()), ";")
+ if len(parts) != 2 {
+ break // invalid, but we still need to parse the next sequence
+ }
+ c = ansi.XParseColor(parts[1])
+ }
+ case ansi.HasCsiPrefix(seq):
+ switch pa.Command() {
+ case ansi.Command('?', 0, 'c'): // DA1
+ return false
+ }
+ }
+ return true
+ }, ansi.RequestBackgroundColor+ansi.RequestPrimaryDeviceAttributes)
+ return
+}
+
+const defaultQueryTimeout = time.Second * 2
+
+// queryTerminalFilter is a function that filters input events using a type
+// switch. If false is returned, the QueryTerminal function will stop reading
+// input.
+type queryTerminalFilter func(seq string, pa *ansi.Parser) bool
+
+// queryTerminal queries the terminal for support of various features and
+// returns a list of response events.
+// Most of the time, you will need to set stdin to raw mode before calling this
+// function.
+// Note: This function will block until the terminal responds or the timeout
+// is reached.
+// copied from x/term@v0.1.3.
+func queryTerminal(
+ in io.Reader,
+ out io.Writer,
+ timeout time.Duration,
+ filter queryTerminalFilter,
+ query string,
+) error {
+ // We use [uv.NewCancelReader] because it uses a different Windows
+ // implementation than the on in the [cancelreader] library, which uses
+ // the Cancel IO API to cancel reads instead of using Overlapped IO.
+ rd, err := uv.NewCancelReader(in)
+ if err != nil {
+ return fmt.Errorf("could not create cancel reader: %w", err)
+ }
+
+ defer rd.Close() //nolint: errcheck
+
+ done := make(chan struct{}, 1)
+ defer close(done)
+ go func() {
+ select {
+ case <-done:
+ case <-time.After(timeout):
+ rd.Cancel()
+ }
+ }()
+
+ if _, err := io.WriteString(out, query); err != nil {
+ return fmt.Errorf("could not write query: %w", err)
+ }
+
+ pa := ansi.GetParser()
+ defer ansi.PutParser(pa)
+
+ var acc []byte // Accumulate partial responses before filtering
+ var buf [256]byte // 256 bytes should be enough for most responses
+ var state byte
+ for {
+ n, err := rd.Read(buf[:])
+ if err != nil {
+ return fmt.Errorf("could not read from input: %w", err)
+ }
+
+ p := buf[:]
+ for n > 0 {
+ seq, _, read, newState := ansi.DecodeSequence(p[:n], state, pa)
+ acc = append(acc, seq...)
+
+ if newState == ansi.NormalState {
+ if !filter(string(acc), pa) {
+ return nil
+ }
+
+ acc = acc[:0]
+ }
+
+ state = newState
+ n -= read
+ p = p[read:]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/unset.go b/hack/tools/vendor/charm.land/lipgloss/v2/unset.go
similarity index 91%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/unset.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/unset.go
index 1086e722686..b81ee882a01 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/unset.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/unset.go
@@ -19,8 +19,7 @@ func (s Style) UnsetItalic() Style {
// UnsetUnderline removes the underline style rule, if set.
func (s Style) UnsetUnderline() Style {
- s.unset(underlineKey)
- return s
+ return s.Underline(false)
}
// UnsetStrikethrough removes the strikethrough style rule, if set.
@@ -96,6 +95,13 @@ func (s Style) UnsetPadding() Style {
s.unset(paddingRightKey)
s.unset(paddingTopKey)
s.unset(paddingBottomKey)
+ s.unset(paddingCharKey)
+ return s
+}
+
+// UnsetPaddingChar removes the padding character style rule, if set.
+func (s Style) UnsetPaddingChar() Style {
+ s.unset(paddingCharKey)
return s
}
@@ -237,6 +243,20 @@ func (s Style) UnsetBorderLeftForeground() Style {
return s
}
+// UnsetBorderForegroundBlend removes the border blend foreground color rules,
+// if set.
+func (s Style) UnsetBorderForegroundBlend() Style {
+ s.unset(borderForegroundBlendKey)
+ return s
+}
+
+// UnsetBorderForegroundBlendOffset removes the border blend offset style rule,
+// if set.
+func (s Style) UnsetBorderForegroundBlendOffset() Style {
+ s.unset(borderForegroundBlendOffsetKey)
+ return s
+}
+
// UnsetBorderBackground removes all border background color styles, if
// set.
func (s Style) UnsetBorderBackground() Style {
@@ -324,6 +344,14 @@ func (s Style) UnsetTransform() Style {
return s
}
+// UnsetHyperlink removes the value set by Hyperlink.
+func (s Style) UnsetHyperlink() Style {
+ s.unset(linkKey)
+ s.unset(linkParamsKey)
+ s.link, s.linkParams = "", "" // save memory
+ return s
+}
+
// UnsetString sets the underlying string value to the empty string.
func (s Style) UnsetString() Style {
s.value = ""
diff --git a/hack/tools/vendor/github.com/charmbracelet/lipgloss/whitespace.go b/hack/tools/vendor/charm.land/lipgloss/v2/whitespace.go
similarity index 55%
rename from hack/tools/vendor/github.com/charmbracelet/lipgloss/whitespace.go
rename to hack/tools/vendor/charm.land/lipgloss/v2/whitespace.go
index 040dc98e65e..e353a076bae 100644
--- a/hack/tools/vendor/github.com/charmbracelet/lipgloss/whitespace.go
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/whitespace.go
@@ -4,24 +4,17 @@ import (
"strings"
"github.com/charmbracelet/x/ansi"
- "github.com/muesli/termenv"
)
// whitespace is a whitespace renderer.
type whitespace struct {
- re *Renderer
- style termenv.Style
chars string
+ style Style
}
-// newWhitespace creates a new whitespace renderer. The order of the options
-// matters, if you're using WithWhitespaceRenderer, make sure it comes first as
-// other options might depend on it.
-func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace {
- w := &whitespace{
- re: r,
- style: r.ColorProfile().String(),
- }
+// newWhitespace creates a new whitespace renderer.
+func newWhitespace(opts ...WhitespaceOption) *whitespace {
+ w := &whitespace{}
for _, opt := range opts {
opt(w)
}
@@ -41,11 +34,18 @@ func (w whitespace) render(width int) string {
// Cycle through runes and print them into the whitespace.
for i := 0; i < width; {
b.WriteRune(r[j])
+ // Measure the width of the rune we just wrote, ensuring we always
+ // make progress to avoid infinite loops with zero-width characters
+ // like tabs.
+ runeWidth := ansi.StringWidth(string(r[j]))
+ if runeWidth < 1 {
+ runeWidth = 1
+ }
+ i += runeWidth
j++
if j >= len(r) {
j = 0
}
- i += ansi.StringWidth(string(r[j]))
}
// Fill any extra gaps white spaces. This might be necessary if any runes
@@ -55,23 +55,16 @@ func (w whitespace) render(width int) string {
b.WriteString(strings.Repeat(" ", short))
}
- return w.style.Styled(b.String())
+ return w.style.Render(b.String())
}
// WhitespaceOption sets a styling rule for rendering whitespace.
type WhitespaceOption func(*whitespace)
-// WithWhitespaceForeground sets the color of the characters in the whitespace.
-func WithWhitespaceForeground(c TerminalColor) WhitespaceOption {
- return func(w *whitespace) {
- w.style = w.style.Foreground(c.color(w.re))
- }
-}
-
-// WithWhitespaceBackground sets the background color of the whitespace.
-func WithWhitespaceBackground(c TerminalColor) WhitespaceOption {
+// WithWhitespaceStyle sets the style for the whitespace.
+func WithWhitespaceStyle(s Style) WhitespaceOption {
return func(w *whitespace) {
- w.style = w.style.Background(c.color(w.re))
+ w.style = s
}
}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/wrap.go b/hack/tools/vendor/charm.land/lipgloss/v2/wrap.go
new file mode 100644
index 00000000000..ca0a1e239bc
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/wrap.go
@@ -0,0 +1,107 @@
+package lipgloss
+
+import (
+ "bytes"
+ "io"
+
+ uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/x/ansi"
+)
+
+// Wrap wraps the given string to the given width, preserving ANSI styles and links.
+func Wrap(s string, width int, breakpoints string) string {
+ var buf bytes.Buffer
+ s = ansi.Wrap(s, width, breakpoints)
+ w := NewWrapWriter(&buf)
+ defer w.Close() //nolint:errcheck
+ _, _ = io.WriteString(w, s)
+ return buf.String()
+}
+
+// WrapWriter is a writer that writes to a buffer and keeps track of the
+// current pen style and link state for the purpose of wrapping with newlines.
+//
+// When it encounters a newline, it resets the style and link, writes the
+// newline, and then reapplies the style and link to the next line.
+type WrapWriter struct {
+ w io.Writer
+ p *ansi.Parser
+ style uv.Style
+ link uv.Link
+}
+
+// NewWrapWriter returns a new [WrapWriter].
+func NewWrapWriter(w io.Writer) *WrapWriter {
+ pw := &WrapWriter{w: w}
+ pw.p = ansi.GetParser()
+ handleCsi := func(cmd ansi.Cmd, params ansi.Params) {
+ if cmd == 'm' {
+ uv.ReadStyle(params, &pw.style)
+ }
+ }
+ handleOsc := func(cmd int, data []byte) {
+ if cmd == 8 {
+ uv.ReadLink(data, &pw.link)
+ }
+ }
+ pw.p.SetHandler(ansi.Handler{
+ HandleCsi: handleCsi,
+ HandleOsc: handleOsc,
+ })
+ return pw
+}
+
+// Style returns the current pen style.
+func (w *WrapWriter) Style() uv.Style {
+ return w.style
+}
+
+// Link returns the current pen link.
+func (w *WrapWriter) Link() uv.Link {
+ return w.link
+}
+
+// Write writes to the buffer.
+func (w *WrapWriter) Write(p []byte) (int, error) {
+ for i := range p {
+ b := p[i]
+ w.p.Advance(b)
+ if b == '\n' {
+ if !w.style.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetStyle))
+ }
+ if !w.link.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetHyperlink()))
+ }
+ }
+
+ _, _ = w.w.Write([]byte{b})
+ if b == '\n' {
+ if !w.link.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.SetHyperlink(w.link.URL, w.link.Params)))
+ }
+ if !w.style.IsZero() {
+ _, _ = w.w.Write([]byte(w.style.String()))
+ }
+ }
+ }
+
+ return len(p), nil
+}
+
+// Close closes the writer, resets the style and link if necessary, and releases
+// its parser. Calling it is performance critical, but forgetting it does not
+// cause safety issues or leaks.
+func (w *WrapWriter) Close() error {
+ if !w.style.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetStyle))
+ }
+ if !w.link.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetHyperlink()))
+ }
+ if w.p != nil {
+ ansi.PutParser(w.p)
+ w.p = nil
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/charm.land/lipgloss/v2/writer.go b/hack/tools/vendor/charm.land/lipgloss/v2/writer.go
new file mode 100644
index 00000000000..78b48b8d3e0
--- /dev/null
+++ b/hack/tools/vendor/charm.land/lipgloss/v2/writer.go
@@ -0,0 +1,160 @@
+package lipgloss
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/charmbracelet/colorprofile"
+)
+
+// Writer is the default writer that prints to stdout, automatically
+// downsampling colors when necessary.
+var Writer = colorprofile.NewWriter(os.Stdout, os.Environ())
+
+// Println to stdout, automatically downsampling colors when necessary, ending
+// with a trailing newline.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("breakfast")
+//
+// Println("Time for a", str, "sandwich!")
+func Println(v ...any) (int, error) {
+ return fmt.Fprintln(Writer, v...) //nolint:wrapcheck
+}
+
+// Printf prints formatted text to stdout, automatically downsampling colors
+// when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("knuckle")
+//
+// Printf("Time for a %s sandwich!\n", str)
+func Printf(format string, v ...any) (int, error) {
+ return fmt.Fprintf(Writer, format, v...) //nolint:wrapcheck
+}
+
+// Print to stdout, automatically downsampling colors when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("Who wants marmalade?\n")
+//
+// Print(str)
+func Print(v ...any) (int, error) {
+ return fmt.Fprint(Writer, v...) //nolint:wrapcheck
+}
+
+// Fprint pritnts to the given writer, automatically downsampling colors when
+// necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("guzzle")
+//
+// Fprint(os.Stderr, "I %s horchata pretty much all the time.\n", str)
+func Fprint(w io.Writer, v ...any) (int, error) {
+ return fmt.Fprint(colorprofile.NewWriter(w, os.Environ()), v...) //nolint:wrapcheck
+}
+
+// Fprintln prints to the given writer, automatically downsampling colors when
+// necessary, and ending with a trailing newline.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("Sandwich time!")
+//
+// Fprintln(os.Stderr, str)
+func Fprintln(w io.Writer, v ...any) (int, error) {
+ return fmt.Fprintln(colorprofile.NewWriter(w, os.Environ()), v...) //nolint:wrapcheck
+}
+
+// Fprintf prints text to a writer, against the given format, automatically
+// downsampling colors when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("artichokes")
+//
+// Fprintf(os.Stderr, "I really love %s!\n", food)
+func Fprintf(w io.Writer, format string, v ...any) (int, error) {
+ return fmt.Fprintf(colorprofile.NewWriter(w, os.Environ()), format, v...) //nolint:wrapcheck
+}
+
+// Sprint returns a string for stdout, automatically downsampling colors when
+// necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Faint(true).
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("I love to eat")
+//
+// str = Sprint(str)
+func Sprint(v ...any) string {
+ var buf bytes.Buffer
+ w := colorprofile.Writer{
+ Forward: &buf,
+ Profile: Writer.Profile,
+ }
+ fmt.Fprint(&w, v...) //nolint:errcheck
+ return buf.String()
+}
+
+// Sprintln returns a string for stdout, automatically downsampling colors when
+// necessary, and ending with a trailing newline.
+//
+// Example:
+//
+// str := NewStyle().
+// Bold(true).
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("Yummy!")
+//
+// str = Sprintln(str)
+func Sprintln(v ...any) string {
+ var buf bytes.Buffer
+ w := colorprofile.Writer{
+ Forward: &buf,
+ Profile: Writer.Profile,
+ }
+ fmt.Fprintln(&w, v...) //nolint:errcheck
+ return buf.String()
+}
+
+// Sprintf returns a formatted string for stdout, automatically downsampling
+// colors when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Bold(true).
+// Foreground(lipgloss.Color("#fccaee")).
+// Render("Cantaloupe")
+//
+// str = Sprintf("I really love %s!", str)
+func Sprintf(format string, v ...any) string {
+ var buf bytes.Buffer
+ w := colorprofile.Writer{
+ Forward: &buf,
+ Profile: Writer.Profile,
+ }
+ fmt.Fprintf(&w, format, v...) //nolint:errcheck
+ return buf.String()
+}
diff --git a/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE
new file mode 100644
index 00000000000..a7e77cb28d3
--- /dev/null
+++ b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go
new file mode 100644
index 00000000000..68d1309890a
--- /dev/null
+++ b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go
@@ -0,0 +1,33 @@
+package util
+
+import (
+ "go/ast"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// IsChObj returns true if the input ast.Expr is of type clickhouse go driver
+func IsChObj(pass *analysis.Pass, expr ast.Expr, name string) bool {
+ t := pass.TypesInfo.TypeOf(expr)
+ if t == nil {
+ return false
+ }
+ named, ok := t.(*types.Named)
+ if !ok {
+ return false
+ }
+ obj := named.Obj()
+ if obj.Pkg() == nil {
+ return false
+ }
+ return obj.Pkg().Path() == "github.com/ClickHouse/clickhouse-go/v2/lib/driver" &&
+ obj.Name() == name
+}
+
+func IdentName(expr ast.Expr) string {
+ if id, ok := expr.(*ast.Ident); ok {
+ return id.Name
+ }
+ return ""
+}
diff --git a/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go
new file mode 100644
index 00000000000..3da2c55d6ba
--- /dev/null
+++ b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go
@@ -0,0 +1,182 @@
+package chbatchclose
+
+import (
+ "go/ast"
+ "go/token"
+ "os"
+ "strconv"
+
+ "github.com/ClickHouse/clickhouse-go-linter/internal/util"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+type analyzer struct {
+ // if true, report valid usages and log spurious but valid cases.
+ debug bool
+}
+
+func NewAnalyzer() *analysis.Analyzer {
+ debug, _ := strconv.ParseBool(os.Getenv("CH_GO_LINTER_DEBUG"))
+ a := analyzer{
+ debug: debug,
+ }
+ return &analysis.Analyzer{
+ Name: "chbatchclosecheck",
+ Doc: "chbatchclosecheck checks whether defer batch.Close() is called on ClickHouse driver Batch variables",
+ Run: a.run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ }
+}
+
+func (a *analyzer) run(pass *analysis.Pass) (any, error) {
+ insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ nodeFilter := []ast.Node{
+ (*ast.FuncDecl)(nil),
+ (*ast.FuncLit)(nil),
+ }
+
+ insp.Preorder(nodeFilter, func(n ast.Node) {
+ var body *ast.BlockStmt
+ switch fn := n.(type) {
+ case *ast.FuncDecl:
+ body = fn.Body
+ case *ast.FuncLit:
+ body = fn.Body
+ }
+
+ if body == nil {
+ return
+ }
+ a.checkFunc(pass, body)
+ })
+
+ return nil, nil
+}
+
+// batchUsage tracks whether a driver.Batch variable has a defer Close/Abort or is returned.
+type batchUsage struct {
+ assignPos token.Pos
+ deferredClose bool
+ returned bool
+}
+
+func (b *batchUsage) report(varName string, pass *analysis.Pass, debug bool) {
+ if b.assignPos == token.NoPos {
+ // no usage of Batch
+ return
+ }
+ if !b.deferredClose && !b.returned {
+ pass.Reportf(b.assignPos,
+ "clickhouse Batch %s must be closed defensively with defer %s.Close() after successful instantiation",
+ varName, varName)
+ } else if debug {
+ if b.deferredClose {
+ pass.Reportf(b.assignPos,
+ "clickhouse Batch %s is properly closed defensively after successful instantiation [valid]",
+ varName)
+ } else {
+ pass.Reportf(b.assignPos,
+ "clickhouse Batch %s is returned by the function [valid]",
+ varName)
+ }
+ }
+}
+
+// checkFunc analyzes a single function/closure body.
+// It does a single-pass collection of Batch assignments, defer Close/Abort calls, and return statements.
+// It does not descend into nested closures (they are handled as separate units by the Preorder visitor above).
+func (a *analyzer) checkFunc(pass *analysis.Pass, body *ast.BlockStmt) {
+ usages := map[string]*batchUsage{}
+
+ ast.Inspect(body, func(n ast.Node) bool {
+ if n == nil {
+ return false
+ }
+ // don't descend into nested closures
+ if n != body {
+ if _, ok := n.(*ast.FuncLit); ok {
+ return false
+ }
+ }
+
+ switch node := n.(type) {
+ case *ast.AssignStmt:
+ a.handleAssign(pass, node, usages)
+ case *ast.DeferStmt:
+ handleDefer(node, usages)
+ case *ast.ReturnStmt:
+ handleReturn(node, usages)
+ }
+
+ return true
+ })
+
+ // remaining usages that were not flushed
+ for varName, u := range usages {
+ u.report(varName, pass, a.debug)
+ }
+}
+
+// handleAssign checks if any LHS variable in the assignment is of type driver.Batch.
+// If a tracked variable is reassigned, it flushes/reports the previous tracking first.
+func (a *analyzer) handleAssign(pass *analysis.Pass, assign *ast.AssignStmt, usages map[string]*batchUsage) {
+ for _, lhs := range assign.Lhs {
+ name := util.IdentName(lhs)
+ if name == "" {
+ continue
+ }
+ if name == "_" && util.IsChObj(pass, lhs, "Batch") {
+ pass.Reportf(assign.Pos(), "clickhouse Batch assigned to blank identifier. Connection leak. clickhouse Batch must be instantiated and closed defensively with defer batch.Close() after successful instantiation")
+ continue
+ }
+
+ // if this var was already tracked, flush previous usage before re-tracking
+ if u, ok := usages[name]; ok {
+ u.report(name, pass, a.debug)
+ delete(usages, name)
+ }
+
+ if util.IsChObj(pass, lhs, "Batch") {
+ usages[name] = &batchUsage{assignPos: assign.Pos()}
+ }
+ }
+}
+
+// handleDefer checks if a defer statement calls Close() or Abort() on a tracked Batch variable.
+func handleDefer(deferStmt *ast.DeferStmt, usages map[string]*batchUsage) {
+ call := deferStmt.Call
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+ varName := util.IdentName(sel.X)
+ if varName == "" {
+ return
+ }
+ u, exists := usages[varName]
+ if !exists {
+ return
+ }
+
+ switch sel.Sel.Name {
+ case "Close":
+ u.deferredClose = true
+ }
+}
+
+// handleReturn checks if any return value is a tracked Batch variable.
+func handleReturn(ret *ast.ReturnStmt, usages map[string]*batchUsage) {
+ for _, result := range ret.Results {
+ name := util.IdentName(result)
+ if name == "" {
+ continue
+ }
+ if u, exists := usages[name]; exists {
+ u.returned = true
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go
new file mode 100644
index 00000000000..bba0f82ad8f
--- /dev/null
+++ b/hack/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go
@@ -0,0 +1,162 @@
+package chrowserr
+
+import (
+ "go/ast"
+ "go/token"
+ "log"
+ "os"
+ "strconv"
+
+ "github.com/ClickHouse/clickhouse-go-linter/internal/util"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+type analyzer struct {
+ // if true, report valid usages and log spurious but valid cases.
+ debug bool
+}
+
+func NewAnalyzer() *analysis.Analyzer {
+ debug, _ := strconv.ParseBool(os.Getenv("CH_GO_LINTER_DEBUG"))
+ a := analyzer{
+ debug: debug,
+ }
+ return &analysis.Analyzer{
+ Name: "chrowserrcheck",
+ Doc: "chrowserrcheck checks whether ClickHouse driver Rows.Err is called after Rows.Next()",
+ Run: a.run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ }
+}
+
+func (a *analyzer) run(pass *analysis.Pass) (any, error) {
+ insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ nodeFilter := []ast.Node{
+ (*ast.FuncDecl)(nil),
+ (*ast.FuncLit)(nil),
+ }
+
+ insp.Preorder(nodeFilter, func(n ast.Node) {
+ var body *ast.BlockStmt
+ switch fn := n.(type) {
+ case *ast.FuncDecl:
+ body = fn.Body
+ case *ast.FuncLit:
+ body = fn.Body
+ }
+
+ if body == nil {
+ return
+ }
+ a.checkFunc(pass, body)
+ })
+
+ return nil, nil
+}
+
+// rowsUsage tracks Next/Err usage observations for a single Rows variable within a function.
+type rowsUsage struct {
+ nextPos token.Pos
+ errCalled bool
+}
+
+func (r *rowsUsage) report(varName string, pass *analysis.Pass, debug bool) {
+ if r.nextPos == token.NoPos {
+ // no usage of rows.Next()
+ return
+ }
+ // rows.Next() was called
+ if !r.errCalled {
+ pass.Reportf(r.nextPos,
+ "clickhouse %s.Err() must be checked after %s.Next()",
+ varName, varName)
+ } else if debug {
+ // for dev purpose - list valid usages
+ pass.Reportf(r.nextPos,
+ "clickhouse %s.Err() is properly called after %s.Next() [valid]",
+ varName, varName)
+ }
+}
+
+// checkFunc analyzes a single function/closure body.
+// It does a single-pass collection of Next() and Err() calls,
+// it does not descend into nested closures (they are handled as separate units by the Preorder visitor above).
+func (a *analyzer) checkFunc(pass *analysis.Pass, body *ast.BlockStmt) {
+ usages := map[string]*rowsUsage{}
+ ast.Inspect(body, func(n ast.Node) bool {
+ if n == nil {
+ return false
+ }
+ // don't descend into nested closures
+ if n != body {
+ if _, ok := n.(*ast.FuncLit); ok {
+ return false
+ }
+ }
+
+ // if a tracked var appears in an assignment, it means it is re-assigned - run lint report and flush var from usages.
+ if assign, ok := n.(*ast.AssignStmt); ok {
+ for _, lhs := range assign.Lhs {
+ name := util.IdentName(lhs)
+ if name == "" {
+ continue
+ }
+ if s, ok := usages[name]; ok {
+ s.report(name, pass, a.debug)
+ }
+ delete(usages, name)
+ }
+ // let ast.Inspect continue
+ return true
+ }
+
+ // handle CH driver method calls Next() and Err() - skip everything else
+ call, ok := n.(*ast.CallExpr)
+ if !ok {
+ return true
+ }
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return true
+ }
+ varName := util.IdentName(sel.X)
+ if varName == "" {
+ return true
+ }
+ if !util.IsChObj(pass, sel.X, "Rows") {
+ return true
+ }
+
+ // call is a CH driver Rows method call
+ switch sel.Sel.Name {
+ case "Next":
+ if _, exists := usages[varName]; !exists {
+ usages[varName] = &rowsUsage{nextPos: call.Pos()}
+ } else if a.debug {
+ log.Printf("Rows.Next() is written multiple times with no re-assignment. Valid but rare usage. If this observation is not correct, it is a bug in this linter library. Please reach out to maintainer.")
+ // in particular could be a bug in the re-assignment detection
+ }
+ case "Err":
+ if s, exists := usages[varName]; exists {
+ s.errCalled = true
+ s.report(varName, pass, a.debug)
+ delete(usages, varName)
+ } else if a.debug {
+ log.Printf("%s.Err() is called on ClickHouse Rows %s but %s.Next() was never called. Valid but unexpected usage. If this observation is not correct, it is a bug in this linter library. Please reach out to maintainer.",
+ varName, varName, varName)
+ // in particular could be a bug in the re-assignment detection
+ }
+
+ }
+
+ return true
+ })
+
+ // remaining usages that were not flushed (misusages only, as correct usages are flushed already)
+ for varName, s := range usages {
+ s.report(varName, pass, a.debug)
+ }
+}
diff --git a/hack/tools/vendor/github.com/Masterminds/semver/v3/.gitignore b/hack/tools/vendor/github.com/Masterminds/semver/v3/.gitignore
index 6b061e6174b..35f0e5a3a48 100644
--- a/hack/tools/vendor/github.com/Masterminds/semver/v3/.gitignore
+++ b/hack/tools/vendor/github.com/Masterminds/semver/v3/.gitignore
@@ -1 +1,2 @@
-_fuzz/
\ No newline at end of file
+_fuzz/
+.devcontainer/
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml b/hack/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml
index fbc6332592f..24277f3acab 100644
--- a/hack/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml
+++ b/hack/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml
@@ -1,27 +1,42 @@
-run:
- deadline: 2m
-
+version: "2"
linters:
- disable-all: true
+ default: none
enable:
- - misspell
- - govet
- - staticcheck
+ - dupl
- errcheck
- - unparam
+ - gocyclo
+ - gosec
+ - govet
- ineffassign
+ - misspell
- nakedret
- - gocyclo
- - dupl
- - goimports
- revive
- - gosec
- - gosimple
- - typecheck
+ - staticcheck
+ - unparam
- unused
-
-linters-settings:
- gofmt:
- simplify: true
- dupl:
- threshold: 600
+ settings:
+ dupl:
+ threshold: 600
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - goimports
+ settings:
+ gofmt:
+ simplify: true
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
diff --git a/hack/tools/vendor/github.com/Masterminds/semver/v3/constraints.go b/hack/tools/vendor/github.com/Masterminds/semver/v3/constraints.go
index 8b7a10f8369..e8353bc4698 100644
--- a/hack/tools/vendor/github.com/Masterminds/semver/v3/constraints.go
+++ b/hack/tools/vendor/github.com/Masterminds/semver/v3/constraints.go
@@ -21,21 +21,43 @@ type Constraints struct {
IncludePrerelease bool
}
+// MaxConstraintLen is the maximum allowed length of a constraint string.
+const MaxConstraintLen = 512
+
+// MaxConstraintGroups is the maximum number of OR groups allowed in a
+// constraint string.
+const MaxConstraintGroups = 32
+
+// ErrConstraintTooLong is returned when a constraint string exceeds the
+// maximum allowed length.
+var ErrConstraintTooLong = fmt.Errorf("constraint string is too long (max %d bytes)", MaxConstraintLen)
+
+// ErrTooManyConstraintGroups is returned when a constraint string contains
+// too many OR groups.
+var ErrTooManyConstraintGroups = fmt.Errorf("too many constraint groups (max %d)", MaxConstraintGroups)
+
// NewConstraint returns a Constraints instance that a Version instance can
// be checked against. If there is a parse error it will be returned.
func NewConstraint(c string) (*Constraints, error) {
+ if len(c) > MaxConstraintLen {
+ return nil, ErrConstraintTooLong
+ }
+
// Rewrite - ranges into a comparison operation.
c = rewriteRange(c)
ors := strings.Split(c, "||")
+ if len(ors) > MaxConstraintGroups {
+ return nil, ErrTooManyConstraintGroups
+ }
lenors := len(ors)
or := make([][]*constraint, lenors)
hasPre := make([]bool, lenors)
for k, v := range ors {
// Validate the segment
if !validConstraintRegex.MatchString(v) {
- return nil, fmt.Errorf("improper constraint: %s", v)
+ return nil, fmt.Errorf("improper constraint: %q", v)
}
cs := findConstraintRegex.FindAllString(v, -1)
@@ -104,9 +126,9 @@ func (cs Constraints) Validate(v *Version) (bool, []error) {
for _, c := range o {
// Before running the check handle the case there the version is
// a prerelease and the check is not searching for prereleases.
- if !(cs.IncludePrerelease || cs.containsPre[i]) && v.pre != "" {
+ if !cs.IncludePrerelease && !cs.containsPre[i] && v.pre != "" {
if !prerelesase {
- em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ em := fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
e = append(e, em)
prerelesase = true
}
@@ -258,7 +280,7 @@ func parseConstraint(c string) (*constraint, error) {
if len(c) > 0 {
m := constraintRegex.FindStringSubmatch(c)
if m == nil {
- return nil, fmt.Errorf("improper constraint: %s", c)
+ return nil, fmt.Errorf("improper constraint: %q", c)
}
cs := &constraint{
@@ -325,7 +347,7 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
if c.dirty {
@@ -335,7 +357,7 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error
if c.con.Minor() != v.Minor() && !c.minorDirty {
return true, nil
} else if c.minorDirty {
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
} else if c.con.Patch() != v.Patch() && !c.patchDirty {
return true, nil
} else if c.patchDirty {
@@ -345,15 +367,15 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
}
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
}
}
eq := v.Equal(c.con)
if eq {
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
}
return true, nil
@@ -364,7 +386,7 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
@@ -374,17 +396,17 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
}
if v.Major() > c.con.Major() {
return true, nil
} else if v.Major() < c.con.Major() {
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
} else if c.minorDirty {
// This is a range case such as >11. When the version is something like
// 11.1.0 is it not > 11. For that we would need 12 or higher
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
} else if c.patchDirty {
// This is for ranges such as >11.1. A version of 11.1.1 is not greater
// which one of 11.2.1 is greater
@@ -392,7 +414,7 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
}
// If we have gotten here we are not comparing pre-preleases and can use the
@@ -401,21 +423,21 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
}
func constraintLessThan(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) < 0
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than or equal to %q", v, c.orig)
}
func constraintGreaterThanEqual(v *Version, c *constraint, includePre bool) (bool, error) {
@@ -423,21 +445,21 @@ func constraintGreaterThanEqual(v *Version, c *constraint, includePre bool) (boo
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) >= 0
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than %q", v, c.orig)
}
func constraintLessThanEqual(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
@@ -447,13 +469,13 @@ func constraintLessThanEqual(v *Version, c *constraint, includePre bool) (bool,
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is greater than %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than %q", v, c.orig)
}
if v.Major() > c.con.Major() {
- return false, fmt.Errorf("%s is greater than %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than %q", v, c.orig)
} else if v.Major() == c.con.Major() && v.Minor() > c.con.Minor() && !c.minorDirty {
- return false, fmt.Errorf("%s is greater than %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than %q", v, c.orig)
}
return true, nil
@@ -469,11 +491,11 @@ func constraintTilde(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
if v.LessThan(c.con) {
- return false, fmt.Errorf("%s is less than %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than %q", v, c.orig)
}
// ~0.0.0 is a special case where all constraints are accepted. It's
@@ -484,11 +506,11 @@ func constraintTilde(v *Version, c *constraint, includePre bool) (bool, error) {
}
if v.Major() != c.con.Major() {
- return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig)
}
if v.Minor() != c.con.Minor() && !c.minorDirty {
- return false, fmt.Errorf("%s does not have same major and minor version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major and minor version as %q", v, c.orig)
}
return true, nil
@@ -500,7 +522,7 @@ func constraintTildeOrEqual(v *Version, c *constraint, includePre bool) (bool, e
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
if c.dirty {
@@ -512,7 +534,7 @@ func constraintTildeOrEqual(v *Version, c *constraint, includePre bool) (bool, e
return true, nil
}
- return false, fmt.Errorf("%s is not equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is not equal to %q", v, c.orig)
}
// ^* --> (any)
@@ -528,12 +550,12 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
// This less than handles prereleases
if v.LessThan(c.con) {
- return false, fmt.Errorf("%s is less than %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than %q", v, c.orig)
}
var eq bool
@@ -548,12 +570,12 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
if eq {
return true, nil
}
- return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig)
}
// ^ when the major is 0 and minor > 0 is >=0.y.z < 0.y+1
if c.con.Major() == 0 && v.Major() > 0 {
- return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig)
}
// If the con Minor is > 0 it is not dirty
if c.con.Minor() > 0 || c.patchDirty {
@@ -561,11 +583,11 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
if eq {
return true, nil
}
- return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig)
+ return false, fmt.Errorf("%q does not have same minor version as %q. Expected minor versions to match when constraint major version is 0", v, c.orig)
}
// ^ when the minor is 0 and minor > 0 is =0.0.z
if c.con.Minor() == 0 && v.Minor() > 0 {
- return false, fmt.Errorf("%s does not have same minor version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same minor version as %q", v, c.orig)
}
// At this point the major is 0 and the minor is 0 and not dirty. The patch
@@ -574,7 +596,7 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
if eq {
return true, nil
}
- return false, fmt.Errorf("%s does not equal %s. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
+ return false, fmt.Errorf("%q does not equal %q. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
}
func isX(x string) bool {
diff --git a/hack/tools/vendor/github.com/Masterminds/semver/v3/version.go b/hack/tools/vendor/github.com/Masterminds/semver/v3/version.go
index 7a3ba738876..da428760ce6 100644
--- a/hack/tools/vendor/github.com/Masterminds/semver/v3/version.go
+++ b/hack/tools/vendor/github.com/Masterminds/semver/v3/version.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "math"
"regexp"
"strconv"
"strings"
@@ -48,8 +49,16 @@ var (
// ErrInvalidPrerelease is returned when the pre-release is an invalid format
ErrInvalidPrerelease = errors.New("invalid prerelease string")
+
+ // ErrVersionTooLong is returned when a version string exceeds the
+ // maximum allowed length.
+ ErrVersionTooLong = fmt.Errorf("version string is too long (max %d bytes)", MaxVersionLen)
)
+// MaxVersionLen is the maximum allowed length of a version string. This guards
+// against unbounded input causing excessive memory allocations during parsing.
+const MaxVersionLen = 256
+
// semVerRegex is the regular expression used to parse a semantic version.
// This is not the official regex from the semver spec. It has been modified to allow for loose handling
// where versions like 2.1 are detected.
@@ -94,6 +103,10 @@ func StrictNewVersion(v string) (*Version, error) {
return nil, ErrEmptyString
}
+ if len(v) > MaxVersionLen {
+ return nil, ErrVersionTooLong
+ }
+
// Split the parts into [0]major, [1]minor, and [2]patch,prerelease,build
parts := strings.SplitN(v, ".", 3)
if len(parts) != 3 {
@@ -161,6 +174,9 @@ func StrictNewVersion(v string) (*Version, error) {
// attempts to convert it to SemVer. If you want to validate it was a strict
// semantic version at parse time see StrictNewVersion().
func NewVersion(v string) (*Version, error) {
+ if len(v) > MaxVersionLen {
+ return nil, ErrVersionTooLong
+ }
if CoerceNewVersion {
return coerceNewVersion(v)
}
@@ -289,6 +305,8 @@ func coerceNewVersion(v string) (*Version, error) {
// New creates a new instance of Version with each of the parts passed in as
// arguments instead of parsing a version string.
+// Note, New does not validate prerelease or metadata. Incorrect information can
+// be passed in.
func New(major, minor, patch uint64, pre, metadata string) *Version {
v := Version{
major: major,
@@ -301,6 +319,7 @@ func New(major, minor, patch uint64, pre, metadata string) *Version {
v.original = v.String()
+ // TODO: In the next semver major version validate the pre and metadata. Return error if there is one.
return &v
}
@@ -388,6 +407,9 @@ func (v Version) IncPatch() Version {
} else {
vNext.metadata = ""
vNext.pre = ""
+ if v.patch == math.MaxUint64 {
+ panic("patch version increment would overflow uint64")
+ }
vNext.patch = v.patch + 1
}
vNext.original = v.originalVPrefix() + "" + vNext.String()
@@ -404,6 +426,9 @@ func (v Version) IncMinor() Version {
vNext.metadata = ""
vNext.pre = ""
vNext.patch = 0
+ if v.minor == math.MaxUint64 {
+ panic("minor version increment would overflow uint64")
+ }
vNext.minor = v.minor + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
@@ -421,6 +446,9 @@ func (v Version) IncMajor() Version {
vNext.pre = ""
vNext.patch = 0
vNext.minor = 0
+ if v.major == math.MaxUint64 {
+ panic("major version increment would overflow uint64")
+ }
vNext.major = v.major + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
@@ -568,7 +596,16 @@ func (v Version) MarshalText() ([]byte, error) {
// Scan implements the SQL.Scanner interface.
func (v *Version) Scan(value interface{}) error {
var s string
- s, _ = value.(string)
+ switch t := value.(type) {
+ case string:
+ s = t
+ case []byte:
+ s = string(t)
+ case nil:
+ return fmt.Errorf("cannot scan nil into Version")
+ default:
+ return fmt.Errorf("unsupported Scan type %T", value)
+ }
temp, err := NewVersion(s)
if err != nil {
return err
diff --git a/hack/tools/vendor/github.com/a8m/envsubst/parse/parse.go b/hack/tools/vendor/github.com/a8m/envsubst/parse/parse.go
index 8b9b427a5d1..522f5ad51d7 100644
--- a/hack/tools/vendor/github.com/a8m/envsubst/parse/parse.go
+++ b/hack/tools/vendor/github.com/a8m/envsubst/parse/parse.go
@@ -11,11 +11,11 @@ type Mode int
// Mode for parser behaviour
const (
- Quick Mode = iota // stop parsing after first error encoutered and return
+ Quick Mode = iota // stop parsing after first error encountered and return
AllErrors // report all errors
)
-// The restrictions option controls the parsring restriction.
+// The restrictions option controls the parsing restriction.
type Restrictions struct {
NoUnset bool
NoEmpty bool
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/.gitignore b/hack/tools/vendor/github.com/agext/levenshtein/.gitignore
new file mode 100644
index 00000000000..404365f638f
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/.gitignore
@@ -0,0 +1,2 @@
+README.html
+coverage.out
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/.travis.yml b/hack/tools/vendor/github.com/agext/levenshtein/.travis.yml
new file mode 100644
index 00000000000..95be94af9f3
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/.travis.yml
@@ -0,0 +1,70 @@
+language: go
+sudo: false
+go:
+ - 1.8
+ - 1.7.5
+ - 1.7.4
+ - 1.7.3
+ - 1.7.2
+ - 1.7.1
+ - 1.7
+ - tip
+ - 1.6.4
+ - 1.6.3
+ - 1.6.2
+ - 1.6.1
+ - 1.6
+ - 1.5.4
+ - 1.5.3
+ - 1.5.2
+ - 1.5.1
+ - 1.5
+ - 1.4.3
+ - 1.4.2
+ - 1.4.1
+ - 1.4
+ - 1.3.3
+ - 1.3.2
+ - 1.3.1
+ - 1.3
+ - 1.2.2
+ - 1.2.1
+ - 1.2
+ - 1.1.2
+ - 1.1.1
+ - 1.1
+before_install:
+ - go get github.com/mattn/goveralls
+script:
+ - $HOME/gopath/bin/goveralls -service=travis-ci
+notifications:
+ email:
+ on_success: never
+matrix:
+ fast_finish: true
+ allow_failures:
+ - go: tip
+ - go: 1.6.4
+ - go: 1.6.3
+ - go: 1.6.2
+ - go: 1.6.1
+ - go: 1.6
+ - go: 1.5.4
+ - go: 1.5.3
+ - go: 1.5.2
+ - go: 1.5.1
+ - go: 1.5
+ - go: 1.4.3
+ - go: 1.4.2
+ - go: 1.4.1
+ - go: 1.4
+ - go: 1.3.3
+ - go: 1.3.2
+ - go: 1.3.1
+ - go: 1.3
+ - go: 1.2.2
+ - go: 1.2.1
+ - go: 1.2
+ - go: 1.1.2
+ - go: 1.1.1
+ - go: 1.1
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/DCO b/hack/tools/vendor/github.com/agext/levenshtein/DCO
new file mode 100644
index 00000000000..716561d5d28
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/DCO
@@ -0,0 +1,36 @@
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+660 York Street, Suite 102,
+San Francisco, CA 94110 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+(c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+(d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/LICENSE b/hack/tools/vendor/github.com/agext/levenshtein/LICENSE
new file mode 100644
index 00000000000..261eeb9e9f8
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/MAINTAINERS b/hack/tools/vendor/github.com/agext/levenshtein/MAINTAINERS
new file mode 100644
index 00000000000..726c2afb321
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/MAINTAINERS
@@ -0,0 +1 @@
+Alex Bucataru (@AlexBucataru)
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/NOTICE b/hack/tools/vendor/github.com/agext/levenshtein/NOTICE
new file mode 100644
index 00000000000..eaffaab94c4
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/NOTICE
@@ -0,0 +1,5 @@
+Alrux Go EXTensions (AGExt) - package levenshtein
+Copyright 2016 ALRUX Inc.
+
+This product includes software developed at ALRUX Inc.
+(http://www.alrux.com/).
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/README.md b/hack/tools/vendor/github.com/agext/levenshtein/README.md
new file mode 100644
index 00000000000..90509c2a20d
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/README.md
@@ -0,0 +1,38 @@
+# A Go package for calculating the Levenshtein distance between two strings
+
+[](https://github.com/agext/levenshtein/releases/latest)
+[](https://godoc.org/github.com/agext/levenshtein)
+[](https://travis-ci.org/agext/levenshtein)
+[](https://coveralls.io/github/agext/levenshtein)
+[](https://goreportcard.com/report/github.com/agext/levenshtein)
+
+
+This package implements distance and similarity metrics for strings, based on the Levenshtein measure, in [Go](http://golang.org).
+
+## Project Status
+
+v1.2.1 Stable: Guaranteed no breaking changes to the API in future v1.x releases. Probably safe to use in production, though provided on "AS IS" basis.
+
+This package is being actively maintained. If you encounter any problems or have any suggestions for improvement, please [open an issue](https://github.com/agext/levenshtein/issues). Pull requests are welcome.
+
+## Overview
+
+The Levenshtein `Distance` between two strings is the minimum total cost of edits that would convert the first string into the second. The allowed edit operations are insertions, deletions, and substitutions, all at character (one UTF-8 code point) level. Each operation has a default cost of 1, but each can be assigned its own cost equal to or greater than 0.
+
+A `Distance` of 0 means the two strings are identical, and the higher the value the more different the strings. Since in practice we are interested in finding if the two strings are "close enough", it often does not make sense to continue the calculation once the result is mathematically guaranteed to exceed a desired threshold. Providing this value to the `Distance` function allows it to take a shortcut and return a lower bound instead of an exact cost when the threshold is exceeded.
+
+The `Similarity` function calculates the distance, then converts it into a normalized metric within the range 0..1, with 1 meaning the strings are identical, and 0 that they have nothing in common. A minimum similarity threshold can be provided to speed up the calculation of the metric for strings that are far too dissimilar for the purpose at hand. All values under this threshold are rounded down to 0.
+
+The `Match` function provides a similarity metric, with the same range and meaning as `Similarity`, but with a bonus for string pairs that share a common prefix and have a similarity above a "bonus threshold". It uses the same method as proposed by Winkler for the Jaro distance, and the reasoning behind it is that these string pairs are very likely spelling variations or errors, and they are more closely linked than the edit distance alone would suggest.
+
+The underlying `Calculate` function is also exported, to allow the building of other derivative metrics, if needed.
+
+## Installation
+
+```
+go get github.com/agext/levenshtein
+```
+
+## License
+
+Package levenshtein is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/levenshtein.go b/hack/tools/vendor/github.com/agext/levenshtein/levenshtein.go
new file mode 100644
index 00000000000..df69ce70165
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/levenshtein.go
@@ -0,0 +1,290 @@
+// Copyright 2016 ALRUX Inc.
+//
+// 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 levenshtein implements distance and similarity metrics for strings, based on the Levenshtein measure.
+
+The Levenshtein `Distance` between two strings is the minimum total cost of edits that would convert the first string into the second. The allowed edit operations are insertions, deletions, and substitutions, all at character (one UTF-8 code point) level. Each operation has a default cost of 1, but each can be assigned its own cost equal to or greater than 0.
+
+A `Distance` of 0 means the two strings are identical, and the higher the value the more different the strings. Since in practice we are interested in finding if the two strings are "close enough", it often does not make sense to continue the calculation once the result is mathematically guaranteed to exceed a desired threshold. Providing this value to the `Distance` function allows it to take a shortcut and return a lower bound instead of an exact cost when the threshold is exceeded.
+
+The `Similarity` function calculates the distance, then converts it into a normalized metric within the range 0..1, with 1 meaning the strings are identical, and 0 that they have nothing in common. A minimum similarity threshold can be provided to speed up the calculation of the metric for strings that are far too dissimilar for the purpose at hand. All values under this threshold are rounded down to 0.
+
+The `Match` function provides a similarity metric, with the same range and meaning as `Similarity`, but with a bonus for string pairs that share a common prefix and have a similarity above a "bonus threshold". It uses the same method as proposed by Winkler for the Jaro distance, and the reasoning behind it is that these string pairs are very likely spelling variations or errors, and they are more closely linked than the edit distance alone would suggest.
+
+The underlying `Calculate` function is also exported, to allow the building of other derivative metrics, if needed.
+*/
+package levenshtein
+
+// Calculate determines the Levenshtein distance between two strings, using
+// the given costs for each edit operation. It returns the distance along with
+// the lengths of the longest common prefix and suffix.
+//
+// If maxCost is non-zero, the calculation stops as soon as the distance is determined
+// to be greater than maxCost. Therefore, any return value higher than maxCost is a
+// lower bound for the actual distance.
+func Calculate(str1, str2 []rune, maxCost, insCost, subCost, delCost int) (dist, prefixLen, suffixLen int) {
+ l1, l2 := len(str1), len(str2)
+ // trim common prefix, if any, as it doesn't affect the distance
+ for ; prefixLen < l1 && prefixLen < l2; prefixLen++ {
+ if str1[prefixLen] != str2[prefixLen] {
+ break
+ }
+ }
+ str1, str2 = str1[prefixLen:], str2[prefixLen:]
+ l1 -= prefixLen
+ l2 -= prefixLen
+ // trim common suffix, if any, as it doesn't affect the distance
+ for 0 < l1 && 0 < l2 {
+ if str1[l1-1] != str2[l2-1] {
+ str1, str2 = str1[:l1], str2[:l2]
+ break
+ }
+ l1--
+ l2--
+ suffixLen++
+ }
+ // if the first string is empty, the distance is the length of the second string times the cost of insertion
+ if l1 == 0 {
+ dist = l2 * insCost
+ return
+ }
+ // if the second string is empty, the distance is the length of the first string times the cost of deletion
+ if l2 == 0 {
+ dist = l1 * delCost
+ return
+ }
+
+ // variables used in inner "for" loops
+ var y, dy, c, l int
+
+ // if maxCost is greater than or equal to the maximum possible distance, it's equivalent to 'unlimited'
+ if maxCost > 0 {
+ if subCost < delCost+insCost {
+ if maxCost >= l1*subCost+(l2-l1)*insCost {
+ maxCost = 0
+ }
+ } else {
+ if maxCost >= l1*delCost+l2*insCost {
+ maxCost = 0
+ }
+ }
+ }
+
+ if maxCost > 0 {
+ // prefer the longer string first, to minimize time;
+ // a swap also transposes the meanings of insertion and deletion.
+ if l1 < l2 {
+ str1, str2, l1, l2, insCost, delCost = str2, str1, l2, l1, delCost, insCost
+ }
+
+ // the length differential times cost of deletion is a lower bound for the cost;
+ // if it is higher than the maxCost, there is no point going into the main calculation.
+ if dist = (l1 - l2) * delCost; dist > maxCost {
+ return
+ }
+
+ d := make([]int, l1+1)
+
+ // offset and length of d in the current row
+ doff, dlen := 0, 1
+ for y, dy = 1, delCost; y <= l1 && dy <= maxCost; dlen++ {
+ d[y] = dy
+ y++
+ dy = y * delCost
+ }
+ // fmt.Printf("%q -> %q: init doff=%d dlen=%d d[%d:%d]=%v\n", str1, str2, doff, dlen, doff, doff+dlen, d[doff:doff+dlen])
+
+ for x := 0; x < l2; x++ {
+ dy, d[doff] = d[doff], d[doff]+insCost
+ for d[doff] > maxCost && dlen > 0 {
+ if str1[doff] != str2[x] {
+ dy += subCost
+ }
+ doff++
+ dlen--
+ if c = d[doff] + insCost; c < dy {
+ dy = c
+ }
+ dy, d[doff] = d[doff], dy
+ }
+ for y, l = doff, doff+dlen-1; y < l; dy, d[y] = d[y], dy {
+ if str1[y] != str2[x] {
+ dy += subCost
+ }
+ if c = d[y] + delCost; c < dy {
+ dy = c
+ }
+ y++
+ if c = d[y] + insCost; c < dy {
+ dy = c
+ }
+ }
+ if y < l1 {
+ if str1[y] != str2[x] {
+ dy += subCost
+ }
+ if c = d[y] + delCost; c < dy {
+ dy = c
+ }
+ for ; dy <= maxCost && y < l1; dy, d[y] = dy+delCost, dy {
+ y++
+ dlen++
+ }
+ }
+ // fmt.Printf("%q -> %q: x=%d doff=%d dlen=%d d[%d:%d]=%v\n", str1, str2, x, doff, dlen, doff, doff+dlen, d[doff:doff+dlen])
+ if dlen == 0 {
+ dist = maxCost + 1
+ return
+ }
+ }
+ if doff+dlen-1 < l1 {
+ dist = maxCost + 1
+ return
+ }
+ dist = d[l1]
+ } else {
+ // ToDo: This is O(l1*l2) time and O(min(l1,l2)) space; investigate if it is
+ // worth to implement diagonal approach - O(l1*(1+dist)) time, up to O(l1*l2) space
+ // http://www.csse.monash.edu.au/~lloyd/tildeStrings/Alignment/92.IPL.html
+
+ // prefer the shorter string first, to minimize space; time is O(l1*l2) anyway;
+ // a swap also transposes the meanings of insertion and deletion.
+ if l1 > l2 {
+ str1, str2, l1, l2, insCost, delCost = str2, str1, l2, l1, delCost, insCost
+ }
+ d := make([]int, l1+1)
+
+ for y = 1; y <= l1; y++ {
+ d[y] = y * delCost
+ }
+ for x := 0; x < l2; x++ {
+ dy, d[0] = d[0], d[0]+insCost
+ for y = 0; y < l1; dy, d[y] = d[y], dy {
+ if str1[y] != str2[x] {
+ dy += subCost
+ }
+ if c = d[y] + delCost; c < dy {
+ dy = c
+ }
+ y++
+ if c = d[y] + insCost; c < dy {
+ dy = c
+ }
+ }
+ }
+ dist = d[l1]
+ }
+
+ return
+}
+
+// Distance returns the Levenshtein distance between str1 and str2, using the
+// default or provided cost values. Pass nil for the third argument to use the
+// default cost of 1 for all three operations, with no maximum.
+func Distance(str1, str2 string, p *Params) int {
+ if p == nil {
+ p = defaultParams
+ }
+ dist, _, _ := Calculate([]rune(str1), []rune(str2), p.maxCost, p.insCost, p.subCost, p.delCost)
+ return dist
+}
+
+// Similarity returns a score in the range of 0..1 for how similar the two strings are.
+// A score of 1 means the strings are identical, and 0 means they have nothing in common.
+//
+// A nil third argument uses the default cost of 1 for all three operations.
+//
+// If a non-zero MinScore value is provided in the parameters, scores lower than it
+// will be returned as 0.
+func Similarity(str1, str2 string, p *Params) float64 {
+ return Match(str1, str2, p.Clone().BonusThreshold(1.1)) // guaranteed no bonus
+}
+
+// Match returns a similarity score adjusted by the same method as proposed by Winkler for
+// the Jaro distance - giving a bonus to string pairs that share a common prefix, only if their
+// similarity score is already over a threshold.
+//
+// The score is in the range of 0..1, with 1 meaning the strings are identical,
+// and 0 meaning they have nothing in common.
+//
+// A nil third argument uses the default cost of 1 for all three operations, maximum length of
+// common prefix to consider for bonus of 4, scaling factor of 0.1, and bonus threshold of 0.7.
+//
+// If a non-zero MinScore value is provided in the parameters, scores lower than it
+// will be returned as 0.
+func Match(str1, str2 string, p *Params) float64 {
+ s1, s2 := []rune(str1), []rune(str2)
+ l1, l2 := len(s1), len(s2)
+ // two empty strings are identical; shortcut also avoids divByZero issues later on.
+ if l1 == 0 && l2 == 0 {
+ return 1
+ }
+
+ if p == nil {
+ p = defaultParams
+ }
+
+ // a min over 1 can never be satisfied, so the score is 0.
+ if p.minScore > 1 {
+ return 0
+ }
+
+ insCost, delCost, maxDist, max := p.insCost, p.delCost, 0, 0
+ if l1 > l2 {
+ l1, l2, insCost, delCost = l2, l1, delCost, insCost
+ }
+
+ if p.subCost < delCost+insCost {
+ maxDist = l1*p.subCost + (l2-l1)*insCost
+ } else {
+ maxDist = l1*delCost + l2*insCost
+ }
+
+ // a zero min is always satisfied, so no need to set a max cost.
+ if p.minScore > 0 {
+ // if p.minScore is lower than p.bonusThreshold, we can use a simplified formula
+ // for the max cost, because a sim score below min cannot receive a bonus.
+ if p.minScore < p.bonusThreshold {
+ // round down the max - a cost equal to a rounded up max would already be under min.
+ max = int((1 - p.minScore) * float64(maxDist))
+ } else {
+ // p.minScore <= sim + p.bonusPrefix*p.bonusScale*(1-sim)
+ // p.minScore <= (1-dist/maxDist) + p.bonusPrefix*p.bonusScale*(1-(1-dist/maxDist))
+ // p.minScore <= 1 - dist/maxDist + p.bonusPrefix*p.bonusScale*dist/maxDist
+ // 1 - p.minScore >= dist/maxDist - p.bonusPrefix*p.bonusScale*dist/maxDist
+ // (1-p.minScore)*maxDist/(1-p.bonusPrefix*p.bonusScale) >= dist
+ max = int((1 - p.minScore) * float64(maxDist) / (1 - float64(p.bonusPrefix)*p.bonusScale))
+ }
+ }
+
+ dist, pl, _ := Calculate(s1, s2, max, p.insCost, p.subCost, p.delCost)
+ if max > 0 && dist > max {
+ return 0
+ }
+ sim := 1 - float64(dist)/float64(maxDist)
+
+ if sim >= p.bonusThreshold && sim < 1 && p.bonusPrefix > 0 && p.bonusScale > 0 {
+ if pl > p.bonusPrefix {
+ pl = p.bonusPrefix
+ }
+ sim += float64(pl) * p.bonusScale * (1 - sim)
+ }
+
+ if sim < p.minScore {
+ return 0
+ }
+
+ return sim
+}
diff --git a/hack/tools/vendor/github.com/agext/levenshtein/params.go b/hack/tools/vendor/github.com/agext/levenshtein/params.go
new file mode 100644
index 00000000000..a85727b3eff
--- /dev/null
+++ b/hack/tools/vendor/github.com/agext/levenshtein/params.go
@@ -0,0 +1,152 @@
+// Copyright 2016 ALRUX Inc.
+//
+// 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 levenshtein
+
+// Params represents a set of parameter values for the various formulas involved
+// in the calculation of the Levenshtein string metrics.
+type Params struct {
+ insCost int
+ subCost int
+ delCost int
+ maxCost int
+ minScore float64
+ bonusPrefix int
+ bonusScale float64
+ bonusThreshold float64
+}
+
+var (
+ defaultParams = NewParams()
+)
+
+// NewParams creates a new set of parameters and initializes it with the default values.
+func NewParams() *Params {
+ return &Params{
+ insCost: 1,
+ subCost: 1,
+ delCost: 1,
+ maxCost: 0,
+ minScore: 0,
+ bonusPrefix: 4,
+ bonusScale: .1,
+ bonusThreshold: .7,
+ }
+}
+
+// Clone returns a pointer to a copy of the receiver parameter set, or of a new
+// default parameter set if the receiver is nil.
+func (p *Params) Clone() *Params {
+ if p == nil {
+ return NewParams()
+ }
+ return &Params{
+ insCost: p.insCost,
+ subCost: p.subCost,
+ delCost: p.delCost,
+ maxCost: p.maxCost,
+ minScore: p.minScore,
+ bonusPrefix: p.bonusPrefix,
+ bonusScale: p.bonusScale,
+ bonusThreshold: p.bonusThreshold,
+ }
+}
+
+// InsCost overrides the default value of 1 for the cost of insertion.
+// The new value must be zero or positive.
+func (p *Params) InsCost(v int) *Params {
+ if v >= 0 {
+ p.insCost = v
+ }
+ return p
+}
+
+// SubCost overrides the default value of 1 for the cost of substitution.
+// The new value must be zero or positive.
+func (p *Params) SubCost(v int) *Params {
+ if v >= 0 {
+ p.subCost = v
+ }
+ return p
+}
+
+// DelCost overrides the default value of 1 for the cost of deletion.
+// The new value must be zero or positive.
+func (p *Params) DelCost(v int) *Params {
+ if v >= 0 {
+ p.delCost = v
+ }
+ return p
+}
+
+// MaxCost overrides the default value of 0 (meaning unlimited) for the maximum cost.
+// The calculation of Distance() stops when the result is guaranteed to exceed
+// this maximum, returning a lower-bound rather than exact value.
+// The new value must be zero or positive.
+func (p *Params) MaxCost(v int) *Params {
+ if v >= 0 {
+ p.maxCost = v
+ }
+ return p
+}
+
+// MinScore overrides the default value of 0 for the minimum similarity score.
+// Scores below this threshold are returned as 0 by Similarity() and Match().
+// The new value must be zero or positive. Note that a minimum greater than 1
+// can never be satisfied, resulting in a score of 0 for any pair of strings.
+func (p *Params) MinScore(v float64) *Params {
+ if v >= 0 {
+ p.minScore = v
+ }
+ return p
+}
+
+// BonusPrefix overrides the default value for the maximum length of
+// common prefix to be considered for bonus by Match().
+// The new value must be zero or positive.
+func (p *Params) BonusPrefix(v int) *Params {
+ if v >= 0 {
+ p.bonusPrefix = v
+ }
+ return p
+}
+
+// BonusScale overrides the default value for the scaling factor used by Match()
+// in calculating the bonus.
+// The new value must be zero or positive. To guarantee that the similarity score
+// remains in the interval 0..1, this scaling factor is not allowed to exceed
+// 1 / BonusPrefix.
+func (p *Params) BonusScale(v float64) *Params {
+ if v >= 0 {
+ p.bonusScale = v
+ }
+
+ // the bonus cannot exceed (1-sim), or the score may become greater than 1.
+ if float64(p.bonusPrefix)*p.bonusScale > 1 {
+ p.bonusScale = 1 / float64(p.bonusPrefix)
+ }
+
+ return p
+}
+
+// BonusThreshold overrides the default value for the minimum similarity score
+// for which Match() can assign a bonus.
+// The new value must be zero or positive. Note that a threshold greater than 1
+// effectively makes Match() become the equivalent of Similarity().
+func (p *Params) BonusThreshold(v float64) *Params {
+ if v >= 0 {
+ p.bonusThreshold = v
+ }
+ return p
+}
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/COPYING b/hack/tools/vendor/github.com/alecthomas/chroma/v2/COPYING
index 92dc39f7091..33da4898172 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/COPYING
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/COPYING
@@ -17,3 +17,102 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+
+// formatters/svg/font_liberation_mono.go
+
+Digitized data copyright (c) 2010 Google Corporation
+with Reserved Font Arimo, Tinos and Cousine.
+Copyright (c) 2012 Red Hat, Inc.
+with Reserved Font Name Liberation.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://openfontlicense.org
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile b/hack/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile
index c86b3793256..8a706766d31 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile
@@ -1,7 +1,7 @@
# Multi-stage Dockerfile for chromad Go application using Hermit-managed tools
# Build stage
-FROM ubuntu:24.04 AS builder
+FROM ubuntu:26.04 AS builder
# Install system dependencies
RUN apt-get update && apt-get install -y \
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/README.md b/hack/tools/vendor/github.com/alecthomas/chroma/v2/README.md
index 4aeb54d9719..d6747695878 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/README.md
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/README.md
@@ -36,25 +36,25 @@ translators for Pygments lexers and styles.
| Prefix | Language
| :----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, ATL, AutoHotkey, AutoIt, Awk
+| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, AMPL, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, ATL, AutoHotkey, AutoIt, Awk
| B | Ballerina, Bash, Bash Session, Batchfile, Beef, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck
| C | C, C#, C++, C3, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Core, Crystal, CSS, CSV, CUE, Cython
| D | D, Dart, Dax, Desktop file, Diff, Django/Jinja, dns, Docker, DTD, Dylan
| E | EBNF, Elixir, Elm, EmacsLisp, Erlang
| F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp
-| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy
+| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gettext, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy
| H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy
| I | Idris, Igor, INI, Io, ISCdhcpd
| J | J, Janet, Java, JavaScript, JSON, JSONata, Jsonnet, Julia, Jungle
| K | Kakoune, Kotlin
-| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua
+| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua, Luau
| M | Makefile, Mako, markdown, Markless, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, MiniZinc, MLIR, Modelica, Modula-2, Mojo, MonkeyC, MoonScript, MorrowindScript, Myghty, MySQL
| N | NASM, Natural, NDISASM, Newspeak, Nginx configuration file, Nim, Nix, NSIS, Nu
| O | Objective-C, ObjectPascal, OCaml, Octave, Odin, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode
| P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Plutus Core, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerQuery, PowerShell, Prolog, Promela, PromQL, properties, Protocol Buffer, Protocol Buffer Text Format, PRQL, PSL, Puppet, Python, Python 2
| Q | QBasic, QML
| R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, RGBDS Assembly, Ring, RPGLE, RPMSpec, Ruby, Rust
-| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog
+| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, Spade, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog
| T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData, Typst
| U | ucode
| V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue
@@ -226,11 +226,11 @@ formatter outputs raw tokens. The latter is useful for debugging lexers.
### Styles
Chroma styles are defined in XML. The style entries use the
-[same syntax](http://pygments.org/docs/styles/) as Pygments.
-
-All Pygments styles have been converted to Chroma using the `_tools/style.py`
+[same syntax](http://pygments.org/docs/styles/) as Pygments. All Pygments styles have been converted to Chroma using the `_tools/style.py`
script.
+Style names are case-insensitive. For example, `monokai` and `Monokai` are treated as the same style.
+
When you work with one of [Chroma's styles](https://github.com/alecthomas/chroma/tree/master/styles),
know that the `Background` token type provides the default style for tokens. It does so
by defining a foreground color and background color.
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go b/hack/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go
index 70d692ec45d..416208a732b 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go
@@ -4,7 +4,7 @@
// with Reserved Font Name Liberation.
//
// This Font Software is licensed under the SIL Open Font License, Version 1.1.
-// This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+// This license is copied below, and is also available with a FAQ at: https://openfontlicense.org
//
// -----------------------------------------------------------
// SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml
new file mode 100644
index 00000000000..8c2479e504b
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml
@@ -0,0 +1,98 @@
+
+
+ AMPL
+ ampl
+ *.mod
+ *.run
+ text/x-ampl
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml
new file mode 100644
index 00000000000..e597cd8a99d
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml
@@ -0,0 +1,37 @@
+
+
+ ERB
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml
index 7557bce0f22..399cdd00863 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml
@@ -56,7 +56,7 @@
-
+
@@ -114,7 +114,7 @@
-
+
@@ -139,7 +139,7 @@
-
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml
new file mode 100644
index 00000000000..38c0c21b442
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml
@@ -0,0 +1,24 @@
+
+
+
+ Gettext
+ pot
+ po
+ *.pot
+ *.po
+ application/x-gettext
+ text/x-gettext
+ text/gettext
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml
index b06227357df..b40422f2256 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml
@@ -76,6 +76,10 @@
+
+
+
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml
index efe80ed3758..0e475c53e85 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml
@@ -133,7 +133,7 @@
-
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml
index a34abfa4980..0057aa1b694 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml
@@ -4,7 +4,9 @@
json
*.json
*.jsonc
+ *.json5
*.avsc
+ .luaurc
application/json
true
true
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml
new file mode 100644
index 00000000000..cea10eba732
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml
@@ -0,0 +1,184 @@
+
+
+ Lateralus
+ lateralus
+ ltl
+ *.ltl
+ text/x-lateralus
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml
index e3d778f12a9..903d4581feb 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml
@@ -2,10 +2,8 @@
Lua
lua
- luau
*.lua
*.wlua
- *.luau
text/x-lua
application/x-lua
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml
new file mode 100644
index 00000000000..79a60949aa8
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml
@@ -0,0 +1,173 @@
+
+
+ Luau
+ luau
+ *.luau
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml
index 7094ddc3eeb..616d7ae4c74 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml
@@ -45,7 +45,7 @@
-
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml
index 130047df6ad..fcfbda11568 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml
@@ -4,6 +4,7 @@
meson
meson.build
meson.build
+ meson.options
meson_options.txt
text/x-meson
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml
index b6c2046d5e6..0517ec8f78c 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml
@@ -38,7 +38,7 @@
-
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml
index c9e22ea5778..774bb79be22 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml
@@ -54,7 +54,7 @@
-
+
@@ -82,12 +82,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -101,6 +135,10 @@
+
+
+
+
@@ -116,7 +154,7 @@
-
+
@@ -132,6 +170,13 @@
+
+
+
+
+
+
+
@@ -161,7 +206,7 @@
-
+
@@ -170,8 +215,9 @@
-
+
+
@@ -185,7 +231,7 @@
-
+
@@ -194,7 +240,7 @@
-
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml
new file mode 100644
index 00000000000..1b3a876efc2
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml
@@ -0,0 +1,115 @@
+
+
+ scdoc
+ scdoc
+ *.scd
+ *.scdoc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml
new file mode 100644
index 00000000000..4dfe3292bab
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml
@@ -0,0 +1,292 @@
+
+
+ Spade
+ spade
+ *.spade
+ text/spade
+ text/x-spade
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml
index a3e3be2391c..b39c9649ccc 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml
@@ -226,7 +226,7 @@
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml
index 2c6a4d99041..99d5d53027d 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml
@@ -10,6 +10,7 @@
*.wsdl
*.wsf
*.svg
+ *.qrc
*.csproj
*.vcxproj
*.fsproj
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go
new file mode 100644
index 00000000000..2d141ed9ea0
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go
@@ -0,0 +1,29 @@
+package lexers
+
+import (
+ "strings"
+
+ . "github.com/alecthomas/chroma/v2" // nolint
+)
+
+// ERB lexer is Ruby embedded in HTML.
+var ERB = Register(DelegatingLexer(HTML, MustNewXMLLexer(
+ embedded,
+ "embedded/erb.xml",
+).SetConfig(
+ &Config{
+ Name: "ERB",
+ Aliases: []string{"erb", "html+erb", "html+ruby", "rhtml"},
+ Filenames: []string{"*.erb", "*.html.erb", "*.xml.erb", "*.rhtml"},
+ MimeTypes: []string{"application/x-ruby-templating"},
+ DotAll: true,
+ },
+).SetAnalyser(func(text string) float32 {
+ if strings.Contains(text, "<%=") && strings.Contains(text, "%>") {
+ return 0.4
+ }
+ if strings.Contains(text, "<%") {
+ return 0.1
+ }
+ return 0.0
+})))
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go b/hack/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go
index c0e5e10818d..d183fa5dc28 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go
@@ -308,6 +308,7 @@ type RegexLexer struct {
rules map[string][]*CompiledRule
fetchRulesFunc func() (Rules, error)
compileOnce sync.Once
+ compileError error
}
func (r *RegexLexer) String() string {
@@ -446,8 +447,11 @@ func (r *RegexLexer) needRules() error {
var err error
if r.fetchRulesFunc != nil {
r.compileOnce.Do(func() {
- err = r.fetchRules()
+ r.compileError = r.fetchRules()
})
+ if r.compileError != nil {
+ return r.compileError
+ }
}
if err := r.maybeCompile(); err != nil {
return err
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go
index e26d6f0a56a..9e21c8844fd 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go
@@ -4,6 +4,7 @@ import (
"embed"
"io/fs"
"sort"
+ "strings"
"github.com/alecthomas/chroma/v2"
)
@@ -31,7 +32,7 @@ var Registry = func() map[string]*chroma.Style {
if err != nil {
panic(err)
}
- registry[style.Name] = style
+ registry[strings.ToLower(style.Name)] = style
_ = r.Close()
}
return registry
@@ -42,7 +43,7 @@ var Fallback = Registry["swapoff"]
// Register a chroma.Style.
func Register(style *chroma.Style) *chroma.Style {
- Registry[style.Name] = style
+ Registry[strings.ToLower(style.Name)] = style
return style
}
@@ -58,7 +59,7 @@ func Names() []string {
// Get named style, or Fallback.
func Get(name string) *chroma.Style {
- if style, ok := Registry[name]; ok {
+ if style, ok := Registry[strings.ToLower(name)]; ok {
return style
}
return Fallback
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go
index 4a6aaa6652d..03098536767 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go
@@ -31,6 +31,9 @@ var (
HrDark = Registry["hrdark"]
HrHighContrast = Registry["hr_high_contrast"]
Igor = Registry["igor"]
+ KanagawaDragon = Registry["kanagawa-dragon"]
+ KanagawaLotus = Registry["kanagawa-lotus"]
+ KanagawaWave = Registry["kanagawa-wave"]
Lovelace = Registry["lovelace"]
Manni = Registry["manni"]
ModusOperandi = Registry["modus-operandi"]
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml
new file mode 100644
index 00000000000..4c3550623ae
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml
@@ -0,0 +1,83 @@
+
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml
index 711aeafc4ab..c5b0dbb5e4d 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml
@@ -15,6 +15,7 @@
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml
new file mode 100644
index 00000000000..114d1651d15
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml
@@ -0,0 +1,83 @@
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml
new file mode 100644
index 00000000000..dde3bc8efa2
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml
@@ -0,0 +1,83 @@
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml
new file mode 100644
index 00000000000..cebcda1b5be
--- /dev/null
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml
@@ -0,0 +1,83 @@
+
diff --git a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml
index 4fbc1d4a675..8839e760204 100644
--- a/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml
+++ b/hack/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml
@@ -1,5 +1,5 @@
`)
diff --git a/hack/tools/vendor/github.com/golangci/dupl/suffixtree/dupl.go b/hack/tools/vendor/github.com/golangci/dupl/suffixtree/dupl.go
index ab145b4f3b6..0263203edf7 100644
--- a/hack/tools/vendor/github.com/golangci/dupl/suffixtree/dupl.go
+++ b/hack/tools/vendor/github.com/golangci/dupl/suffixtree/dupl.go
@@ -54,7 +54,7 @@ func (c *contextList) append(c2 *contextList) {
}
}
-// FindDuplOver find pairs of maximal duplicities over a threshold
+// FindDuplOver finds pairs of maximal duplicities over a threshold
// length.
func (t *STree) FindDuplOver(threshold int) <-chan Match {
auxTran := newTran(0, 0, t.root)
diff --git a/hack/tools/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go b/hack/tools/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go
index 871469e8d5d..30aaa6f4e98 100644
--- a/hack/tools/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go
+++ b/hack/tools/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go
@@ -38,7 +38,7 @@ func New() *STree {
return t
}
-// Update refreshes the suffix tree to by new data.
+// Update refreshes the suffix tree with new data.
func (t *STree) Update(data ...Token) {
t.data = append(t.data, data...)
for range data {
@@ -79,8 +79,8 @@ func (t *STree) update() {
}
// testAndSplit tests whether a state with canonical ref. pair
-// (s, (start, end)) is the end point, that is, a state that have
-// a c-transition. If not, then state (exs, (start, end)) is made
+// (s, (start, end)) is the end point, that is, a state that has
+// a c-transition. If not, then the state (exs, (start, end)) is made
// explicit (if not already so).
func (t *STree) testAndSplit(s *state, start, end Pos) (exs *state, endPoint bool) {
c := t.data[t.end]
@@ -148,11 +148,11 @@ func (t *STree) String() string {
return buf.String()
}
-func printState(buf *bytes.Buffer, s *state, ident int) {
+func printState(buf *bytes.Buffer, s *state, indent int) {
for _, tr := range s.trans {
- fmt.Fprint(buf, strings.Repeat(" ", ident))
+ fmt.Fprint(buf, strings.Repeat(" ", indent))
fmt.Fprintf(buf, "* (%d, %d)\n", tr.start, tr.ActEnd())
- printState(buf, tr.state, ident+1)
+ printState(buf, tr.state, indent+1)
}
}
diff --git a/hack/tools/vendor/github.com/golangci/dupl/syntax/golang/golang.go b/hack/tools/vendor/github.com/golangci/dupl/syntax/golang/golang.go
index a0b1e77e13f..ff3e51b2eea 100644
--- a/hack/tools/vendor/github.com/golangci/dupl/syntax/golang/golang.go
+++ b/hack/tools/vendor/github.com/golangci/dupl/syntax/golang/golang.go
@@ -39,6 +39,7 @@ const (
IfStmt
IncDecStmt
IndexExpr
+ IndexListExpr
InterfaceType
KeyValueExpr
LabeledStmt
@@ -234,6 +235,9 @@ func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
case *ast.FuncType:
o.Type = FuncType
+ if n.TypeParams != nil {
+ o.AddChildren(t.trans(n.TypeParams))
+ }
o.AddChildren(t.trans(n.Params))
if n.Results != nil {
o.AddChildren(t.trans(n.Results))
@@ -270,6 +274,13 @@ func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
o.Type = IndexExpr
o.AddChildren(t.trans(n.X), t.trans(n.Index))
+ case *ast.IndexListExpr:
+ o.Type = IndexListExpr
+ o.AddChildren(t.trans(n.X))
+ for _, idx := range n.Indices {
+ o.AddChildren(t.trans(idx))
+ }
+
case *ast.InterfaceType:
o.Type = InterfaceType
o.AddChildren(t.trans(n.Methods))
@@ -358,7 +369,11 @@ func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
case *ast.TypeSpec:
o.Type = TypeSpec
- o.AddChildren(t.trans(n.Name), t.trans(n.Type))
+ o.AddChildren(t.trans(n.Name))
+ if n.TypeParams != nil {
+ o.AddChildren(t.trans(n.TypeParams))
+ }
+ o.AddChildren(t.trans(n.Type))
case *ast.TypeSwitchStmt:
o.Type = TypeSwitchStmt
diff --git a/hack/tools/vendor/github.com/golangci/dupl/syntax/syntax.go b/hack/tools/vendor/github.com/golangci/dupl/syntax/syntax.go
index 9b11d3119b4..871f671864e 100644
--- a/hack/tools/vendor/github.com/golangci/dupl/syntax/syntax.go
+++ b/hack/tools/vendor/github.com/golangci/dupl/syntax/syntax.go
@@ -129,8 +129,8 @@ func getUnitsIndexes(nodeSeq []*Node, threshold int) []int {
return indexes
}
-// isCyclic finds out whether there is a repetive pattern in the found clone. If positive,
-// it return false to point out that the clone would be redundant.
+// isCyclic finds out whether there is a repetitive pattern in the found clone. If positive,
+// it returns true to point out that the clone would be redundant.
func isCyclic(indexes []int, nodes []*Node) bool {
cnt := len(indexes)
if cnt <= 1 {
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go
index 138a36148a8..f299afe7cba 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go
@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"maps"
+ "path/filepath"
"runtime"
"slices"
"strings"
@@ -172,6 +173,11 @@ func (c *Cache) computePkgHash(pkg *packages.Package) (hashResults, error) {
return nil, fmt.Errorf("failed to calculate file %s hash: %w", f, fErr)
}
+ // This is the current module (the project to analyze).
+ if pkg.Module != nil && pkg.Module.Version == "" {
+ f = pkg.Module.Path + strings.TrimPrefix(filepath.ToSlash(f), filepath.ToSlash(pkg.Module.Dir))
+ }
+
fmt.Fprintf(key, "file %s %x\n", f, h)
}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/custom-gcl.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/custom-gcl.jsonschema.json
new file mode 100644
index 00000000000..71ea3e98df6
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/custom-gcl.jsonschema.json
@@ -0,0 +1,76 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$ref": "#/$defs/Configuration",
+ "$defs": {
+ "Configuration": {
+ "properties": {
+ "version": {
+ "type": "string",
+ "description": "golangci-lint version."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the binary."
+ },
+ "destination": {
+ "type": "string",
+ "description": "Destination is the path to a directory to store the binary."
+ },
+ "plugins": {
+ "items": {
+ "$ref": "#/$defs/Plugin"
+ },
+ "type": "array",
+ "description": "Plugins information."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "description": "Configuration represents the configuration file."
+ },
+ "Plugin": {
+ "oneOf": [
+ {
+ "required": [
+ "version"
+ ],
+ "title": "version"
+ },
+ {
+ "required": [
+ "path"
+ ],
+ "title": "path"
+ }
+ ],
+ "properties": {
+ "module": {
+ "type": "string",
+ "description": "Module name."
+ },
+ "import": {
+ "type": "string",
+ "description": "Import to use."
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the module.\nOnly for module available through a Go proxy."
+ },
+ "path": {
+ "type": "string",
+ "description": "Path to the local module.\nOnly for local module."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "module"
+ ],
+ "description": "Plugin represents information about a plugin."
+ }
+ },
+ "description": "mygcl configuration definition file"
+}
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.jsonschema.json
new file mode 100644
index 00000000000..0ac9d577eb7
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.jsonschema.json
@@ -0,0 +1,5438 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G124",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707",
+ "G708",
+ "G709",
+ "G710"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "inline",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "after-block",
+ "after-decl",
+ "after-defer",
+ "after-expr",
+ "after-go",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "assign",
+ "branch",
+ "cuddle-group",
+ "decl",
+ "defer",
+ "err",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "leading-whitespace",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "trailing-whitespace",
+ "type-switch"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "clickhouselint",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "gomodguard_v2",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bodycloseSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-consumption": {
+ "description": "Check that the response body is consumed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ },
+ "function": {
+ "description": "Checks that exported functions are placed before unexported functions.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-tests": {
+ "description": "Ignore strings from test files",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-functions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardv2Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-replace-directives": {
+ "type": "boolean"
+ },
+ "allowed": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "enum": ["", "exact", "prefix", "regex"],
+ "default": "exact"
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ },
+ "recommendations": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-cleanup": {
+ "description": "Check that defer is not used with t.Parallel (use t.Cleanup instead).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-global": {
+ "description": "Report the use of global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "context": {
+ "description": "Report the use of functions without a context.Context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Report dynamic log messages, such as those that are built with fmt.Sprintf.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Report log messages that do not match a particular style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Report the use of both key-value pairs and attributes within a single function call.",
+ "type": "boolean",
+ "default": true
+ },
+ "kv-only": {
+ "description": "Report any use of attributes as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "attr-only": {
+ "description": "Report any use of key-value pairs as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Report two or more arguments on the same line.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Report the use of string literals as log keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-keys": {
+ "description": "Report the use of log keys that are not explicitly allowed.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "forbidden-keys": {
+ "description": "Report the use of forbidden log keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "key-naming-case": {
+ "description": "Report log keys that do not match a particular naming case.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "custom-funcs": {
+ "description": "Analyze custom functions in addition to the standard log/slog functions.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/settings/definitions/sloglintCustomFunc"
+ }
+ }
+ }
+ },
+ "sloglintCustomFunc": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The full name of the function, including the package. If the function is a method, the receiver type must be wrapped in parentheses.",
+ "type": "string"
+ },
+ "msg-pos": {
+ "description": "The position of the \"msg string\" argument in the function signature, starting from 0. If there is no message in the function, a negative value must be passed.",
+ "type": "integer"
+ },
+ "args-pos": {
+ "description": "The position of the \"args ...any\" argument in the function signature, starting from 0. If there are no arguments in the function, a negative value must be passed.",
+ "type": "integer"
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "cuddle-max-statements": {
+ "type": "integer",
+ "default": 1
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "bodyclose": {
+ "$ref": "#/definitions/settings/definitions/bodycloseSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gomodguard_v2": {
+ "$ref": "#/definitions/settings/definitions/gomodguardv2Settings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.next.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.next.jsonschema.json
new file mode 100644
index 00000000000..0ac9d577eb7
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.next.jsonschema.json
@@ -0,0 +1,5438 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G124",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707",
+ "G708",
+ "G709",
+ "G710"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "inline",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "after-block",
+ "after-decl",
+ "after-defer",
+ "after-expr",
+ "after-go",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "assign",
+ "branch",
+ "cuddle-group",
+ "decl",
+ "defer",
+ "err",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "leading-whitespace",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "trailing-whitespace",
+ "type-switch"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "clickhouselint",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "gomodguard_v2",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bodycloseSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-consumption": {
+ "description": "Check that the response body is consumed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ },
+ "function": {
+ "description": "Checks that exported functions are placed before unexported functions.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-tests": {
+ "description": "Ignore strings from test files",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-functions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardv2Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-replace-directives": {
+ "type": "boolean"
+ },
+ "allowed": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "enum": ["", "exact", "prefix", "regex"],
+ "default": "exact"
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ },
+ "recommendations": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-cleanup": {
+ "description": "Check that defer is not used with t.Parallel (use t.Cleanup instead).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-global": {
+ "description": "Report the use of global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "context": {
+ "description": "Report the use of functions without a context.Context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Report dynamic log messages, such as those that are built with fmt.Sprintf.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Report log messages that do not match a particular style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Report the use of both key-value pairs and attributes within a single function call.",
+ "type": "boolean",
+ "default": true
+ },
+ "kv-only": {
+ "description": "Report any use of attributes as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "attr-only": {
+ "description": "Report any use of key-value pairs as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Report two or more arguments on the same line.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Report the use of string literals as log keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-keys": {
+ "description": "Report the use of log keys that are not explicitly allowed.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "forbidden-keys": {
+ "description": "Report the use of forbidden log keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "key-naming-case": {
+ "description": "Report log keys that do not match a particular naming case.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "custom-funcs": {
+ "description": "Analyze custom functions in addition to the standard log/slog functions.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/settings/definitions/sloglintCustomFunc"
+ }
+ }
+ }
+ },
+ "sloglintCustomFunc": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The full name of the function, including the package. If the function is a method, the receiver type must be wrapped in parentheses.",
+ "type": "string"
+ },
+ "msg-pos": {
+ "description": "The position of the \"msg string\" argument in the function signature, starting from 0. If there is no message in the function, a negative value must be passed.",
+ "type": "integer"
+ },
+ "args-pos": {
+ "description": "The position of the \"args ...any\" argument in the function signature, starting from 0. If there are no arguments in the function, a negative value must be passed.",
+ "type": "integer"
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "cuddle-max-statements": {
+ "type": "integer",
+ "default": 1
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "bodyclose": {
+ "$ref": "#/definitions/settings/definitions/bodycloseSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gomodguard_v2": {
+ "$ref": "#/definitions/settings/definitions/gomodguardv2Settings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.57.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.57.jsonschema.json
new file mode 100644
index 00000000000..a97c0d42919
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.57.jsonschema.json
@@ -0,0 +1,3480 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "goerr113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomnd",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore": {
+ "description": "DEPRECATED: use `exclude-functions` instead. Comma-separated list of pairs of the form \"pkg:regex\".",
+ "type": "string",
+ "default": "fmt:.*"
+ },
+ "exclude": {
+ "description": "DEPRECATED: use `exclude-functions` instead. Path to a file containing a list of functions to exclude from checking.",
+ "type": "string",
+ "examples": ["/path/to/file.txt"]
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "DEPRECATED: use 'sections' and 'prefix(github.com/org/project)' instead.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ },
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "lang-version": {
+ "description": "Select the Go version to target.",
+ "type": "string",
+ "default": "1.15"
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "go": {
+ "description": "Targeted Go version",
+ "type": "string",
+ "default": "1.13"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "Order of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context-only": {
+ "description": "Enforce using methods that accept a context.",
+ "type": "boolean",
+ "default": false
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "go": {
+ "description": "Targeted Go version",
+ "type": "string",
+ "default": "1.13"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "go": {
+ "description": "Targeted Go version",
+ "type": "string",
+ "default": "1.13"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "disable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"]
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "os-dev-null": {
+ "description": "Suggest the use of os.DevNull.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "syslog-priority": {
+ "description": "Suggest the use of syslog.Priority.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated-strict": {
+ "description": "To follow strict Go generated file convention",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.58.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.58.jsonschema.json
new file mode 100644
index 00000000000..d0bdc8d7b95
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.58.jsonschema.json
@@ -0,0 +1,3638 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "Order of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "disable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"]
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated-strict": {
+ "description": "To follow strict Go generated file convention",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.59.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.59.jsonschema.json
new file mode 100644
index 00000000000..cc3e63655bc
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.59.jsonschema.json
@@ -0,0 +1,3766 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.60.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.60.jsonschema.json
new file mode 100644
index 00000000000..b8920ae06f9
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.60.jsonschema.json
@@ -0,0 +1,3792 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions if format string is used.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.61.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.61.jsonschema.json
new file mode 100644
index 00000000000..a574b0195bc
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.61.jsonschema.json
@@ -0,0 +1,3797 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions if format string is used.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.62.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.62.jsonschema.json
new file mode 100644
index 00000000000..3ca3593b260
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.62.jsonschema.json
@@ -0,0 +1,3860 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.63.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.63.jsonschema.json
new file mode 100644
index 00000000000..c54dd6904d1
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.63.jsonschema.json
@@ -0,0 +1,4082 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exportloopref",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetesting": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.64.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.64.jsonschema.json
new file mode 100644
index 00000000000..b265c1a8233
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.64.jsonschema.json
@@ -0,0 +1,4224 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontext": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetesting": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "lax"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "default": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "stdErrorHandling",
+ "commonFalsePositives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "EXC0001",
+ "EXC0002",
+ "EXC0003",
+ "EXC0004",
+ "EXC0005",
+ "EXC0006",
+ "EXC0007",
+ "EXC0008",
+ "EXC0009",
+ "EXC0010",
+ "EXC0011",
+ "EXC0012",
+ "EXC0013",
+ "EXC0014",
+ "EXC0015"
+ ]
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.jsonschema.json
new file mode 100644
index 00000000000..b265c1a8233
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.jsonschema.json
@@ -0,0 +1,4224 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontext": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetesting": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "lax"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "default": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "stdErrorHandling",
+ "commonFalsePositives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "EXC0001",
+ "EXC0002",
+ "EXC0003",
+ "EXC0004",
+ "EXC0005",
+ "EXC0006",
+ "EXC0007",
+ "EXC0008",
+ "EXC0009",
+ "EXC0010",
+ "EXC0011",
+ "EXC0012",
+ "EXC0013",
+ "EXC0014",
+ "EXC0015"
+ ]
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.0.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.0.jsonschema.json
new file mode 100644
index 00000000000..437943b5f31
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.0.jsonschema.json
@@ -0,0 +1,4738 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.1.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.1.jsonschema.json
new file mode 100644
index 00000000000..0f2ef5fcc50
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.1.jsonschema.json
@@ -0,0 +1,4790 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.10.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.10.jsonschema.json
new file mode 100644
index 00000000000..7fa4a12dbeb
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.10.jsonschema.json
@@ -0,0 +1,5285 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace",
+ "after-block"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.11.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.11.jsonschema.json
new file mode 100644
index 00000000000..38b3e77a5d9
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.11.jsonschema.json
@@ -0,0 +1,5295 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace",
+ "after-block"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.2.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.2.jsonschema.json
new file mode 100644
index 00000000000..3e51264fec4
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.2.jsonschema.json
@@ -0,0 +1,4901 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.3.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.3.jsonschema.json
new file mode 100644
index 00000000000..7c4840521f4
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.3.jsonschema.json
@@ -0,0 +1,4907 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.4.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.4.jsonschema.json
new file mode 100644
index 00000000000..67cd80a55e9
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.4.jsonschema.json
@@ -0,0 +1,4929 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.5.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.5.jsonschema.json
new file mode 100644
index 00000000000..f471fd3dadf
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.5.jsonschema.json
@@ -0,0 +1,5081 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.6.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.6.jsonschema.json
new file mode 100644
index 00000000000..e2f59663e36
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.6.jsonschema.json
@@ -0,0 +1,5136 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "bloop",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.7.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.7.jsonschema.json
new file mode 100644
index 00000000000..accf61f9745
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.7.jsonschema.json
@@ -0,0 +1,5144 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "bloop",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.8.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.8.jsonschema.json
new file mode 100644
index 00000000000..675beedd035
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.8.jsonschema.json
@@ -0,0 +1,5223 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G116",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "bloop",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.9.jsonschema.json b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.9.jsonschema.json
new file mode 100644
index 00000000000..38b3590c625
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.9.jsonschema.json
@@ -0,0 +1,5278 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G116",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace",
+ "after-block"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/jsonschema.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/jsonschema.go
new file mode 100644
index 00000000000..b380e44305c
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/jsonschema/jsonschema.go
@@ -0,0 +1,40 @@
+package jsonschema
+
+import (
+ "embed"
+ "path/filepath"
+
+ "github.com/santhosh-tekuri/jsonschema/v6"
+)
+
+const (
+ V1Schema = "/golangci.v1.jsonschema.json"
+ NextSchema = "/golangci.next.jsonschema.json"
+)
+
+//go:embed golangci.next.jsonschema.json golangci.v1.jsonschema.json
+var content embed.FS
+
+type EmbedLoader struct {
+ jsonschema.FileLoader
+}
+
+func NewEmbedLoader() *EmbedLoader {
+ return &EmbedLoader{}
+}
+
+func (f *EmbedLoader) Load(uri string) (any, error) {
+ p, err := f.ToFile(uri)
+ if err != nil {
+ return nil, err
+ }
+
+ file, err := content.Open(filepath.Base(p))
+ if err != nil {
+ return nil, err
+ }
+
+ defer func() { _ = file.Close() }()
+
+ return jsonschema.UnmarshalJSON(file)
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go
index b1889fa4266..79945eb0c26 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go
@@ -24,9 +24,8 @@ type configCommand struct {
viper *viper.Viper
cmd *cobra.Command
- opts config.LoaderOptions
- verifyOpts verifyOptions
- pathOpts pathOptions
+ opts config.LoaderOptions
+ pathOpts pathOptions
buildInfo BuildInfo
@@ -78,11 +77,6 @@ func newConfigCommand(log logutils.Log, info BuildInfo) *configCommand {
setupConfigFileFlagSet(flagSet, &c.opts)
- // ex: --schema jsonschema/golangci.next.jsonschema.json
- verifyFlagSet := verifyCommand.Flags()
- verifyFlagSet.StringVar(&c.verifyOpts.schemaURL, "schema", "", color.GreenString("JSON schema URL"))
- _ = verifyFlagSet.MarkHidden("schema")
-
pathFlagSet := pathCommand.Flags()
pathFlagSet.BoolVar(&c.pathOpts.JSON, "json", false, color.GreenString("Display as JSON"))
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go
index 7281e0888a8..8e99c7ee6e5 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go
@@ -1,31 +1,23 @@
package commands
import (
- "context"
"encoding/json"
"errors"
"fmt"
- "net/http"
"os"
"path/filepath"
"strconv"
"strings"
- "time"
- hcversion "github.com/hashicorp/go-version"
"github.com/pelletier/go-toml/v2"
"github.com/santhosh-tekuri/jsonschema/v6"
"github.com/spf13/cobra"
- "github.com/spf13/pflag"
"go.yaml.in/yaml/v3"
+ jsonsch "github.com/golangci/golangci-lint/v2/jsonschema"
"github.com/golangci/golangci-lint/v2/pkg/exitcodes"
)
-type verifyOptions struct {
- schemaURL string // For debugging purpose only (Flag only).
-}
-
func (c *configCommand) executeVerify(cmd *cobra.Command, _ []string) error {
usedConfigFile := c.getUsedConfig()
if usedConfigFile == "" {
@@ -33,14 +25,9 @@ func (c *configCommand) executeVerify(cmd *cobra.Command, _ []string) error {
os.Exit(exitcodes.NoConfigFileDetected)
}
- schemaURL, err := createSchemaURL(cmd.Flags(), c.buildInfo)
- if err != nil {
- return fmt.Errorf("get JSON schema: %w", err)
- }
+ c.log.Infof("Verifying the configuration file %q with the JSON Schema", usedConfigFile)
- c.log.Infof("Verifying the configuration file %q with the JSON Schema from %s", usedConfigFile, schemaURL)
-
- err = validateConfiguration(schemaURL, usedConfigFile)
+ err := validateConfiguration(jsonsch.NextSchema, usedConfigFile)
if err != nil {
var v *jsonschema.ValidationError
if !errors.As(err, &v) {
@@ -55,85 +42,12 @@ func (c *configCommand) executeVerify(cmd *cobra.Command, _ []string) error {
return nil
}
-func createSchemaURL(flags *pflag.FlagSet, buildInfo BuildInfo) (string, error) {
- schemaURL, err := flags.GetString("schema")
- if err != nil {
- return "", fmt.Errorf("get schema flag: %w", err)
- }
-
- if schemaURL != "" {
- return schemaURL, nil
- }
-
- switch {
- case buildInfo.Version != "" && buildInfo.Version != "(devel)":
- version, err := hcversion.NewVersion(buildInfo.Version)
- if err != nil {
- return "", fmt.Errorf("parse version: %w", err)
- }
-
- if version.Core().Equal(hcversion.Must(hcversion.NewVersion("v0.0.0"))) {
- commit, err := extractCommitHash(buildInfo)
- if err != nil {
- return "", err
- }
-
- return fmt.Sprintf("https://raw.githubusercontent.com/golangci/golangci-lint/%s/jsonschema/golangci.next.jsonschema.json",
- commit), nil
- }
-
- return fmt.Sprintf("https://golangci-lint.run/jsonschema/golangci.v%d.%d.jsonschema.json",
- version.Segments()[0], version.Segments()[1]), nil
-
- case buildInfo.Commit != "" && buildInfo.Commit != "?":
- commit, err := extractCommitHash(buildInfo)
- if err != nil {
- return "", err
- }
-
- return fmt.Sprintf("https://raw.githubusercontent.com/golangci/golangci-lint/%s/jsonschema/golangci.next.jsonschema.json",
- commit), nil
-
- default:
- return "", errors.New("version not found")
- }
-}
-
-func extractCommitHash(buildInfo BuildInfo) (string, error) {
- if buildInfo.Commit == "" || buildInfo.Commit == "?" {
- return "", errors.New("empty commit information")
- }
-
- if buildInfo.Commit == "unknown" {
- return "", errors.New("unknown commit information")
- }
-
- commit := buildInfo.Commit
-
- if after, ok := strings.CutPrefix(commit, "("); ok {
- c, _, ok := strings.Cut(after, ",")
- if !ok {
- return "", errors.New("commit information not found")
- }
-
- commit = c
- }
-
- if commit == "unknown" {
- return "", errors.New("unknown commit information")
- }
-
- return commit, nil
-}
-
func validateConfiguration(schemaPath, targetFile string) error {
compiler := jsonschema.NewCompiler()
- compiler.UseLoader(jsonschema.SchemeURLLoader{
- "file": jsonschema.FileLoader{},
- "https": newJSONSchemaHTTPLoader(),
- })
+ compiler.UseLoader(jsonsch.NewEmbedLoader())
compiler.DefaultDraft(jsonschema.Draft7)
+ // The name is not us
schema, err := compiler.Compile(schemaPath)
if err != nil {
return fmt.Errorf("compile schema: %w", err)
@@ -209,33 +123,3 @@ func decodeTomlFile(filename string) (any, error) {
return m, nil
}
-
-type jsonschemaHTTPLoader struct {
- *http.Client
-}
-
-func newJSONSchemaHTTPLoader() *jsonschemaHTTPLoader {
- return &jsonschemaHTTPLoader{Client: &http.Client{
- Timeout: 2 * time.Second,
- }}
-}
-
-func (l jsonschemaHTTPLoader) Load(url string) (any, error) {
- req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, http.NoBody)
- if err != nil {
- return nil, err
- }
-
- resp, err := l.Do(req)
- if err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("%s returned status code %d", url, resp.StatusCode)
- }
-
- return jsonschema.UnmarshalJSON(resp.Body)
-}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go
index 63f6f2f189e..df2a134a436 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go
@@ -96,6 +96,7 @@ func (b Builder) clone(ctx context.Context) error {
"https://github.com/golangci/golangci-lint.git",
)
cmd.Dir = b.root
+ cmd.Env = filterGitEnviron(os.Environ())
output, err := cmd.CombinedOutput()
if err != nil {
@@ -280,3 +281,33 @@ func sanitizeVersion(v string) string {
return strings.Join(strings.FieldsFunc(v, fn), "")
}
+
+// Inspired by https://github.com/pre-commit/pre-commit/blob/f5678bf4ac35cffc0ff7174ad85f7fdc2a5c977e/pre_commit/git.py#L27
+func filterGitEnviron(envs []string) []string {
+ var filtered []string
+
+ for _, env := range envs {
+ if !strings.HasPrefix(env, "GIT_") {
+ filtered = append(filtered, env)
+ continue
+ }
+
+ if strings.HasPrefix(env, "GIT_CONFIG_KEY_") || strings.HasPrefix(env, "GIT_CONFIG_VALUE_") {
+ filtered = append(filtered, env)
+ continue
+ }
+
+ key, _, _ := strings.Cut(env, "=")
+
+ switch key {
+ case "GIT_EXEC_PATH", "GIT_SSH", "GIT_SSH_COMMAND", "GIT_SSL_CAINFO",
+ "GIT_SSL_NO_VERIFY", "GIT_CONFIG_COUNT",
+ "GIT_HTTP_PROXY_AUTHMETHOD",
+ "GIT_ALLOW_PROTOCOL",
+ "GIT_ASKPASS":
+ filtered = append(filtered, env)
+ }
+ }
+
+ return filtered
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go
index 7012e9226e5..cfc5eb015e0 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go
@@ -7,12 +7,13 @@ import (
"path/filepath"
"strings"
- "github.com/charmbracelet/lipgloss"
+ "charm.land/lipgloss/v2"
"github.com/fatih/color"
"github.com/santhosh-tekuri/jsonschema/v6"
"github.com/spf13/cobra"
"github.com/spf13/viper"
+ jsonsch "github.com/golangci/golangci-lint/v2/jsonschema"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/fakeloader"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/parser"
@@ -153,7 +154,7 @@ func (c *migrateCommand) preRunE(cmd *cobra.Command, _ []string) error {
c.log.Infof("Validating v1 configuration file: %s", usedConfigFile)
- err := validateConfiguration("https://golangci-lint.run/jsonschema/golangci.v1.jsonschema.json", usedConfigFile)
+ err := validateConfiguration(jsonsch.V1Schema, usedConfigFile)
if err != nil {
var v *jsonschema.ValidationError
if !errors.As(err, &v) {
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go
index a9a3495aae9..84c47015252 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go
@@ -713,7 +713,8 @@ func computeGoModSalt() (string, error) {
return "", fmt.Errorf("failed to read go.mod: %w", err)
}
- sum, err := dirhash.Hash1([]string{goModPath}, func(string) (io.ReadCloser, error) {
+ // NOTE: the variable `goModPath` is not used here to ensure getting the same hash, independently of the location, for the same content.
+ sum, err := dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
return io.NopCloser(bytes.NewReader(data)), nil
})
if err != nil {
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go
index 3f7193bd3e2..7f001da34b8 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go
@@ -141,17 +141,20 @@ var defaultLintersSettings = LintersSettings{
Predeclared: PredeclaredSettings{
Qualified: false,
},
- SlogLint: SlogLintSettings{
- NoMixedArgs: true,
- KVOnly: false,
- AttrOnly: false,
+ Sloglint: SloglintSettings{
NoGlobal: "",
Context: "",
StaticMsg: false,
+ MsgStyle: "",
+ NoMixedArgs: true,
+ KVOnly: false,
+ AttrOnly: false,
+ ArgsOnSepLines: false,
NoRawKeys: false,
+ AllowedKeys: []string{},
+ ForbiddenKeys: []string{},
KeyNamingCase: "",
- ForbiddenKeys: nil,
- ArgsOnSepLines: false,
+ CustomFuncs: []SloglintCustomFunc{},
},
TagAlign: TagAlignSettings{
Align: true,
@@ -226,13 +229,14 @@ var defaultLintersSettings = LintersSettings{
ForceExclusiveShortDeclarations: false,
},
WSLv5: WSLv5Settings{
- AllowFirstInBlock: true,
- AllowWholeBlock: false,
- BranchMaxLines: 2,
- CaseMaxLines: 0,
- Default: "default",
- Enable: nil,
- Disable: nil,
+ AllowFirstInBlock: true,
+ AllowWholeBlock: false,
+ BranchMaxLines: 2,
+ CaseMaxLines: 0,
+ CuddleMaxStatements: 1,
+ Default: "default",
+ Enable: nil,
+ Disable: nil,
},
}
@@ -241,6 +245,7 @@ type LintersSettings struct {
Asasalint AsasalintSettings `mapstructure:"asasalint"`
BiDiChk BiDiChkSettings `mapstructure:"bidichk"`
+ BodyClose BodyCloseSettings `mapstructure:"bodyclose"`
CopyLoopVar CopyLoopVarSettings `mapstructure:"copyloopvar"`
Cyclop CyclopSettings `mapstructure:"cyclop"`
Decorder DecorderSettings `mapstructure:"decorder"`
@@ -270,6 +275,7 @@ type LintersSettings struct {
Goheader GoHeaderSettings `mapstructure:"goheader"`
GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"`
Gomodguard GoModGuardSettings `mapstructure:"gomodguard"`
+ Gomodguardv2 GoModGuardv2Settings `mapstructure:"gomodguard_v2"`
Gosec GoSecSettings `mapstructure:"gosec"`
Gosmopolitan GosmopolitanSettings `mapstructure:"gosmopolitan"`
Unqueryvet UnqueryvetSettings `mapstructure:"unqueryvet"`
@@ -306,7 +312,7 @@ type LintersSettings struct {
Recvcheck RecvcheckSettings `mapstructure:"recvcheck"`
Revive ReviveSettings `mapstructure:"revive"`
RowsErrCheck RowsErrCheckSettings `mapstructure:"rowserrcheck"`
- SlogLint SlogLintSettings `mapstructure:"sloglint"`
+ Sloglint SloglintSettings `mapstructure:"sloglint"`
Spancheck SpancheckSettings `mapstructure:"spancheck"`
Staticcheck StaticCheckSettings `mapstructure:"staticcheck"`
TagAlign TagAlignSettings `mapstructure:"tagalign"`
@@ -359,6 +365,10 @@ type BiDiChkSettings struct {
PopDirectionalIsolate bool `mapstructure:"pop-directional-isolate"`
}
+type BodyCloseSettings struct {
+ CheckConsumption bool `mapstructure:"check-consumption"`
+}
+
type CopyLoopVarSettings struct {
CheckAlias bool `mapstructure:"check-alias"`
}
@@ -526,6 +536,11 @@ type GoConstSettings struct {
IgnoreCalls bool `mapstructure:"ignore-calls"`
FindDuplicates bool `mapstructure:"find-duplicates"`
EvalConstExpressions bool `mapstructure:"eval-const-expressions"`
+ IgnoreFunctions []string `mapstructure:"ignore-functions"`
+
+ // This option cannot be managed with `linters.exclusions.rules`.
+ // Because the linter counts occurrences across all files in the package.
+ IgnoreTests bool `mapstructure:"ignore-tests"`
// Deprecated: use IgnoreStringValues instead.
IgnoreStrings string `mapstructure:"ignore-strings"`
@@ -596,6 +611,26 @@ type GoModDirectivesSettings struct {
CheckModulePath bool `mapstructure:"check-module-path"`
}
+type GoModGuardv2Settings struct {
+ Allowed []GoModGuardv2Base `mapstructure:"allowed"`
+ Blocked []GoModGuardv2Blocked `mapstructure:"blocked"`
+ LocalReplaceDirectives bool `mapstructure:"local-replace-directives"`
+}
+
+type GoModGuardv2Base struct {
+ Module string `mapstructure:"module"`
+ Version string `mapstructure:"version"`
+ MatchType string `mapstructure:"match-type"`
+}
+
+type GoModGuardv2Blocked struct {
+ GoModGuardv2Base `mapstructure:",squash"`
+
+ Recommendations []string `mapstructure:"recommendations"`
+ Reason string `mapstructure:"reason"`
+}
+
+// Deprecated: use GoModGuardv2Settings instead.
type GoModGuardSettings struct {
Allowed GoModGuardAllowed `mapstructure:"allowed"`
Blocked GoModGuardBlocked `mapstructure:"blocked"`
@@ -799,6 +834,7 @@ type ParallelTestSettings struct {
Go string `mapstructure:"-"`
IgnoreMissing bool `mapstructure:"ignore-missing"`
IgnoreMissingSubtests bool `mapstructure:"ignore-missing-subtests"`
+ CheckCleanup bool `mapstructure:"check-cleanup"`
}
type PerfSprintSettings struct {
@@ -882,18 +918,26 @@ type RowsErrCheckSettings struct {
Packages []string `mapstructure:"packages"`
}
-type SlogLintSettings struct {
- NoMixedArgs bool `mapstructure:"no-mixed-args"`
- KVOnly bool `mapstructure:"kv-only"`
- AttrOnly bool `mapstructure:"attr-only"`
- NoGlobal string `mapstructure:"no-global"`
- Context string `mapstructure:"context"`
- StaticMsg bool `mapstructure:"static-msg"`
- MsgStyle string `mapstructure:"msg-style"`
- NoRawKeys bool `mapstructure:"no-raw-keys"`
- KeyNamingCase string `mapstructure:"key-naming-case"`
- ForbiddenKeys []string `mapstructure:"forbidden-keys"`
- ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"`
+type SloglintSettings struct {
+ NoGlobal string `mapstructure:"no-global"`
+ Context string `mapstructure:"context"`
+ StaticMsg bool `mapstructure:"static-msg"`
+ MsgStyle string `mapstructure:"msg-style"`
+ NoMixedArgs bool `mapstructure:"no-mixed-args"`
+ KVOnly bool `mapstructure:"kv-only"`
+ AttrOnly bool `mapstructure:"attr-only"`
+ ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"`
+ NoRawKeys bool `mapstructure:"no-raw-keys"`
+ AllowedKeys []string `mapstructure:"allowed-keys"`
+ ForbiddenKeys []string `mapstructure:"forbidden-keys"`
+ KeyNamingCase string `mapstructure:"key-naming-case"`
+ CustomFuncs []SloglintCustomFunc `mapstructure:"custom-funcs"`
+}
+
+type SloglintCustomFunc struct {
+ Name string `mapstructure:"name"`
+ MsgPos int `mapstructure:"msg-pos"`
+ ArgsPos int `mapstructure:"args-pos"`
}
type SpancheckSettings struct {
@@ -1131,13 +1175,14 @@ type WSLv4Settings struct {
}
type WSLv5Settings struct {
- AllowFirstInBlock bool `mapstructure:"allow-first-in-block"`
- AllowWholeBlock bool `mapstructure:"allow-whole-block"`
- BranchMaxLines int `mapstructure:"branch-max-lines"`
- CaseMaxLines int `mapstructure:"case-max-lines"`
- Default string `mapstructure:"default"`
- Enable []string `mapstructure:"enable"`
- Disable []string `mapstructure:"disable"`
+ AllowFirstInBlock bool `mapstructure:"allow-first-in-block"`
+ AllowWholeBlock bool `mapstructure:"allow-whole-block"`
+ BranchMaxLines int `mapstructure:"branch-max-lines"`
+ CaseMaxLines int `mapstructure:"case-max-lines"`
+ CuddleMaxStatements int `mapstructure:"cuddle-max-statements"`
+ Default string `mapstructure:"default"`
+ Enable []string `mapstructure:"enable"`
+ Disable []string `mapstructure:"disable"`
}
// CustomLinterSettings encapsulates the meta-data of a private linter.
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go
index f68c4d0a9e6..95cf790bc02 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go
@@ -3,11 +3,21 @@ package bodyclose
import (
"github.com/timakin/bodyclose/passes/bodyclose"
+ "github.com/golangci/golangci-lint/v2/pkg/config"
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
)
-func New() *goanalysis.Linter {
+func New(settings *config.BodyCloseSettings) *goanalysis.Linter {
+ var cfg map[string]any
+
+ if settings != nil {
+ cfg = map[string]any{
+ "check-consumption": settings.CheckConsumption,
+ }
+ }
+
return goanalysis.
NewLinterFromAnalyzer(bodyclose.Analyzer).
+ WithConfig(cfg).
WithLoadMode(goanalysis.LoadModeTypesInfo)
}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint/clickhouselint.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint/clickhouselint.go
new file mode 100644
index 00000000000..0459864bc1b
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint/clickhouselint.go
@@ -0,0 +1,18 @@
+package clickhouselint
+
+import (
+ "github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose"
+ "github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr"
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/golangci/golangci-lint/v2/pkg/goanalysis"
+)
+
+func New() *goanalysis.Linter {
+ return goanalysis.NewLinter(
+ "clickhouselint",
+ "Detects common mistakes with the ClickHouse native Go driver API.",
+ []*analysis.Analyzer{chrowserr.NewAnalyzer(), chbatchclose.NewAnalyzer()},
+ nil,
+ ).WithLoadMode(goanalysis.LoadModeTypesInfo)
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go
index b58d860c6ed..be231224727 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go
@@ -50,6 +50,7 @@ func New(settings *config.GoConstSettings) *goanalysis.Linter {
func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goanalysis.Issue, error) {
cfg := goconstAPI.Config{
IgnoreStrings: settings.IgnoreStringValues,
+ IgnoreTests: settings.IgnoreTests,
MatchWithConstants: settings.MatchWithConstants,
MinStringLength: settings.MinStringLen,
MinOccurrences: settings.MinOccurrencesCount,
@@ -59,9 +60,7 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goana
ExcludeTypes: map[goconstAPI.Type]bool{},
FindDuplicates: settings.FindDuplicates,
EvalConstExpressions: settings.EvalConstExpressions,
-
- // Should be managed with `linters.exclusions.rules`.
- IgnoreTests: false,
+ IgnoreFunctions: settings.IgnoreFunctions,
}
if settings.IgnoreCalls {
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go
index 7d16f57b3a5..b8bdd09650b 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go
@@ -87,3 +87,66 @@ func New(settings *config.GoModGuardSettings) *goanalysis.Linter {
}).
WithLoadMode(goanalysis.LoadModeSyntax)
}
+
+// Only used the set YAML struct tags.
+type v2YAML struct {
+ Allowed []goModGuardv2Base `yaml:"allowed,omitempty"`
+ Blocked []goModGuardv2Blocked `yaml:"blocked,omitempty"`
+ LocalReplaceDirectives bool `yaml:"local-replace-directives,omitempty"`
+}
+
+// Only used the set YAML struct tags.
+type goModGuardv2Base struct {
+ Module string `yaml:"module,omitempty"`
+ Version string `yaml:"version,omitempty"`
+ MatchType string `yaml:"match-type,omitempty"`
+}
+
+// Only used the set YAML struct tags.
+type goModGuardv2Blocked struct {
+ goModGuardv2Base `yaml:",inline"`
+
+ Recommendations []string `yaml:"recommendations,omitempty"`
+ Reason string `yaml:"reason,omitempty"`
+}
+
+func Migration(old *config.GoModGuardSettings) any {
+ if old == nil {
+ return nil
+ }
+
+ if len(old.Allowed.Modules) == 0 && len(old.Allowed.Domains) == 0 && len(old.Blocked.Modules) == 0 && !old.Blocked.LocalReplaceDirectives {
+ return nil
+ }
+
+ cfg := &v2YAML{
+ LocalReplaceDirectives: old.Blocked.LocalReplaceDirectives,
+ }
+
+ for _, module := range old.Allowed.Modules {
+ cfg.Allowed = append(cfg.Allowed, goModGuardv2Base{
+ Module: module,
+ })
+ }
+
+ for _, domain := range old.Allowed.Domains {
+ cfg.Allowed = append(cfg.Allowed, goModGuardv2Base{
+ Module: domain + "/.*",
+ MatchType: "regex",
+ })
+ }
+
+ for _, blocked := range old.Blocked.Modules {
+ for name, module := range blocked {
+ cfg.Blocked = append(cfg.Blocked, goModGuardv2Blocked{
+ goModGuardv2Base: goModGuardv2Base{
+ Module: name,
+ },
+ Recommendations: module.Recommendations,
+ Reason: module.Reason,
+ })
+ }
+ }
+
+ return cfg
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard_v2.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard_v2.go
new file mode 100644
index 00000000000..d25e720605f
--- /dev/null
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard_v2.go
@@ -0,0 +1,106 @@
+package gomodguard
+
+import (
+ "sync"
+
+ "github.com/Masterminds/semver/v3"
+ "github.com/ryancurrah/gomodguard/v2"
+ "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"
+ "github.com/golangci/golangci-lint/v2/pkg/lint/linter"
+ "github.com/golangci/golangci-lint/v2/pkg/result"
+)
+
+const linterNameV2 = "gomodguard_v2"
+
+func NewV2(settings *config.GoModGuardv2Settings) *goanalysis.Linter {
+ var issues []*goanalysis.Issue
+ var mu sync.Mutex
+
+ processorCfg := &gomodguard.Configuration{}
+ if settings != nil {
+ processorCfg.LocalReplaceDirectives = settings.LocalReplaceDirectives
+
+ for _, allowed := range settings.Allowed {
+ rule := gomodguard.AllowedModule{
+ Module: allowed.Module,
+ MatchType: gomodguard.MatchType(allowed.MatchType),
+ Version: nil,
+ Matcher: nil,
+ }
+
+ if allowed.Version != "" {
+ var err error
+
+ rule.Version, err = semver.NewConstraint(allowed.Version)
+ if err != nil {
+ internal.LinterLogger.Fatalf("gomodguard: invalid constraint: %v", err)
+ }
+ }
+
+ processorCfg.Allowed = append(processorCfg.Allowed, rule)
+ }
+
+ for _, blocked := range settings.Blocked {
+ rule := gomodguard.BlockedModule{
+ Module: blocked.Module,
+ MatchType: gomodguard.MatchType(blocked.MatchType),
+ Recommendations: blocked.Recommendations,
+ Reason: blocked.Reason,
+ }
+
+ if blocked.Version != "" {
+ var err error
+
+ rule.Version, err = semver.NewConstraint(blocked.Version)
+ if err != nil {
+ internal.LinterLogger.Fatalf("gomodguard: invalid constraint: %v", err)
+ }
+ }
+
+ processorCfg.Blocked = append(processorCfg.Blocked, rule)
+ }
+ }
+
+ analyzer := &analysis.Analyzer{
+ Name: linterNameV2,
+ Doc: "Allow and blocklist linter for direct Go module dependencies. " +
+ "This is different from depguard where there are different block " +
+ "types for example version constraints and module recommendations.",
+ Run: goanalysis.DummyRun,
+ }
+
+ return goanalysis.NewLinterFromAnalyzer(analyzer).
+ WithContextSetter(func(lintCtx *linter.Context) {
+ processor, err := gomodguard.NewProcessor(processorCfg)
+ if err != nil {
+ lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+
+ "it is suggested to disable this linter", err)
+ return
+ }
+
+ analyzer.Run = func(pass *analysis.Pass) (any, error) {
+ gomodguardIssues := processor.ProcessFiles(internal.GetGoFileNames(pass))
+
+ mu.Lock()
+ defer mu.Unlock()
+
+ for _, gomodguardIssue := range gomodguardIssues {
+ issues = append(issues, goanalysis.NewIssue(&result.Issue{
+ FromLinter: linterNameV2,
+ Pos: gomodguardIssue.Position,
+ Text: gomodguardIssue.Reason,
+ }, pass))
+ }
+
+ return nil, nil
+ }
+ }).
+ WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue {
+ return issues
+ }).
+ WithLoadMode(goanalysis.LoadModeSyntax)
+}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go
index 7755e4ec26f..9f98f4054ad 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go
@@ -28,6 +28,7 @@ import (
"golang.org/x/tools/go/analysis/passes/httpmux"
"golang.org/x/tools/go/analysis/passes/httpresponse"
"golang.org/x/tools/go/analysis/passes/ifaceassert"
+ "golang.org/x/tools/go/analysis/passes/inline"
_ "golang.org/x/tools/go/analysis/passes/inspect" // unused internal analyzer
"golang.org/x/tools/go/analysis/passes/loopclosure"
"golang.org/x/tools/go/analysis/passes/lostcancel"
@@ -83,6 +84,7 @@ var (
httpmux.Analyzer,
httpresponse.Analyzer,
ifaceassert.Analyzer,
+ inline.Analyzer,
loopclosure.Analyzer,
lostcancel.Analyzer,
nilfunc.Analyzer,
@@ -109,7 +111,8 @@ var (
waitgroup.Analyzer,
}
- // https://github.com/golang/go/blob/go1.25.2/src/cmd/vet/main.go#L57-L91
+ // https://github.com/golang/go/blob/go1.26.1/src/cmd/vet/main.go#L63-L99
+ // https://github.com/golang/go/blob/go1.26.1/src/cmd/fix/main.go#L47-L51
defaultAnalyzers = []*analysis.Analyzer{
appends.Analyzer,
asmdecl.Analyzer,
@@ -127,6 +130,7 @@ var (
hostport.Analyzer,
httpresponse.Analyzer,
ifaceassert.Analyzer,
+ inline.Analyzer,
loopclosure.Analyzer,
lostcancel.Analyzer,
nilfunc.Analyzer,
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go
index f3eac2e05af..be052628b94 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go
@@ -14,6 +14,7 @@ func New(settings *config.ParallelTestSettings) *goanalysis.Linter {
cfg = map[string]any{
"i": settings.IgnoreMissing,
"ignoremissingsubtests": settings.IgnoreMissingSubtests,
+ "checkcleanup": settings.CheckCleanup,
}
if config.IsGoGreaterThanOrEqual(settings.Go, "1.22") {
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go
index 9dc8453710e..7fe736f205d 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go
@@ -209,9 +209,11 @@ func getConfig(cfg *config.ReviveSettings) (*lint.Config, error) {
}
func createConfigMap(cfg *config.ReviveSettings) map[string]any {
+ const severity = "severity"
+
rawRoot := map[string]any{
"confidence": cfg.Confidence,
- "severity": cfg.Severity,
+ severity: cfg.Severity,
"errorCode": cfg.ErrorCode,
"warningCode": cfg.WarningCode,
"enableAllRules": cfg.EnableAllRules,
@@ -224,7 +226,7 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]any {
rawDirectives := map[string]map[string]any{}
for _, directive := range cfg.Directives {
rawDirectives[directive.Name] = map[string]any{
- "severity": directive.Severity,
+ severity: directive.Severity,
}
}
@@ -235,7 +237,7 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]any {
rawRules := map[string]map[string]any{}
for _, s := range cfg.Rules {
rawRules[s.Name] = map[string]any{
- "severity": s.Severity,
+ severity: s.Severity,
"arguments": safeTomlSlice(s.Arguments),
"disabled": s.Disabled,
"exclude": s.Exclude,
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go
index de0fe4da917..572990390d5 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go
@@ -1,7 +1,7 @@
package rowserrcheck
import (
- "github.com/jingyugao/rowserrcheck/passes/rowserr"
+ "github.com/golangci/rowserrcheck/passes/rowserr"
"github.com/golangci/golangci-lint/v2/pkg/config"
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go
index 891f1fcfdbd..2db696e5160 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go
@@ -7,22 +7,31 @@ import (
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
)
-func New(settings *config.SlogLintSettings) *goanalysis.Linter {
+func New(settings *config.SloglintSettings) *goanalysis.Linter {
var opts *sloglint.Options
if settings != nil {
opts = &sloglint.Options{
- NoMixedArgs: settings.NoMixedArgs,
- KVOnly: settings.KVOnly,
- AttrOnly: settings.AttrOnly,
- NoGlobal: settings.NoGlobal,
- ContextOnly: settings.Context,
- StaticMsg: settings.StaticMsg,
- MsgStyle: settings.MsgStyle,
- NoRawKeys: settings.NoRawKeys,
- KeyNamingCase: settings.KeyNamingCase,
- ForbiddenKeys: settings.ForbiddenKeys,
- ArgsOnSepLines: settings.ArgsOnSepLines,
+ NoGlobalLogger: settings.NoGlobal,
+ ContextOnly: settings.Context,
+ StaticMessage: settings.StaticMsg,
+ MessageStyle: settings.MsgStyle,
+ NoMixedArguments: settings.NoMixedArgs,
+ KeyValuePairsOnly: settings.KVOnly,
+ AttributesOnly: settings.AttrOnly,
+ ArgumentsOnSeparateLines: settings.ArgsOnSepLines,
+ ConstantKeys: settings.NoRawKeys,
+ AllowedKeys: settings.AllowedKeys,
+ ForbiddenKeys: settings.ForbiddenKeys,
+ KeyNamingCase: settings.KeyNamingCase,
+ }
+
+ for _, fn := range settings.CustomFuncs {
+ opts.CustomFuncs = append(opts.CustomFuncs, sloglint.Func{
+ FullName: fn.Name,
+ MessagePos: fn.MsgPos,
+ ArgumentsPos: fn.ArgsPos,
+ })
}
}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go
index cb7b2562830..8b8eef3f2b3 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go
@@ -18,12 +18,13 @@ func NewV5(settings *config.WSLv5Settings) *goanalysis.Linter {
}
conf = &wsl.Configuration{
- IncludeGenerated: true, // force to true because golangci-lint already has a way to filter generated files.
- AllowFirstInBlock: settings.AllowFirstInBlock,
- AllowWholeBlock: settings.AllowWholeBlock,
- BranchMaxLines: settings.BranchMaxLines,
- CaseMaxLines: settings.CaseMaxLines,
- Checks: checkSet,
+ IncludeGenerated: true, // force to true because golangci-lint already has a way to filter generated files.
+ AllowFirstInBlock: settings.AllowFirstInBlock,
+ AllowWholeBlock: settings.AllowWholeBlock,
+ BranchMaxLines: settings.BranchMaxLines,
+ CaseMaxLines: settings.CaseMaxLines,
+ CuddleMaxStatements: settings.CuddleMaxStatements,
+ Checks: checkSet,
}
}
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go
index a5b98413d40..2386220db55 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go
@@ -185,15 +185,18 @@ func Replacement[T any](replacement string, mgr func(T) any, data T) func(*Depre
encoder := yaml.NewEncoder(buf)
encoder.SetIndent(2)
+ linters := map[string]any{
+ "enable": []string{d.Replacement},
+ }
+
+ replacementSettings := mgr(data)
+
+ if replacementSettings != nil {
+ linters["settings"] = map[string]any{d.Replacement: replacementSettings}
+ }
+
suggestion := map[string]any{
- "linters": map[string]any{
- "enable": []string{
- d.Replacement,
- },
- "settings": map[string]any{
- d.Replacement: mgr(data),
- },
- },
+ "linters": linters,
}
err := encoder.Encode(suggestion)
diff --git a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go
index 44eadecc56d..2e9515b27a9 100644
--- a/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go
+++ b/hack/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go
@@ -9,6 +9,7 @@ import (
"github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk"
"github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose"
"github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader"
+ "github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint"
"github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx"
"github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck"
"github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar"
@@ -161,7 +162,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
WithSince("v1.43.0").
WithURL("https://github.com/breml/bidichk"),
- linter.NewConfig(bodyclose.New()).
+ linter.NewConfig(bodyclose.New(&cfg.Linters.Settings.BodyClose)).
WithSince("v1.18.0").
WithLoadForGoAnalysis().
WithURL("https://github.com/timakin/bodyclose"),
@@ -172,6 +173,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
WithAutoFix().
WithURL("https://github.com/lasiar/canonicalheader"),
+ linter.NewConfig(clickhouselint.New()).
+ WithSince("v2.12.0").
+ WithLoadForGoAnalysis().
+ WithURL("https://github.com/ClickHouse/clickhouse-go-linter"),
+
linter.NewConfig(containedctx.New()).
WithSince("v1.44.0").
WithLoadForGoAnalysis().
@@ -394,6 +400,12 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(gomodguard.New(&cfg.Linters.Settings.Gomodguard)).
WithSince("v1.25.0").
+ DeprecatedWarning("new major version.", "v2.12.0",
+ linter.Replacement("gomodguard_v2", gomodguard.Migration, &cfg.Linters.Settings.Gomodguard)).
+ WithURL("https://github.com/ryancurrah/gomodguard"),
+
+ linter.NewConfig(gomodguard.NewV2(&cfg.Linters.Settings.Gomodguardv2)).
+ WithSince("v2.12.0").
WithURL("https://github.com/ryancurrah/gomodguard"),
linter.NewConfig(goprintffuncname.New()).
@@ -593,9 +605,9 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(rowserrcheck.New(&cfg.Linters.Settings.RowsErrCheck)).
WithSince("v1.23.0").
WithLoadForGoAnalysis().
- WithURL("https://github.com/jingyugao/rowserrcheck"),
+ WithURL("https://github.com/golangci/rowserrcheck"),
- linter.NewConfig(sloglint.New(&cfg.Linters.Settings.SlogLint)).
+ linter.NewConfig(sloglint.New(&cfg.Linters.Settings.Sloglint)).
WithSince("v1.55.0").
WithLoadForGoAnalysis().
WithAutoFix().
diff --git a/hack/tools/vendor/github.com/jingyugao/rowserrcheck/LICENSE b/hack/tools/vendor/github.com/golangci/rowserrcheck/LICENSE
similarity index 100%
rename from hack/tools/vendor/github.com/jingyugao/rowserrcheck/LICENSE
rename to hack/tools/vendor/github.com/golangci/rowserrcheck/LICENSE
diff --git a/hack/tools/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go b/hack/tools/vendor/github.com/golangci/rowserrcheck/passes/rowserr/rowserr.go
similarity index 82%
rename from hack/tools/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go
rename to hack/tools/vendor/github.com/golangci/rowserrcheck/passes/rowserr/rowserr.go
index a142a67442b..a05382c69f1 100644
--- a/hack/tools/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go
+++ b/hack/tools/vendor/github.com/golangci/rowserrcheck/passes/rowserr/rowserr.go
@@ -3,6 +3,7 @@ package rowserr
import (
"go/ast"
"go/types"
+ "slices"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/buildssa"
@@ -35,21 +36,22 @@ type runner struct {
sqlPkgs []string
}
-func NewRun(pkgs ...string) func(pass *analysis.Pass) (interface{}, error) {
- return func(pass *analysis.Pass) (interface{}, error) {
- sqlPkgs := append(pkgs, "database/sql")
+func NewRun(pkgs ...string) func(pass *analysis.Pass) (any, error) {
+ return func(pass *analysis.Pass) (any, error) {
+ sqlPkgs := slices.Concat(pkgs, []string{"database/sql"})
for _, pkg := range sqlPkgs {
r := new(runner)
r.sqlPkgs = sqlPkgs
r.run(pass, pkg)
}
+
return nil, nil
}
}
// run executes an analysis for the pass. The receiver is passed
// by value because this func is called in parallel for different passes.
-func (r runner) run(pass *analysis.Pass, pkgPath string) {
+func (r *runner) run(pass *analysis.Pass, pkgPath string) {
r.pass = pass
pssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
funcs := pssa.SrcFuncs
@@ -65,6 +67,7 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) {
// skip checking
return
}
+
r.rowsObj = rowsType.Object()
if r.rowsObj == nil {
// skip checking
@@ -88,8 +91,8 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) {
// skip if the function is just referenced
var isRefFunc bool
- for i := 0; i < f.Signature.Results().Len(); i++ {
- if types.Identical(f.Signature.Results().At(i).Type(), r.rowsTyp) {
+ for v := range f.Signature.Results().Variables() {
+ if types.Identical(v.Type(), r.rowsTyp) {
isRefFunc = true
}
}
@@ -114,38 +117,59 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
return false
}
+ if call.Referrers() == nil {
+ return false
+ }
+
for _, cRef := range *call.Referrers() {
val, ok := r.getRowsVal(cRef)
if !ok {
continue
}
- if len(*val.Referrers()) == 0 {
- continue
+
+ if val.Referrers() == nil {
+ return false
}
+
resRefs := *val.Referrers()
+
+ if len(resRefs) == 0 {
+ continue
+ }
+
var errCalled func(resRef ssa.Instruction) bool
+
errCalled = func(resRef ssa.Instruction) bool {
switch resRef := resRef.(type) {
case *ssa.Phi:
- for _, rf := range *resRef.Referrers() {
- if errCalled(rf) {
- return true
- }
+ if resRef.Referrers() == nil {
+ return false
+ }
+
+ if slices.ContainsFunc(*resRef.Referrers(), errCalled) {
+ return true
}
case *ssa.Store: // Call in Closure function
+ if resRef.Addr.Referrers() == nil {
+ return false
+ }
+
for _, aref := range *resRef.Addr.Referrers() {
switch c := aref.(type) {
case *ssa.MakeClosure:
f := c.Fn.(*ssa.Function)
+
called := r.isClosureCalled(c)
if r.calledInFunc(f, called) {
return true
}
case *ssa.UnOp:
- for _, rf := range *c.Referrers() {
- if errCalled(rf) {
- return true
- }
+ if c.Referrers() == nil {
+ continue
+ }
+
+ if slices.ContainsFunc(*c.Referrers(), errCalled) {
+ return true
}
}
}
@@ -153,6 +177,7 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
if r.isErrCall(resRef) {
return true
}
+
if f, ok := resRef.Call.Value.(*ssa.Function); ok {
for _, b := range f.Blocks {
for i := range b.Instrs {
@@ -163,16 +188,22 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
}
}
case *ssa.FieldAddr:
+ if resRef.Referrers() == nil {
+ return false
+ }
+
for _, bRef := range *resRef.Referrers() {
bOp, ok := r.getBodyOp(bRef)
if !ok {
continue
}
- for _, ccall := range *bOp.Referrers() {
- if r.isErrCall(ccall) {
- return true
- }
+ if bOp.Referrers() == nil {
+ continue
+ }
+
+ if slices.ContainsFunc(*bOp.Referrers(), r.isErrCall) {
+ return true
}
}
}
@@ -180,10 +211,8 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
return false
}
- for _, resRef := range resRefs {
- if errCalled(resRef) {
- return false
- }
+ if slices.ContainsFunc(resRefs, errCalled) {
+ return false
}
}
@@ -198,11 +227,12 @@ func (r *runner) getCallReturnsRow(instr ssa.Instruction) (*ssa.Call, bool) {
res := call.Call.Signature().Results()
- for i := 0; i < res.Len(); i++ {
- typeToCheck := res.At(i).Type()
+ for v := range res.Variables() {
+ typeToCheck := v.Type()
if types.Identical(typeToCheck, r.rowsTyp) {
return call, true
}
+
if r.rowsInterface != nil && types.Implements(typeToCheck, r.rowsInterface) {
return call, true
}
@@ -217,6 +247,7 @@ func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) {
if len(instr.Call.Args) == 1 && types.Identical(instr.Call.Args[0].Type(), r.rowsTyp) {
return instr.Call.Args[0], true
}
+
if len(instr.Call.Args) == 1 && r.rowsInterface != nil && types.Implements(instr.Call.Args[0].Type(), r.rowsInterface) {
return instr.Call.Args[0], true
}
@@ -224,6 +255,7 @@ func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) {
if types.Identical(instr.Type(), r.rowsTyp) {
return instr, true
}
+
if r.rowsInterface != nil && types.Implements(instr.Type(), r.rowsInterface) {
return instr, true
}
@@ -251,6 +283,7 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool {
if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod {
return true
}
+
if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod {
return true
}
@@ -258,6 +291,7 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool {
if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod {
return true
}
+
if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod {
return true
}
@@ -267,6 +301,10 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool {
}
func (r *runner) isClosureCalled(c *ssa.MakeClosure) bool {
+ if c.Referrers() == nil {
+ return false
+ }
+
for _, ref := range *c.Referrers() {
switch ref.(type) {
case *ssa.Call, *ssa.Defer:
@@ -282,7 +320,12 @@ func (r *runner) calledInFunc(f *ssa.Function, called bool) bool {
for i, instr := range b.Instrs {
switch instr := instr.(type) {
case *ssa.UnOp:
+ if instr.Referrers() == nil {
+ continue
+ }
+
for _, ref := range *instr.Referrers() {
+ //nolint:nestif // need to be reviewed.
if v, ok := ref.(ssa.Value); ok {
if vCall, ok := v.(*ssa.Call); ok {
if vCall.Call.Value != nil && vCall.Call.Value.Name() == errMethod {
@@ -300,5 +343,6 @@ func (r *runner) calledInFunc(f *ssa.Function, called bool) bool {
}
}
}
+
return false
}
diff --git a/hack/tools/vendor/github.com/hashicorp/go-version/CHANGELOG.md b/hack/tools/vendor/github.com/hashicorp/go-version/CHANGELOG.md
index 6d48174bfbe..81b423151c3 100644
--- a/hack/tools/vendor/github.com/hashicorp/go-version/CHANGELOG.md
+++ b/hack/tools/vendor/github.com/hashicorp/go-version/CHANGELOG.md
@@ -1,3 +1,41 @@
+# 1.9.0 (Mar 30, 2026)
+
+ENHANCEMENTS:
+
+Support parsing versions with custom prefixes via opt-in option in https://github.com/hashicorp/go-version/pull/79
+
+INTERNAL:
+
+- Bump the github-actions-backward-compatible group across 1 directory with 2 updates in https://github.com/hashicorp/go-version/pull/179
+- Bump the github-actions-breaking group with 4 updates in https://github.com/hashicorp/go-version/pull/180
+- Bump the github-actions-backward-compatible group with 3 updates in https://github.com/hashicorp/go-version/pull/182
+- Update GitHub Actions to trigger on pull requests and update go version in https://github.com/hashicorp/go-version/pull/185
+- Bump actions/upload-artifact from 6.0.0 to 7.0.0 in the github-actions-breaking group across 1 directory in https://github.com/hashicorp/go-version/pull/183
+- Bump the github-actions-backward-compatible group across 1 directory with 2 updates in https://github.com/hashicorp/go-version/pull/186
+
+# 1.8.0 (Nov 28, 2025)
+
+ENHANCEMENTS:
+
+- Add benchmark test for version.String() in https://github.com/hashicorp/go-version/pull/159
+- Bytes implementation in https://github.com/hashicorp/go-version/pull/161
+
+INTERNAL:
+
+- Add CODEOWNERS file in .github/CODEOWNERS in https://github.com/hashicorp/go-version/pull/145
+- Linting in https://github.com/hashicorp/go-version/pull/151
+- Correct typos in comments in https://github.com/hashicorp/go-version/pull/134
+- Migrate GitHub Actions updates from TSCCR to Dependabot in https://github.com/hashicorp/go-version/pull/155
+- Bump the github-actions-backward-compatible group with 2 updates in https://github.com/hashicorp/go-version/pull/157
+- Update doc reference in README in https://github.com/hashicorp/go-version/pull/135
+- Bump the github-actions-breaking group with 3 updates in https://github.com/hashicorp/go-version/pull/156
+- [Compliance] - PR Template Changes Required in https://github.com/hashicorp/go-version/pull/158
+- Bump actions/cache from 4.2.3 to 4.2.4 in the github-actions-backward-compatible group in https://github.com/hashicorp/go-version/pull/167
+- Bump actions/checkout from 4.2.2 to 5.0.0 in the github-actions-breaking group in https://github.com/hashicorp/go-version/pull/166
+- Bump the github-actions-breaking group across 1 directory with 2 updates in https://github.com/hashicorp/go-version/pull/171
+- [IND-4226] [COMPLIANCE] Update Copyright Headers in https://github.com/hashicorp/go-version/pull/172
+- drop init() in https://github.com/hashicorp/go-version/pull/175
+
# 1.7.0 (May 24, 2024)
ENHANCEMENTS:
diff --git a/hack/tools/vendor/github.com/hashicorp/go-version/README.md b/hack/tools/vendor/github.com/hashicorp/go-version/README.md
index 83a8249f72c..55289602150 100644
--- a/hack/tools/vendor/github.com/hashicorp/go-version/README.md
+++ b/hack/tools/vendor/github.com/hashicorp/go-version/README.md
@@ -34,6 +34,32 @@ if v1.LessThan(v2) {
}
```
+#### Version Parsing and Comparison with Prefixes
+
+The library also supports parsing versions with a custom prefix.
+Using the `WithPrefix` option, you can specify a prefix to strip
+before parsing the version.
+
+Use `WithPrefix` when your input strings carry a known release prefix such as
+`deployment-`, `controller-`, etc.
+
+After parsing, the prefix is not part of the canonical version value. This
+means the regular comparison methods such as `Compare`, `LessThan`, `Equal`,
+and `GreaterThan` compare only the stripped version. If you compare versions
+from different prefixes with these methods, the prefixes are ignored. If you
+need to reject cross-prefix comparisons, inspect the parsed prefixes before
+comparing the versions.
+
+```go
+v1, _ := version.NewVersion("deployment-v1.2.3-beta+metadata", version.WithPrefix("deployment-"))
+v2, _ := version.NewVersion("deployment-v1.2.4", version.WithPrefix("deployment-"))
+
+if v1.LessThan(v2) {
+ fmt.Printf("%s (%s) is less than %s (%s)\n", v1, v1.Original(), v2, v2.Original())
+ // Outputs: 1.2.3-beta+metadata (deployment-v1.2.3-beta+metadata) is less than 1.2.4 (deployment-v1.2.4)
+}
+```
+
#### Version Constraints
```go
diff --git a/hack/tools/vendor/github.com/hashicorp/go-version/version.go b/hack/tools/vendor/github.com/hashicorp/go-version/version.go
index 17b29732ee1..b95503d3cf5 100644
--- a/hack/tools/vendor/github.com/hashicorp/go-version/version.go
+++ b/hack/tools/vendor/github.com/hashicorp/go-version/version.go
@@ -49,6 +49,23 @@ const (
`?`
)
+// Optional options for NewVersion function.
+type options struct {
+ // If set, this prefix will be trimmed from the version string before parsing.
+ prefix string
+}
+
+// Option is a functional option for NewVersion.
+type Option func(*options)
+
+// WithPrefix is a functional option that sets a prefix to be removed from the
+// version string before parsing.
+func WithPrefix(prefix string) Option {
+ return func(o *options) {
+ o.prefix = prefix
+ }
+}
+
// Version represents a single version.
type Version struct {
metadata string
@@ -56,12 +73,36 @@ type Version struct {
segments []int64
si int
original string
+ prefix string
}
-// NewVersion parses the given version and returns a new
-// Version.
-func NewVersion(v string) (*Version, error) {
- return newVersion(v, getVersionRegexp())
+// NewVersion parses the given version and returns a new Version.
+//
+// Optional parsing behavior can be enabled with Option values such as
+// WithPrefix, which validates and strips an expected prefix before parsing.
+func NewVersion(v string, opts ...Option) (*Version, error) {
+ options := &options{}
+ for _, opt := range opts {
+ if opt != nil {
+ opt(options)
+ }
+ }
+
+ vToParse := v
+ if options.prefix != "" {
+ if !strings.HasPrefix(v, options.prefix) {
+ return nil, fmt.Errorf("version %q does not have prefix %q", v, options.prefix)
+ }
+ vToParse = strings.TrimPrefix(v, options.prefix)
+ }
+
+ ver, err := newVersion(vToParse, getVersionRegexp())
+ if err != nil {
+ return nil, err
+ }
+ ver.prefix = options.prefix
+ ver.original = v
+ return ver, nil
}
// NewSemver parses the given version and returns a new
@@ -424,6 +465,11 @@ func (v *Version) Original() string {
return v.original
}
+// Prefix returns the explicit prefix used with WithPrefix, if any.
+func (v *Version) Prefix() string {
+ return v.prefix
+}
+
// UnmarshalText implements encoding.TextUnmarshaler interface.
func (v *Version) UnmarshalText(b []byte) error {
temp, err := NewVersion(string(b))
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/.copywrite.hcl b/hack/tools/vendor/github.com/hashicorp/hcl/v2/.copywrite.hcl
new file mode 100644
index 00000000000..35eae08227e
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/.copywrite.hcl
@@ -0,0 +1,16 @@
+schema_version = 1
+
+project {
+ license = "MPL-2.0"
+ copyright_year = 2014
+
+ # (OPTIONAL) A list of globs that should not have copyright/license headers.
+ # Supports doublestar glob patterns for more flexibility in defining which
+ # files or folders should be ignored
+ header_ignore = [
+ "hclsyntax/fuzz/testdata/**",
+ "hclwrite/fuzz/testdata/**",
+ "json/fuzz/testdata/**",
+ "specsuite/tests/**",
+ ]
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/.go-version b/hack/tools/vendor/github.com/hashicorp/hcl/v2/.go-version
new file mode 100644
index 00000000000..a1b6e17d61f
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/.go-version
@@ -0,0 +1 @@
+1.23
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/.golangci.yaml b/hack/tools/vendor/github.com/hashicorp/hcl/v2/.golangci.yaml
new file mode 100644
index 00000000000..719498be641
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/.golangci.yaml
@@ -0,0 +1,18 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+version: "2"
+issues:
+ max-issues-per-linter: 0 # show all issues found by each linter
+ max-same-issues: 0 # don't ignore same issues
+linters:
+ exclusions:
+ rules:
+ - path: hclsyntax/scan_string_lit.go # generated file, ignore errors
+ linters:
+ - unused
+ - staticcheck
+ - path: hclsyntax/scan_tokens.go # generated file, ignore errors
+ linters:
+ - unused
+ - staticcheck
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/CHANGELOG.md b/hack/tools/vendor/github.com/hashicorp/hcl/v2/CHANGELOG.md
new file mode 100644
index 00000000000..1845e7df537
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/CHANGELOG.md
@@ -0,0 +1,364 @@
+# HCL Changelog
+
+## v2.24.0 (July 7, 2025)
+
+### Enhancements
+
+* Add support for decoding block and attribute source ranges when using `gohcl`. ([#703](https://github.com/hashicorp/hcl/pull/703))
+* hclsyntax: Detect and reject invalid nested splat result. ([#724](https://github.com/hashicorp/hcl/pull/724))
+
+### Bugs Fixed
+
+* Correct handling of unknown objects in Index function. ([#763](https://github.com/hashicorp/hcl/pull/763))
+
+## v2.23.0 (November 15, 2024)
+
+### Bugs Fixed
+
+* Preserve marks when traversing through unknown values. ([#699](https://github.com/hashicorp/hcl/pull/699))
+* Retain marks through conditional and for expressions. ([#710](https://github.com/hashicorp/hcl/pull/710))
+
+## v2.22.0 (August 26, 2024)
+
+### Enhancements
+
+* feat: return an ExprSyntaxError for invalid references that end in a dot ([#692](https://github.com/hashicorp/hcl/pull/692))
+
+## v2.21.0 (June 19, 2024)
+
+### Enhancements
+
+* Introduce `ParseTraversalPartial`, which allows traversals that include the splat (`[*]`) index operator. ([#673](https://github.com/hashicorp/hcl/pull/673))
+* ext/dynblock: Now accepts marked values in `for_each`, and will transfer those marks (as much as technically possible) to values in the generated blocks. ([#679](https://github.com/hashicorp/hcl/pull/679))
+
+### Bugs Fixed
+
+* Expression evaluation will no longer panic if the splat operator is applied to an unknown value that has cty marks. ([#678](https://github.com/hashicorp/hcl/pull/678))
+
+## v2.20.1 (March 26, 2024)
+
+### Bugs Fixed
+
+* Return `ExprSyntaxError` when an invalid namespaced function is encountered during parsing ([#668](https://github.com/hashicorp/hcl/pull/668))
+
+### Internal
+
+* Standardize on only two value dumping/diffing libraries ([#669](https://github.com/hashicorp/hcl/pull/669))
+
+## v2.20.0 (February 29, 2024)
+
+### Enhancements
+
+* Support for namespaced functions ([#639](https://github.com/hashicorp/hcl/pull/639))
+
+### Bugs Fixed
+
+* ext/dynblock: if `iterator` is invalid return this error instead of consequential errors ([#656](https://github.com/hashicorp/hcl/pull/656))
+
+## v2.19.0 (October 16, 2023)
+
+### Enhancements
+
+* ext/dynblock: `dynblock.Expand` now supports an optional hook for calling applications to check and potentially veto (by returning error diagnostics) particular `for_each` values. The behavior is unchanged for callers that don't set the new option. ([#634](https://github.com/hashicorp/hcl/pull/634))
+
+### Bugs Fixed
+
+* hclsyntax: Further fixes for treatment of "marked" values in the conditional expression, and better tracking of refined values into the conditional expression results, building on the fixes from v2.18.1. ([#633](https://github.com/hashicorp/hcl/pull/633))
+
+## v2.18.1 (October 5, 2023)
+
+### Bugs Fixed
+
+* hclsyntax: Conditional expressions will no longer panic when one or both of their results are "marked", as is the case for situations like how HashiCorp Terraform tracks its concept of "sensitive values". ([#630](https://github.com/hashicorp/hcl/pull/630))
+
+## v2.18.0 (August 30, 2023)
+
+### Enhancements
+
+* HCL now uses the tables from Unicode 15 when performing string normalization and character segmentation. HCL was previously using the Unicode 13 tables.
+
+ For calling applications where consistent Unicode support is important, consider also upgrading to Go 1.21 at the same time as adopting HCL v2.18.0 so that the standard library unicode tables (used for case folding, etc) will also be from Unicode 15.
+
+## v2.17.1 (August 30, 2023)
+
+### Enhancements
+
+* hclsyntax: When evaluating string templates that have a long known constant prefix, HCL will truncate the known prefix to avoid creating excessively-large refinements. String prefix refinements are intended primarily for relatively-short fixed prefixes, such as `https://` at the start of a URL known to use that scheme. ([#617](https://github.com/hashicorp/hcl/pull/617))
+* ext/tryfunc: The "try" and "can" functions now handle unknown values slightly more precisely, and so can return known values in more situations when given expressions referring to unknown symbols. ([#622](https://github.com/hashicorp/hcl/pull/622))
+
+### Bugs Fixed
+
+* ext/typeexpr: Will no longer try to refine unknown values of unknown type when dealing with a user-specified type constraint containing the `any` keyword, avoiding an incorrect panic at runtime. ([#625](https://github.com/hashicorp/hcl/pull/625))
+* ext/typeexpr: Now correctly handles attempts to declare the same object type attribute multiple times by returning an error. Previously this could potentially panic by creating an incoherent internal state. ([#624](https://github.com/hashicorp/hcl/pull/624))
+
+## v2.17.0 (May 31, 2023)
+
+### Enhancements
+
+* HCL now uses a newer version of the upstream `cty` library which has improved treatment of unknown values: it can now track additional optional information that reduces the range of an unknown value, which allows some operations against unknown values to return known or partially-known results. ([#590](https://github.com/hashicorp/hcl/pull/590))
+
+ **Note:** This change effectively passes on [`cty`'s notion of backward compatibility](https://github.com/zclconf/go-cty/blob/main/COMPATIBILITY.md) whereby unknown values can become "more known" in later releases. In particular, if your caller is using `cty.Value.RawEquals` in its tests against the results of operations with unknown values then you may see those tests begin failing after upgrading, due to the values now being more "refined".
+
+ If so, you should review the refinements with consideration to [the `cty` refinements docs](https://github.com/zclconf/go-cty/blob/7dcbae46a6f247e983efb1fa774d2bb68781a333/docs/refinements.md) and update your expected results to match only if the reported refinements seem correct for the given situation. The `RawEquals` method is intended only for making exact value comparisons in test cases, so main application code should not use it; use `Equals` instead for real logic, which will take refinements into account automatically.
+
+## v2.16.2 (March 9, 2023)
+
+### Bugs Fixed
+
+* ext/typeexpr: Verify type assumptions when applying default values, and ignore input values that do not match type assumptions. ([#594](https://github.com/hashicorp/hcl/pull/594))
+
+## v2.16.1 (February 13, 2023)
+
+### Bugs Fixed
+
+* hclsyntax: Report correct `Range.End` for `FunctionCall` with incomplete argument ([#588](https://github.com/hashicorp/hcl/pull/588))
+
+## v2.16.0 (January 30, 2023)
+
+### Enhancements
+
+* ext/typeexpr: Modify the `Defaults` functionality to implement additional flexibility. HCL will now upcast lists and sets into tuples, and maps into objects, when applying default values if the applied defaults cause the elements within a target collection to have differing types. Previously, this would have resulted in a panic, now HCL will return a modified overall type. ([#574](https://github.com/hashicorp/hcl/pull/574))
+
+ Users should return to the advice provided by v2.14.0, and apply the go-cty convert functionality *after* setting defaults on a given `cty.Value`, rather than before.
+* hclfmt: Avoid rewriting unchanged files. ([#576](https://github.com/hashicorp/hcl/pull/576))
+* hclsyntax: Simplify the AST for certain string expressions. ([#584](https://github.com/hashicorp/hcl/pull/584))
+
+### Bugs Fixed
+
+* hclwrite: Fix data race in `formatSpaces`. ([#511](https://github.com/hashicorp/hcl/pull/511))
+
+## v2.15.0 (November 10, 2022)
+
+### Bugs Fixed
+
+* ext/typeexpr: Skip null objects when applying defaults. This prevents crashes when null objects are creating inside collections, and stops incomplete objects being created with only optional attributes set. ([#567](https://github.com/hashicorp/hcl/pull/567))
+* ext/typeexpr: Ensure default values do not have optional metadata attached. This prevents crashes when default values are inserted into concrete go-cty values that have also been stripped of their optional metadata. ([#568](https://github.com/hashicorp/hcl/pull/568))
+
+### Enhancements
+
+* ext/typeexpr: With the [go-cty](https://github.com/zclconf/go-cty) upstream depenendency updated to v1.12.0, the `Defaults` struct and associated functions can apply additional and more flexible 'unsafe' conversions (examples include tuples into collections such as lists and sets, and additional safety around null and dynamic values). ([#564](https://github.com/hashicorp/hcl/pull/564))
+* ext/typeexpr: With the [go-cty](https://github.com/zclconf/go-cty) upstream depenendency updated to v1.12.0, users should now apply the go-cty convert functionality *before* setting defaults on a given `cty.Value`, rather than after, if they require a specific `cty.Type`. ([#564](https://github.com/hashicorp/hcl/pull/564))
+
+## v2.14.1 (September 23, 2022)
+
+### Bugs Fixed
+
+* ext/typeexpr: Type convert defaults for optional object attributes when applying them. This prevents crashes in certain cases when the objects in question are part of a collection. ([#555](https://github.com/hashicorp/hcl/pull/555))
+
+## v2.14.0 (September 1, 2022)
+
+### Enhancements
+
+* ext/typeexpr: Added support for optional object attributes to `TypeConstraint`. Attributes can be wrapped in the special `optional(…)` modifier, allowing the attribute to be omitted while still meeting the type constraint. For more information, [cty's documentation on conversion between object types](https://github.com/zclconf/go-cty/blob/main/docs/convert.md#conversion-between-object-types). ([#549](https://github.com/hashicorp/hcl/pull/549))
+* ext/typeexpr: New function: `TypeConstraintWithDefaults`. In this mode, the `optional(…)` modifier accepts a second argument which can be used as the default value for omitted object attributes. The function returns both a `cty.Type` and associated `Defaults`, the latter of which has an `Apply` method to apply defaults to a given value. ([#549](https://github.com/hashicorp/hcl/pull/549))
+
+## v2.13.0 (June 22, 2022)
+
+### Enhancements
+
+* hcl: `hcl.Diagnostic` now has an additional field `Extra` which is intended for carrying arbitrary supporting data ("extra information") related to the diagnostic message, intended to allow diagnostic renderers to optionally tailor the presentation of messages for particular situations. ([#539](https://github.com/hashicorp/hcl/pull/539))
+* hclsyntax: When an error occurs during a function call, the returned diagnostics will include _extra information_ (as described in the previous point) about which function was being called and, if the message is about an error returned by the function itself, that raw `error` value without any post-processing. ([#539](https://github.com/hashicorp/hcl/pull/539))
+
+### Bugs Fixed
+
+* hclwrite: Fixed a potential data race for any situation where `hclwrite.Format` runs concurrently with itself. ([#534](https://github.com/hashicorp/hcl/pull/534))
+
+## v2.12.0 (April 22, 2022)
+
+### Enhancements
+
+* hclsyntax: Evaluation of conditional expressions will now produce more precise error messages about inconsistencies between the types of the true and false result expressions, particularly in cases where both are of the same structural type kind but differ in their nested elements. ([#530](https://github.com/hashicorp/hcl/pull/530))
+* hclsyntax: The lexer will no longer allocate a small object on the heap for each token. Instead, in that situation it will allocate only when needed to return a diagnostic message with source location information. ([#490](https://github.com/hashicorp/hcl/pull/490))
+* hclwrite: New functions `TokensForTuple`, `TokensForObject`, and `TokensForFunctionCall` allow for more easily constructing the three constructs which are supported for static analysis and which HCL-based languages typically use in contexts where an expression is used only for its syntax, and not evaluated to produce a real value. For example, these new functions together are sufficient to construct all valid type constraint expressions from [the Type Expressions Extension](./ext/typeexpr/), which is the basis of variable type constraints in the Terraform language at the time of writing. ([#502](https://github.com/hashicorp/hcl/pull/502))
+* json: New functions `IsJSONExpression` and `IsJSONBody` to determine if a given expression or body was created by the JSON syntax parser. In normal situations it's better not to worry about what syntax a particular expression/body originated in, but this can be useful in some trickier cases where an application needs to shim for backwards-compatibility or for static analysis that needs to have special handling of the JSON syntax's embedded expression/template conventions. ([#524](https://github.com/hashicorp/hcl/pull/524))
+
+### Bugs Fixed
+
+* gohcl: Fix docs about supported types for blocks. ([#507](https://github.com/hashicorp/hcl/pull/507))
+
+## v2.11.1 (December 1, 2021)
+
+### Bugs Fixed
+
+* hclsyntax: The type for an upgraded unknown value with a splat expression cannot be known ([#495](https://github.com/hashicorp/hcl/pull/495))
+
+## v2.11.0 (December 1, 2021)
+
+### Enhancements
+
+* hclsyntax: Various error messages related to unexpectedly reaching end of file while parsing a delimited subtree will now return specialized messages describing the opening tokens as "unclosed", instead of returning a generic diagnostic that just happens to refer to the empty source range at the end of the file. This gives better feedback when error messages are being presented alongside a source code snippet, as is common in HCL-based applications, because it shows which innermost container the parser was working on when it encountered the error. ([#492](https://github.com/hashicorp/hcl/pull/492))
+
+### Bugs Fixed
+
+* hclsyntax: Upgrading an unknown single value to a list using a splat expression must return unknown ([#493](https://github.com/hashicorp/hcl/pull/493))
+
+## v2.10.1 (July 21, 2021)
+
+* dynblock: Decode unknown dynamic blocks in order to obtain any diagnostics even though the decoded value is not used ([#476](https://github.com/hashicorp/hcl/pull/476))
+* hclsyntax: Calling functions is now more robust in the face of an incorrectly-implemented function which returns a `function.ArgError` whose argument index is out of range for the length of the arguments. Previously this would often lead to a panic, but now it'll return a less-precice error message instead. Functions that return out-of-bounds argument indices still ought to be fixed so that the resulting error diagnostics can be as precise as possible. ([#472](https://github.com/hashicorp/hcl/pull/472))
+* hclsyntax: Ensure marks on unknown values are maintained when processing string templates. ([#478](https://github.com/hashicorp/hcl/pull/478))
+* hcl: Improved error messages for various common error situtions in `hcl.Index` and `hcl.GetAttr`. These are part of the implementation of indexing and attribute lookup in the native syntax expression language too, so the new error messages will apply to problems using those operators. ([#474](https://github.com/hashicorp/hcl/pull/474))
+
+## v2.10.0 (April 20, 2021)
+
+### Enhancements
+
+* dynblock,hcldec: Using dynblock in conjunction with hcldec can now decode blocks with unknown dynamic for_each arguments as entirely unknown values ([#461](https://github.com/hashicorp/hcl/pull/461))
+* hclsyntax: Some syntax errors during parsing of the inside of `${` ... `}` template interpolation sequences will now produce an extra hint message about the need to escape as `$${` when trying to include interpolation syntax for other languages like shell scripting, AWS IAM policies, etc. ([#462](https://github.com/hashicorp/hcl/pull/462))
+
+## v2.9.1 (March 10, 2021)
+
+### Bugs Fixed
+
+* hclsyntax: Fix panic for marked index value. ([#451](https://github.com/hashicorp/hcl/pull/451))
+
+## v2.9.0 (February 23, 2021)
+
+### Enhancements
+
+* HCL's native syntax and JSON scanners -- and thus all of the other parsing components that build on top of them -- are now using Unicode 13 rules for text segmentation when counting text characters for the purpose of reporting source location columns. Previously HCL was using Unicode 12. Unicode 13 still uses the same algorithm but includes some additions to the character tables the algorithm is defined in terms of, to properly categorize new characters defined in Unicode 13.
+
+## v2.8.2 (January 6, 2021)
+
+### Bugs Fixed
+
+* hclsyntax: Fix panic for marked collection splat. ([#436](https://github.com/hashicorp/hcl/pull/436))
+* hclsyntax: Fix panic for marked template loops. ([#437](https://github.com/hashicorp/hcl/pull/437))
+* hclsyntax: Fix `for` expression marked conditional. ([#438](https://github.com/hashicorp/hcl/pull/438))
+* hclsyntax: Mark objects with keys that are sensitive. ([#440](https://github.com/hashicorp/hcl/pull/440))
+
+## v2.8.1 (December 17, 2020)
+
+### Bugs Fixed
+
+* hclsyntax: Fix panic when expanding marked function arguments. ([#429](https://github.com/hashicorp/hcl/pull/429))
+* hclsyntax: Error when attempting to use a marked value as an object key. ([#434](https://github.com/hashicorp/hcl/pull/434))
+* hclsyntax: Error when attempting to use a marked value as an object key in expressions. ([#433](https://github.com/hashicorp/hcl/pull/433))
+
+## v2.8.0 (December 7, 2020)
+
+### Enhancements
+
+* hclsyntax: Expression grouping parentheses will now be reflected by an explicit node in the AST, whereas before they were only considered during parsing. ([#426](https://github.com/hashicorp/hcl/pull/426))
+
+### Bugs Fixed
+
+* hclwrite: The parser will now correctly include the `(` and `)` tokens when an expression is surrounded by parentheses. Previously it would incorrectly recognize those tokens as being extraneous tokens outside of the expression. ([#426](https://github.com/hashicorp/hcl/pull/426))
+* hclwrite: The formatter will now remove (rather than insert) spaces between the `!` (unary boolean "not") operator and its subsequent operand. ([#403](https://github.com/hashicorp/hcl/pull/403))
+* hclsyntax: Unmark conditional values in expressions before checking their truthfulness ([#427](https://github.com/hashicorp/hcl/pull/427))
+
+## v2.7.2 (November 30, 2020)
+
+### Bugs Fixed
+
+* gohcl: Fix panic when decoding into type containing value slices. ([#335](https://github.com/hashicorp/hcl/pull/335))
+* hclsyntax: The unusual expression `null[*]` was previously always returning an unknown value, even though the rules for `[*]` normally call for it to return an empty tuple when applied to a null. As well as being a surprising result, it was particularly problematic because it violated the rule that a calling application may assume that an expression result will always be known unless the application itself introduces unknown values via the evaluation context. `null[*]` will now produce an empty tuple. ([#416](https://github.com/hashicorp/hcl/pull/416))
+* hclsyntax: Fix panic when traversing a list, tuple, or map with cty "marks" ([#424](https://github.com/hashicorp/hcl/pull/424))
+
+## v2.7.1 (November 18, 2020)
+
+### Bugs Fixed
+
+* hclwrite: Correctly handle blank quoted string block labels, instead of dropping them ([#422](https://github.com/hashicorp/hcl/pull/422))
+
+## v2.7.0 (October 14, 2020)
+
+### Enhancements
+
+* json: There is a new function `ParseWithStartPos`, which allows overriding the starting position for parsing in case the given JSON bytes are a fragment of a larger document, such as might happen when decoding with `encoding/json` into a `json.RawMessage`. ([#389](https://github.com/hashicorp/hcl/pull/389))
+* json: There is a new function `ParseExpression`, which allows parsing a JSON string directly in expression mode, whereas previously it was only possible to parse a JSON string in body mode. ([#381](https://github.com/hashicorp/hcl/pull/381))
+* hclwrite: `Block` type now supports `SetType` and `SetLabels`, allowing surgical changes to the type and labels of an existing block without having to reconstruct the entire block. ([#340](https://github.com/hashicorp/hcl/pull/340))
+
+### Bugs Fixed
+
+* hclsyntax: Fix confusing error message for bitwise OR operator ([#380](https://github.com/hashicorp/hcl/pull/380))
+* hclsyntax: Several bug fixes for using HCL with values containing cty "marks" ([#404](https://github.com/hashicorp/hcl/pull/404), [#406](https://github.com/hashicorp/hcl/pull/404), [#407](https://github.com/hashicorp/hcl/pull/404))
+
+## v2.6.0 (June 4, 2020)
+
+### Enhancements
+
+* hcldec: Add a new `Spec`, `ValidateSpec`, which allows custom validation of values at decode-time. ([#387](https://github.com/hashicorp/hcl/pull/387))
+
+### Bugs Fixed
+
+* hclsyntax: Fix panic with combination of sequences and null arguments ([#386](https://github.com/hashicorp/hcl/pull/386))
+* hclsyntax: Fix handling of unknown values and sequences ([#386](https://github.com/hashicorp/hcl/pull/386))
+
+## v2.5.1 (May 14, 2020)
+
+### Bugs Fixed
+
+* hclwrite: handle legacy dot access of numeric indexes. ([#369](https://github.com/hashicorp/hcl/pull/369))
+* hclwrite: Fix panic for dotted full splat (`foo.*`) ([#374](https://github.com/hashicorp/hcl/pull/374))
+
+## v2.5.0 (May 6, 2020)
+
+### Enhancements
+
+* hclwrite: Generate multi-line objects and maps. ([#372](https://github.com/hashicorp/hcl/pull/372))
+
+## v2.4.0 (Apr 13, 2020)
+
+### Enhancements
+
+* The Unicode data tables that HCL uses to produce user-perceived "column" positions in diagnostics and other source ranges are now updated to Unicode 12.0.0, which will cause HCL to produce more accurate column numbers for combining characters introduced to Unicode since Unicode 9.0.0.
+
+### Bugs Fixed
+
+* json: Fix panic when parsing malformed JSON. ([#358](https://github.com/hashicorp/hcl/pull/358))
+
+## v2.3.0 (Jan 3, 2020)
+
+### Enhancements
+
+* ext/tryfunc: Optional functions `try` and `can` to include in your `hcl.EvalContext` when evaluating expressions, which allow users to make decisions based on the success of expressions. ([#330](https://github.com/hashicorp/hcl/pull/330))
+* ext/typeexpr: Now has an optional function `convert` which you can include in your `hcl.EvalContext` when evaluating expressions, allowing users to convert values to specific type constraints using the type constraint expression syntax. ([#330](https://github.com/hashicorp/hcl/pull/330))
+* ext/typeexpr: A new `cty` capsule type `typeexpr.TypeConstraintType` which, when used as either a type constraint for a function parameter or as a type constraint for a `hcldec` attribute specification will cause the given expression to be interpreted as a type constraint expression rather than a value expression. ([#330](https://github.com/hashicorp/hcl/pull/330))
+* ext/customdecode: An optional extension that allows overriding the static decoding behavior for expressions either in function arguments or `hcldec` attribute specifications. ([#330](https://github.com/hashicorp/hcl/pull/330))
+* ext/customdecode: New `cty` capsuletypes `customdecode.ExpressionType` and `customdecode.ExpressionClosureType` which, when used as either a type constraint for a function parameter or as a type constraint for a `hcldec` attribute specification will cause the given expression (and, for the closure type, also the `hcl.EvalContext` it was evaluated in) to be captured for later analysis, rather than immediately evaluated. ([#330](https://github.com/hashicorp/hcl/pull/330))
+
+## v2.2.0 (Dec 11, 2019)
+
+### Enhancements
+
+* hcldec: Attribute evaluation (as part of `AttrSpec` or `BlockAttrsSpec`) now captures expression evaluation metadata in any errors it produces during type conversions, allowing for better feedback in calling applications that are able to make use of this metadata when printing diagnostic messages. ([#329](https://github.com/hashicorp/hcl/pull/329))
+
+### Bugs Fixed
+
+* hclsyntax: `IndexExpr`, `SplatExpr`, and `RelativeTraversalExpr` will now report a source range that covers all of their child expression nodes. Previously they would report only the operator part, such as `["foo"]`, `[*]`, or `.foo`, which was problematic for callers using source ranges for code analysis. ([#328](https://github.com/hashicorp/hcl/pull/328))
+* hclwrite: Parser will no longer panic when the input includes index, splat, or relative traversal syntax. ([#328](https://github.com/hashicorp/hcl/pull/328))
+
+## v2.1.0 (Nov 19, 2019)
+
+### Enhancements
+
+* gohcl: When decoding into a struct value with some fields already populated, those values will be retained if not explicitly overwritten in the given HCL body, with similar overriding/merging behavior as `json.Unmarshal` in the Go standard library.
+* hclwrite: New interface to set the expression for an attribute to be a raw token sequence, with no special processing. This has some caveats, so if you intend to use it please refer to the godoc comments. ([#320](https://github.com/hashicorp/hcl/pull/320))
+
+### Bugs Fixed
+
+* hclwrite: The `Body.Blocks` method was returing the blocks in an indefined order, rather than preserving the order of declaration in the source input. ([#313](https://github.com/hashicorp/hcl/pull/313))
+* hclwrite: The `TokensForTraversal` function (and thus in turn the `Body.SetAttributeTraversal` method) was not correctly handling index steps in traversals, and thus producing invalid results. ([#319](https://github.com/hashicorp/hcl/pull/319))
+
+## v2.0.0 (Oct 2, 2019)
+
+Initial release of HCL 2, which is a new implementating combining the HCL 1
+language with the HIL expression language to produce a single language
+supporting both nested configuration structures and arbitrary expressions.
+
+HCL 2 has an entirely new Go library API and so is _not_ a drop-in upgrade
+relative to HCL 1. It's possible to import both versions of HCL into a single
+program using Go's _semantic import versioning_ mechanism:
+
+```
+import (
+ hcl1 "github.com/hashicorp/hcl"
+ hcl2 "github.com/hashicorp/hcl/v2"
+)
+```
+
+---
+
+Prior to v2.0.0 there was not a curated changelog. Consult the git history
+from the latest v1.x.x tag for information on the changes to HCL 1.
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/LICENSE b/hack/tools/vendor/github.com/hashicorp/hcl/v2/LICENSE
new file mode 100644
index 00000000000..e25da5fad94
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/LICENSE
@@ -0,0 +1,355 @@
+Copyright (c) 2014 HashiCorp, Inc.
+
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. “Contributor”
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. “Contributor Version”
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor’s Contribution.
+
+1.3. “Contribution”
+
+ means Covered Software of a particular Contributor.
+
+1.4. “Covered Software”
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. “Incompatible With Secondary Licenses”
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of version
+ 1.1 or earlier of the License, but not also under the terms of a
+ Secondary License.
+
+1.6. “Executable Form”
+
+ means any form of the work other than Source Code Form.
+
+1.7. “Larger Work”
+
+ means a work that combines Covered Software with other material, in a separate
+ file or files, that is not Covered Software.
+
+1.8. “License”
+
+ means this document.
+
+1.9. “Licensable”
+
+ means having the right to grant, to the maximum extent possible, whether at the
+ time of the initial grant or subsequently, any and all of the rights conveyed by
+ this License.
+
+1.10. “Modifications”
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to, deletion
+ from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. “Patent Claims” of a Contributor
+
+ means any patent claim(s), including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by such Contributor that
+ would be infringed, but for the grant of the License, by the making,
+ using, selling, offering for sale, having made, import, or transfer of
+ either its Contributions or its Contributor Version.
+
+1.12. “Secondary License”
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. “Source Code Form”
+
+ means the form of the work preferred for making modifications.
+
+1.14. “You” (or “Your”)
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, “You” includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, “control” means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or as
+ part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its Contributions
+ or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution become
+ effective for each Contribution on the date the Contributor first distributes
+ such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under this
+ License. No additional rights or licenses will be implied from the distribution
+ or licensing of Covered Software under this License. Notwithstanding Section
+ 2.1(b) above, no patent license is granted by a Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party’s
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of its
+ Contributions.
+
+ This License does not grant any rights in the trademarks, service marks, or
+ logos of any Contributor (except as may be necessary to comply with the
+ notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this License
+ (see Section 10.2) or under the terms of a Secondary License (if permitted
+ under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its Contributions
+ are its original creation(s) or it has sufficient rights to grant the
+ rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under applicable
+ copyright doctrines of fair use, fair dealing, or other equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under the
+ terms of this License. You must inform recipients that the Source Code Form
+ of the Covered Software is governed by the terms of this License, and how
+ they can obtain a copy of this License. You may not attempt to alter or
+ restrict the recipients’ rights in the Source Code Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this License,
+ or sublicense it under different terms, provided that the license for
+ the Executable Form does not attempt to limit or alter the recipients’
+ rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for the
+ Covered Software. If the Larger Work is a combination of Covered Software
+ with a work governed by one or more Secondary Licenses, and the Covered
+ Software is not Incompatible With Secondary Licenses, this License permits
+ You to additionally distribute such Covered Software under the terms of
+ such Secondary License(s), so that the recipient of the Larger Work may, at
+ their option, further distribute the Covered Software under the terms of
+ either this License or such Secondary License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices (including
+ copyright notices, patent notices, disclaimers of warranty, or limitations
+ of liability) contained within the Source Code Form of the Covered
+ Software, except that You may alter any license notices to the extent
+ required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on behalf
+ of any Contributor. You must make it absolutely clear that any such
+ warranty, support, indemnity, or liability obligation is offered by You
+ alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute, judicial
+ order, or regulation then You must: (a) comply with the terms of this License
+ to the maximum extent possible; and (b) describe the limitations and the code
+ they affect. Such description must be placed in a text file included with all
+ distributions of the Covered Software under this License. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing basis,
+ if such Contributor fails to notify You of the non-compliance by some
+ reasonable means prior to 60 days after You have come back into compliance.
+ Moreover, Your grants from a particular Contributor are reinstated on an
+ ongoing basis if such Contributor notifies You of the non-compliance by
+ some reasonable means, this is the first time You have received notice of
+ non-compliance with this License from such Contributor, and You become
+ compliant prior to 30 days after Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions, counter-claims,
+ and cross-claims) alleging that a Contributor Version directly or
+ indirectly infringes any patent, then the rights granted to You by any and
+ all Contributors for the Covered Software under Section 2.1 of this License
+ shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an “as is” basis, without
+ warranty of any kind, either expressed, implied, or statutory, including,
+ without limitation, warranties that the Covered Software is free of defects,
+ merchantable, fit for a particular purpose or non-infringing. The entire
+ risk as to the quality and performance of the Covered Software is with You.
+ Should any Covered Software prove defective in any respect, You (not any
+ Contributor) assume the cost of any necessary servicing, repair, or
+ correction. This disclaimer of warranty constitutes an essential part of this
+ License. No use of any Covered Software is authorized under this License
+ except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from such
+ party’s negligence to the extent applicable law prohibits such limitation.
+ Some jurisdictions do not allow the exclusion or limitation of incidental or
+ consequential damages, so this exclusion and limitation may not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts of
+ a jurisdiction where the defendant maintains its principal place of business
+ and such litigation shall be governed by laws of that jurisdiction, without
+ reference to its conflict-of-law provisions. Nothing in this Section shall
+ prevent a party’s ability to bring cross-claims or counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject matter
+ hereof. If any provision of this License is held to be unenforceable, such
+ provision shall be reformed only to the extent necessary to make it
+ enforceable. Any law or regulation which provides that the language of a
+ contract shall be construed against the drafter shall not be used to construe
+ this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version of
+ the License under which You originally received the Covered Software, or
+ under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a modified
+ version of this License if you rename the license and remove any
+ references to the name of the license steward (except to note that such
+ modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
+ If You choose to distribute Source Code Form that is Incompatible With
+ Secondary Licenses under the terms of this version of the License, the
+ notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file, then
+You may include the notice in a location (such as a LICENSE file in a relevant
+directory) where a recipient would be likely to look for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - “Incompatible With Secondary Licenses” Notice
+
+ This Source Code Form is “Incompatible
+ With Secondary Licenses”, as defined by
+ the Mozilla Public License, v. 2.0.
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/Makefile b/hack/tools/vendor/github.com/hashicorp/hcl/v2/Makefile
new file mode 100644
index 00000000000..675178e7475
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/Makefile
@@ -0,0 +1,18 @@
+fmtcheck:
+ "$(CURDIR)/scripts/gofmtcheck.sh"
+
+fmtfix:
+ gofmt -w ./
+
+vetcheck:
+ go vet ./...
+
+copyrightcheck:
+ go run github.com/hashicorp/copywrite@latest headers --plan
+
+copyrightfix:
+ go run github.com/hashicorp/copywrite@latest headers
+
+check: copyrightcheck vetcheck fmtcheck
+
+fix: copyrightfix fmtfix
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/README.md b/hack/tools/vendor/github.com/hashicorp/hcl/v2/README.md
new file mode 100644
index 00000000000..9af736c9dd5
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/README.md
@@ -0,0 +1,219 @@
+# HCL
+
+HCL is a toolkit for creating structured configuration languages that are
+both human- and machine-friendly, for use with command-line tools.
+Although intended to be generally useful, it is primarily targeted
+towards devops tools, servers, etc.
+
+> **NOTE:** This is major version 2 of HCL, whose Go API is incompatible with
+> major version 1. Both versions are available for selection in Go Modules
+> projects. HCL 2 _cannot_ be imported from Go projects that are not using Go Modules. For more information, see
+> [our version selection guide](https://github.com/hashicorp/hcl/wiki/Version-Selection).
+
+HCL has both a _native syntax_, intended to be pleasant to read and write for
+humans, and a JSON-based variant that is easier for machines to generate
+and parse.
+
+The HCL native syntax is inspired by [libucl](https://github.com/vstakhov/libucl),
+[nginx configuration](http://nginx.org/en/docs/beginners_guide.html#conf_structure),
+and others.
+
+It includes an expression syntax that allows basic inline computation and,
+with support from the calling application, use of variables and functions
+for more dynamic configuration languages.
+
+HCL provides a set of constructs that can be used by a calling application to
+construct a configuration language. The application defines which attribute
+names and nested block types are expected, and HCL parses the configuration
+file, verifies that it conforms to the expected structure, and returns
+high-level objects that the application can use for further processing.
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/hashicorp/hcl/v2/hclsimple"
+)
+
+type Config struct {
+ IOMode string `hcl:"io_mode"`
+ Service ServiceConfig `hcl:"service,block"`
+}
+
+type ServiceConfig struct {
+ Protocol string `hcl:"protocol,label"`
+ Type string `hcl:"type,label"`
+ ListenAddr string `hcl:"listen_addr"`
+ Processes []ProcessConfig `hcl:"process,block"`
+}
+
+type ProcessConfig struct {
+ Type string `hcl:"type,label"`
+ Command []string `hcl:"command"`
+}
+
+func main() {
+ var config Config
+ err := hclsimple.DecodeFile("config.hcl", nil, &config)
+ if err != nil {
+ log.Fatalf("Failed to load configuration: %s", err)
+ }
+ log.Printf("Configuration is %#v", config)
+}
+```
+
+A lower-level API is available for applications that need more control over
+the parsing, decoding, and evaluation of configuration. For more information,
+see [the package documentation](https://pkg.go.dev/github.com/hashicorp/hcl/v2).
+
+## Why?
+
+Newcomers to HCL often ask: why not JSON, YAML, etc?
+
+Whereas JSON and YAML are formats for serializing data structures, HCL is
+a syntax and API specifically designed for building structured configuration
+formats.
+
+HCL attempts to strike a compromise between generic serialization formats
+such as JSON and configuration formats built around full programming languages
+such as Ruby. HCL syntax is designed to be easily read and written by humans,
+and allows _declarative_ logic to permit its use in more complex applications.
+
+HCL is intended as a base syntax for configuration formats built
+around key-value pairs and hierarchical blocks whose structure is well-defined
+by the calling application, and this definition of the configuration structure
+allows for better error messages and more convenient definition within the
+calling application.
+
+It can't be denied that JSON is very convenient as a _lingua franca_
+for interoperability between different pieces of software. Because of this,
+HCL defines a common configuration model that can be parsed from either its
+native syntax or from a well-defined equivalent JSON structure. This allows
+configuration to be provided as a mixture of human-authored configuration
+files in the native syntax and machine-generated files in JSON.
+
+## Information Model and Syntax
+
+HCL is built around two primary concepts: _attributes_ and _blocks_. In
+native syntax, a configuration file for a hypothetical application might look
+something like this:
+
+```hcl
+io_mode = "async"
+
+service "http" "web_proxy" {
+ listen_addr = "127.0.0.1:8080"
+
+ process "main" {
+ command = ["/usr/local/bin/awesome-app", "server"]
+ }
+
+ process "mgmt" {
+ command = ["/usr/local/bin/awesome-app", "mgmt"]
+ }
+}
+```
+
+The JSON equivalent of this configuration is the following:
+
+```json
+{
+ "io_mode": "async",
+ "service": {
+ "http": {
+ "web_proxy": {
+ "listen_addr": "127.0.0.1:8080",
+ "process": {
+ "main": {
+ "command": ["/usr/local/bin/awesome-app", "server"]
+ },
+ "mgmt": {
+ "command": ["/usr/local/bin/awesome-app", "mgmt"]
+ },
+ }
+ }
+ }
+ }
+}
+```
+
+Regardless of which syntax is used, the API within the calling application
+is the same. It can either work directly with the low-level attributes and
+blocks, for more advanced use-cases, or it can use one of the _decoder_
+packages to declaratively extract into either Go structs or dynamic value
+structures.
+
+Attribute values can be expressions as well as just literal values:
+
+```hcl
+# Arithmetic with literals and application-provided variables
+sum = 1 + addend
+
+# String interpolation and templates
+message = "Hello, ${name}!"
+
+# Application-provided functions
+shouty_message = upper(message)
+```
+
+Although JSON syntax doesn't permit direct use of expressions, the interpolation
+syntax allows use of arbitrary expressions within JSON strings:
+
+```json
+{
+ "sum": "${1 + addend}",
+ "message": "Hello, ${name}!",
+ "shouty_message": "${upper(message)}"
+}
+```
+
+For more information, see the detailed specifications:
+
+* [Syntax-agnostic Information Model](spec.md)
+* [HCL Native Syntax](hclsyntax/spec.md)
+* [JSON Representation](json/spec.md)
+
+## Changes in 2.0
+
+Version 2.0 of HCL combines the features of HCL 1.0 with those of the
+interpolation language HIL to produce a single configuration language that
+supports arbitrary expressions.
+
+This new version has a completely new parser and Go API, with no direct
+migration path. Although the syntax is similar, the implementation takes some
+very different approaches to improve on some "rough edges" that existed with
+the original implementation and to allow for more robust error handling.
+
+It's possible to import both HCL 1 and HCL 2 into the same program using Go's
+_semantic import versioning_ mechanism:
+
+```go
+import (
+ hcl1 "github.com/hashicorp/hcl"
+ hcl2 "github.com/hashicorp/hcl/v2"
+)
+```
+
+## Acknowledgements
+
+HCL was heavily inspired by [libucl](https://github.com/vstakhov/libucl),
+by [Vsevolod Stakhov](https://github.com/vstakhov).
+
+HCL and HIL originate in [HashiCorp Terraform](https://terraform.io/),
+with the original parsers for each written by
+[Mitchell Hashimoto](https://github.com/mitchellh).
+
+The original HCL parser was ported to pure Go (from yacc) by
+[Fatih Arslan](https://github.com/fatih). The structure-related portions of
+the new native syntax parser build on that work.
+
+The original HIL parser was ported to pure Go (from yacc) by
+[Martin Atkins](https://github.com/apparentlymart). The expression-related
+portions of the new native syntax parser build on that work.
+
+HCL 2, which merged the original HCL and HIL languages into this single new
+language, builds on design and prototyping work by
+[Martin Atkins](https://github.com/apparentlymart) in
+[zcl](https://github.com/zclconf/go-zcl).
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic.go
new file mode 100644
index 00000000000..a61bb30669f
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic.go
@@ -0,0 +1,189 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "fmt"
+)
+
+// DiagnosticSeverity represents the severity of a diagnostic.
+type DiagnosticSeverity int
+
+const (
+ // DiagInvalid is the invalid zero value of DiagnosticSeverity
+ DiagInvalid DiagnosticSeverity = iota
+
+ // DiagError indicates that the problem reported by a diagnostic prevents
+ // further progress in parsing and/or evaluating the subject.
+ DiagError
+
+ // DiagWarning indicates that the problem reported by a diagnostic warrants
+ // user attention but does not prevent further progress. It is most
+ // commonly used for showing deprecation notices.
+ DiagWarning
+)
+
+// Diagnostic represents information to be presented to a user about an
+// error or anomaly in parsing or evaluating configuration.
+type Diagnostic struct {
+ Severity DiagnosticSeverity
+
+ // Summary and Detail contain the English-language description of the
+ // problem. Summary is a terse description of the general problem and
+ // detail is a more elaborate, often-multi-sentence description of
+ // the problem and what might be done to solve it.
+ Summary string
+ Detail string
+
+ // Subject and Context are both source ranges relating to the diagnostic.
+ //
+ // Subject is a tight range referring to exactly the construct that
+ // is problematic, while Context is an optional broader range (which should
+ // fully contain Subject) that ought to be shown around Subject when
+ // generating isolated source-code snippets in diagnostic messages.
+ // If Context is nil, the Subject is also the Context.
+ //
+ // Some diagnostics have no source ranges at all. If Context is set then
+ // Subject should always also be set.
+ Subject *Range
+ Context *Range
+
+ // For diagnostics that occur when evaluating an expression, Expression
+ // may refer to that expression and EvalContext may point to the
+ // EvalContext that was active when evaluating it. This may allow for the
+ // inclusion of additional useful information when rendering a diagnostic
+ // message to the user.
+ //
+ // It is not always possible to select a single EvalContext for a
+ // diagnostic, and so in some cases this field may be nil even when an
+ // expression causes a problem.
+ //
+ // EvalContexts form a tree, so the given EvalContext may refer to a parent
+ // which in turn refers to another parent, etc. For a full picture of all
+ // of the active variables and functions the caller must walk up this
+ // chain, preferring definitions that are "closer" to the expression in
+ // case of colliding names.
+ Expression Expression
+ EvalContext *EvalContext
+
+ // Extra is an extension point for additional machine-readable information
+ // about this problem.
+ //
+ // Recipients of diagnostic objects may type-assert this value with
+ // specific interface types they know about to discover if any additional
+ // information is available that is interesting for their use-case.
+ //
+ // Extra is always considered to be optional extra information and so a
+ // diagnostic message should still always be fully described (from the
+ // perspective of a human who understands the language the messages are
+ // written in) by the other fields in case a particular recipient.
+ //
+ // Functions that return diagnostics with Extra populated should typically
+ // document that they place values implementing a particular interface,
+ // rather than a concrete type, and define that interface such that its
+ // methods can dynamically indicate a lack of support at runtime even
+ // if the interface happens to be statically available. An Extra
+ // type that wraps other Extra values should additionally implement
+ // interface DiagnosticExtraUnwrapper to return the value they are wrapping
+ // so that callers can access inner values to type-assert against.
+ Extra interface{}
+}
+
+// Diagnostics is a list of Diagnostic instances.
+type Diagnostics []*Diagnostic
+
+// error implementation, so that diagnostics can be returned via APIs
+// that normally deal in vanilla Go errors.
+//
+// This presents only minimal context about the error, for compatibility
+// with usual expectations about how errors will present as strings.
+func (d *Diagnostic) Error() string {
+ return fmt.Sprintf("%s: %s; %s", d.Subject, d.Summary, d.Detail)
+}
+
+// error implementation, so that sets of diagnostics can be returned via
+// APIs that normally deal in vanilla Go errors.
+func (d Diagnostics) Error() string {
+ count := len(d)
+ switch count {
+ case 0:
+ return "no diagnostics"
+ case 1:
+ return d[0].Error()
+ default:
+ return fmt.Sprintf("%s, and %d other diagnostic(s)", d[0].Error(), count-1)
+ }
+}
+
+// Append appends a new error to a Diagnostics and return the whole Diagnostics.
+//
+// This is provided as a convenience for returning from a function that
+// collects and then returns a set of diagnostics:
+//
+// return nil, diags.Append(&hcl.Diagnostic{ ... })
+//
+// Note that this modifies the array underlying the diagnostics slice, so
+// must be used carefully within a single codepath. It is incorrect (and rude)
+// to extend a diagnostics created by a different subsystem.
+func (d Diagnostics) Append(diag *Diagnostic) Diagnostics {
+ return append(d, diag)
+}
+
+// Extend concatenates the given Diagnostics with the receiver and returns
+// the whole new Diagnostics.
+//
+// This is similar to Append but accepts multiple diagnostics to add. It has
+// all the same caveats and constraints.
+func (d Diagnostics) Extend(diags Diagnostics) Diagnostics {
+ return append(d, diags...)
+}
+
+// HasErrors returns true if the receiver contains any diagnostics of
+// severity DiagError.
+func (d Diagnostics) HasErrors() bool {
+ for _, diag := range d {
+ if diag.Severity == DiagError {
+ return true
+ }
+ }
+ return false
+}
+
+func (d Diagnostics) Errs() []error {
+ var errs []error
+ for _, diag := range d {
+ if diag.Severity == DiagError {
+ errs = append(errs, diag)
+ }
+ }
+
+ return errs
+}
+
+// A DiagnosticWriter emits diagnostics somehow.
+type DiagnosticWriter interface {
+ WriteDiagnostic(*Diagnostic) error
+ WriteDiagnostics(Diagnostics) error
+}
+
+// DiagnosticExtraUnwrapper is an interface implemented by values in the
+// Extra field of Diagnostic when they are wrapping another "Extra" value that
+// was generated downstream.
+//
+// Diagnostic recipients which want to examine "Extra" values to sniff for
+// particular types of extra data can either type-assert this interface
+// directly and repeatedly unwrap until they recieve nil, or can use the
+// helper function DiagnosticExtra.
+type DiagnosticExtraUnwrapper interface {
+ // If the reciever is wrapping another "diagnostic extra" value, returns
+ // that value. Otherwise returns nil to indicate dynamically that nothing
+ // is wrapped.
+ //
+ // The "nothing is wrapped" condition can be signalled either by this
+ // method returning nil or by a type not implementing this interface at all.
+ //
+ // Implementers should never create unwrap "cycles" where a nested extra
+ // value returns a value that was also wrapping it.
+ UnwrapDiagnosticExtra() interface{}
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic_text.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic_text.go
new file mode 100644
index 00000000000..294eb1848aa
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic_text.go
@@ -0,0 +1,345 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "sort"
+
+ wordwrap "github.com/mitchellh/go-wordwrap"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type diagnosticTextWriter struct {
+ files map[string]*File
+ wr io.Writer
+ width uint
+ color bool
+}
+
+// NewDiagnosticTextWriter creates a DiagnosticWriter that writes diagnostics
+// to the given writer as formatted text.
+//
+// It is designed to produce text appropriate to print in a monospaced font
+// in a terminal of a particular width, or optionally with no width limit.
+//
+// The given width may be zero to disable word-wrapping of the detail text
+// and truncation of source code snippets.
+//
+// If color is set to true, the output will include VT100 escape sequences to
+// color-code the severity indicators. It is suggested to turn this off if
+// the target writer is not a terminal.
+func NewDiagnosticTextWriter(wr io.Writer, files map[string]*File, width uint, color bool) DiagnosticWriter {
+ return &diagnosticTextWriter{
+ files: files,
+ wr: wr,
+ width: width,
+ color: color,
+ }
+}
+
+func (w *diagnosticTextWriter) WriteDiagnostic(diag *Diagnostic) error {
+ if diag == nil {
+ return errors.New("nil diagnostic")
+ }
+
+ var colorCode, highlightCode, resetCode string
+ if w.color {
+ switch diag.Severity {
+ case DiagError:
+ colorCode = "\x1b[31m"
+ case DiagWarning:
+ colorCode = "\x1b[33m"
+ }
+ resetCode = "\x1b[0m"
+ highlightCode = "\x1b[1;4m"
+ }
+
+ var severityStr string
+ switch diag.Severity {
+ case DiagError:
+ severityStr = "Error"
+ case DiagWarning:
+ severityStr = "Warning"
+ default:
+ // should never happen
+ severityStr = "???????"
+ }
+
+ _, err := fmt.Fprintf(w.wr, "%s%s%s: %s\n\n", colorCode, severityStr, resetCode, diag.Summary)
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+
+ if diag.Subject != nil {
+ snipRange := *diag.Subject
+ highlightRange := snipRange
+ if diag.Context != nil {
+ // Show enough of the source code to include both the subject
+ // and context ranges, which overlap in all reasonable
+ // situations.
+ snipRange = RangeOver(snipRange, *diag.Context)
+ }
+ // We can't illustrate an empty range, so we'll turn such ranges into
+ // single-character ranges, which might not be totally valid (may point
+ // off the end of a line, or off the end of the file) but are good
+ // enough for the bounds checks we do below.
+ if snipRange.Empty() {
+ snipRange.End.Byte++
+ snipRange.End.Column++
+ }
+ if highlightRange.Empty() {
+ highlightRange.End.Byte++
+ highlightRange.End.Column++
+ }
+
+ file := w.files[diag.Subject.Filename]
+ if file == nil || file.Bytes == nil {
+ _, err = fmt.Fprintf(w.wr, " on %s line %d:\n (source code not available)\n\n", diag.Subject.Filename, diag.Subject.Start.Line)
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ } else {
+
+ var contextLine string
+ if diag.Subject != nil {
+ contextLine = contextString(file, diag.Subject.Start.Byte)
+ if contextLine != "" {
+ contextLine = ", in " + contextLine
+ }
+ }
+
+ _, err = fmt.Fprintf(w.wr, " on %s line %d%s:\n", diag.Subject.Filename, diag.Subject.Start.Line, contextLine)
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+
+ src := file.Bytes
+ sc := NewRangeScanner(src, diag.Subject.Filename, bufio.ScanLines)
+
+ for sc.Scan() {
+ lineRange := sc.Range()
+ if !lineRange.Overlaps(snipRange) {
+ continue
+ }
+
+ beforeRange, highlightedRange, afterRange := lineRange.PartitionAround(highlightRange)
+ if highlightedRange.Empty() {
+ _, err = fmt.Fprintf(w.wr, "%4d: %s\n", lineRange.Start.Line, sc.Bytes())
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ } else {
+ before := beforeRange.SliceBytes(src)
+ highlighted := highlightedRange.SliceBytes(src)
+ after := afterRange.SliceBytes(src)
+ _, err = fmt.Fprintf(
+ w.wr, "%4d: %s%s%s%s%s\n",
+ lineRange.Start.Line,
+ before,
+ highlightCode, highlighted, resetCode,
+ after,
+ )
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ }
+
+ }
+
+ _, err = w.wr.Write([]byte{'\n'})
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ }
+
+ if diag.Expression != nil && diag.EvalContext != nil {
+ // We will attempt to render the values for any variables
+ // referenced in the given expression as additional context, for
+ // situations where the same expression is evaluated multiple
+ // times in different scopes.
+ expr := diag.Expression
+ ctx := diag.EvalContext
+
+ vars := expr.Variables()
+ stmts := make([]string, 0, len(vars))
+ seen := make(map[string]struct{}, len(vars))
+ for _, traversal := range vars {
+ val, diags := traversal.TraverseAbs(ctx)
+ if diags.HasErrors() {
+ // Skip anything that generates errors, since we probably
+ // already have the same error in our diagnostics set
+ // already.
+ continue
+ }
+
+ traversalStr := w.traversalStr(traversal)
+ if _, exists := seen[traversalStr]; exists {
+ continue // don't show duplicates when the same variable is referenced multiple times
+ }
+ switch {
+ case !val.IsKnown():
+ // Can't say anything about this yet, then.
+ continue
+ case val.IsNull():
+ stmts = append(stmts, fmt.Sprintf("%s set to null", traversalStr))
+ default:
+ stmts = append(stmts, fmt.Sprintf("%s as %s", traversalStr, w.valueStr(val)))
+ }
+ seen[traversalStr] = struct{}{}
+ }
+
+ sort.Strings(stmts) // FIXME: Should maybe use a traversal-aware sort that can sort numeric indexes properly?
+ last := len(stmts) - 1
+
+ for i, stmt := range stmts {
+ switch i {
+ case 0:
+ _, err = w.wr.Write([]byte{'w', 'i', 't', 'h', ' '})
+ default:
+ _, err = w.wr.Write([]byte{' ', ' ', ' ', ' ', ' '})
+ }
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+
+ _, err = w.wr.Write([]byte(stmt))
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ switch i {
+ case last:
+ _, err = w.wr.Write([]byte{'.', '\n', '\n'})
+ default:
+ _, err = w.wr.Write([]byte{',', '\n'})
+ }
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ }
+ }
+ }
+
+ if diag.Detail != "" {
+ detail := diag.Detail
+ if w.width != 0 {
+ detail = wordwrap.WrapString(detail, w.width)
+ }
+ _, err = fmt.Fprintf(w.wr, "%s\n\n", detail)
+ if err != nil {
+ return fmt.Errorf("write failed: %w", err)
+ }
+ }
+
+ return nil
+}
+
+func (w *diagnosticTextWriter) WriteDiagnostics(diags Diagnostics) error {
+ for _, diag := range diags {
+ err := w.WriteDiagnostic(diag)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (w *diagnosticTextWriter) traversalStr(traversal Traversal) string {
+ // This is a specialized subset of traversal rendering tailored to
+ // producing helpful contextual messages in diagnostics. It is not
+ // comprehensive nor intended to be used for other purposes.
+
+ var buf bytes.Buffer
+ for _, step := range traversal {
+ switch tStep := step.(type) {
+ case TraverseRoot:
+ buf.WriteString(tStep.Name)
+ case TraverseAttr:
+ buf.WriteByte('.')
+ buf.WriteString(tStep.Name)
+ case TraverseIndex:
+ buf.WriteByte('[')
+ if keyTy := tStep.Key.Type(); keyTy.IsPrimitiveType() {
+ buf.WriteString(w.valueStr(tStep.Key))
+ } else {
+ // We'll just use a placeholder for more complex values,
+ // since otherwise our result could grow ridiculously long.
+ buf.WriteString("...")
+ }
+ buf.WriteByte(']')
+ }
+ }
+ return buf.String()
+}
+
+func (w *diagnosticTextWriter) valueStr(val cty.Value) string {
+ // This is a specialized subset of value rendering tailored to producing
+ // helpful but concise messages in diagnostics. It is not comprehensive
+ // nor intended to be used for other purposes.
+
+ ty := val.Type()
+ switch {
+ case val.IsNull():
+ return "null"
+ case !val.IsKnown():
+ // Should never happen here because we should filter before we get
+ // in here, but we'll do something reasonable rather than panic.
+ return "(not yet known)"
+ case ty == cty.Bool:
+ if val.True() {
+ return "true"
+ }
+ return "false"
+ case ty == cty.Number:
+ bf := val.AsBigFloat()
+ return bf.Text('g', 10)
+ case ty == cty.String:
+ // Go string syntax is not exactly the same as HCL native string syntax,
+ // but we'll accept the minor edge-cases where this is different here
+ // for now, just to get something reasonable here.
+ return fmt.Sprintf("%q", val.AsString())
+ case ty.IsCollectionType() || ty.IsTupleType():
+ l := val.LengthInt()
+ switch l {
+ case 0:
+ return "empty " + ty.FriendlyName()
+ case 1:
+ return ty.FriendlyName() + " with 1 element"
+ default:
+ return fmt.Sprintf("%s with %d elements", ty.FriendlyName(), l)
+ }
+ case ty.IsObjectType():
+ atys := ty.AttributeTypes()
+ l := len(atys)
+ switch l {
+ case 0:
+ return "object with no attributes"
+ case 1:
+ var name string
+ for k := range atys {
+ name = k
+ }
+ return fmt.Sprintf("object with 1 attribute %q", name)
+ default:
+ return fmt.Sprintf("object with %d attributes", l)
+ }
+ default:
+ return ty.FriendlyName()
+ }
+}
+
+func contextString(file *File, offset int) string {
+ type contextStringer interface {
+ ContextString(offset int) string
+ }
+
+ if cser, ok := file.Nav.(contextStringer); ok {
+ return cser.ContextString(offset)
+ }
+ return ""
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic_typeparams.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic_typeparams.go
new file mode 100644
index 00000000000..92be8f1a85f
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/diagnostic_typeparams.go
@@ -0,0 +1,42 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build go1.18
+// +build go1.18
+
+package hcl
+
+// This file contains additional diagnostics-related symbols that use the
+// Go 1.18 type parameters syntax and would therefore be incompatible with
+// Go 1.17 and earlier.
+
+// DiagnosticExtra attempts to retrieve an "extra value" of type T from the
+// given diagnostic, if either the diag.Extra field directly contains a value
+// of that type or the value implements DiagnosticExtraUnwrapper and directly
+// or indirectly returns a value of that type.
+//
+// Type T should typically be an interface type, so that code which generates
+// diagnostics can potentially return different implementations of the same
+// interface dynamically as needed.
+//
+// If a value of type T is found, returns that value and true to indicate
+// success. Otherwise, returns the zero value of T and false to indicate
+// failure.
+func DiagnosticExtra[T any](diag *Diagnostic) (T, bool) {
+ extra := diag.Extra
+ var zero T
+
+ for {
+ if ret, ok := extra.(T); ok {
+ return ret, true
+ }
+
+ if unwrap, ok := extra.(DiagnosticExtraUnwrapper); ok {
+ // If our "extra" implements DiagnosticExtraUnwrapper then we'll
+ // unwrap one level and try this again.
+ extra = unwrap.UnwrapDiagnosticExtra()
+ } else {
+ return zero, false
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/didyoumean.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/didyoumean.go
new file mode 100644
index 00000000000..fd00ca6f65b
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/didyoumean.go
@@ -0,0 +1,27 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "github.com/agext/levenshtein"
+)
+
+// nameSuggestion tries to find a name from the given slice of suggested names
+// that is close to the given name and returns it if found. If no suggestion
+// is close enough, returns the empty string.
+//
+// The suggestions are tried in order, so earlier suggestions take precedence
+// if the given string is similar to two or more suggestions.
+//
+// This function is intended to be used with a relatively-small number of
+// suggestions. It's not optimized for hundreds or thousands of them.
+func nameSuggestion(given string, suggestions []string) string {
+ for _, suggestion := range suggestions {
+ dist := levenshtein.Distance(given, suggestion, nil)
+ if dist < 3 { // threshold determined experimentally
+ return suggestion
+ }
+ }
+ return ""
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/doc.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/doc.go
new file mode 100644
index 00000000000..665ad6cadba
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/doc.go
@@ -0,0 +1,37 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package hcl contains the main modelling types and general utility functions
+// for HCL.
+//
+// For a simple entry point into HCL, see the package in the subdirectory
+// "hclsimple", which has an opinionated function Decode that can decode HCL
+// configurations in either native HCL syntax or JSON syntax into a Go struct
+// type:
+//
+// package main
+//
+// import (
+// "log"
+// "github.com/hashicorp/hcl/v2/hclsimple"
+// )
+//
+// type Config struct {
+// LogLevel string `hcl:"log_level"`
+// }
+//
+// func main() {
+// var config Config
+// err := hclsimple.DecodeFile("config.hcl", nil, &config)
+// if err != nil {
+// log.Fatalf("Failed to load configuration: %s", err)
+// }
+// log.Printf("Configuration is %#v", config)
+// }
+//
+// If your application needs more control over the evaluation of the
+// configuration, you can use the functions in the subdirectories hclparse,
+// gohcl, hcldec, etc. Splitting the handling of configuration into multiple
+// phases allows for advanced patterns such as allowing expressions in one
+// part of the configuration to refer to data defined in another part.
+package hcl
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/eval_context.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/eval_context.go
new file mode 100644
index 00000000000..921cfcb429c
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/eval_context.go
@@ -0,0 +1,28 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// An EvalContext provides the variables and functions that should be used
+// to evaluate an expression.
+type EvalContext struct {
+ Variables map[string]cty.Value
+ Functions map[string]function.Function
+ parent *EvalContext
+}
+
+// NewChild returns a new EvalContext that is a child of the receiver.
+func (ctx *EvalContext) NewChild() *EvalContext {
+ return &EvalContext{parent: ctx}
+}
+
+// Parent returns the parent of the receiver, or nil if the receiver has
+// no parent.
+func (ctx *EvalContext) Parent() *EvalContext {
+ return ctx.parent
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_call.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_call.go
new file mode 100644
index 00000000000..ca59b90d236
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_call.go
@@ -0,0 +1,49 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+// ExprCall tests if the given expression is a function call and,
+// if so, extracts the function name and the expressions that represent
+// the arguments. If the given expression is not statically a function call,
+// error diagnostics are returned.
+//
+// A particular Expression implementation can support this function by
+// offering a method called ExprCall that takes no arguments and returns
+// *StaticCall. This method should return nil if a static call cannot
+// be extracted. Alternatively, an implementation can support
+// UnwrapExpression to delegate handling of this function to a wrapped
+// Expression object.
+func ExprCall(expr Expression) (*StaticCall, Diagnostics) {
+ type exprCall interface {
+ ExprCall() *StaticCall
+ }
+
+ physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
+ _, supported := expr.(exprCall)
+ return supported
+ })
+
+ if exC, supported := physExpr.(exprCall); supported {
+ if call := exC.ExprCall(); call != nil {
+ return call, nil
+ }
+ }
+ return nil, Diagnostics{
+ &Diagnostic{
+ Severity: DiagError,
+ Summary: "Invalid expression",
+ Detail: "A static function call is required.",
+ Subject: expr.StartRange().Ptr(),
+ },
+ }
+}
+
+// StaticCall represents a function call that was extracted statically from
+// an expression using ExprCall.
+type StaticCall struct {
+ Name string
+ NameRange Range
+ Arguments []Expression
+ ArgsRange Range
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_list.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_list.go
new file mode 100644
index 00000000000..8c0cf40518e
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_list.go
@@ -0,0 +1,40 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+// ExprList tests if the given expression is a static list construct and,
+// if so, extracts the expressions that represent the list elements.
+// If the given expression is not a static list, error diagnostics are
+// returned.
+//
+// A particular Expression implementation can support this function by
+// offering a method called ExprList that takes no arguments and returns
+// []Expression. This method should return nil if a static list cannot
+// be extracted. Alternatively, an implementation can support
+// UnwrapExpression to delegate handling of this function to a wrapped
+// Expression object.
+func ExprList(expr Expression) ([]Expression, Diagnostics) {
+ type exprList interface {
+ ExprList() []Expression
+ }
+
+ physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
+ _, supported := expr.(exprList)
+ return supported
+ })
+
+ if exL, supported := physExpr.(exprList); supported {
+ if list := exL.ExprList(); list != nil {
+ return list, nil
+ }
+ }
+ return nil, Diagnostics{
+ &Diagnostic{
+ Severity: DiagError,
+ Summary: "Invalid expression",
+ Detail: "A static list expression is required.",
+ Subject: expr.StartRange().Ptr(),
+ },
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_map.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_map.go
new file mode 100644
index 00000000000..56cf974740c
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_map.go
@@ -0,0 +1,47 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+// ExprMap tests if the given expression is a static map construct and,
+// if so, extracts the expressions that represent the map elements.
+// If the given expression is not a static map, error diagnostics are
+// returned.
+//
+// A particular Expression implementation can support this function by
+// offering a method called ExprMap that takes no arguments and returns
+// []KeyValuePair. This method should return nil if a static map cannot
+// be extracted. Alternatively, an implementation can support
+// UnwrapExpression to delegate handling of this function to a wrapped
+// Expression object.
+func ExprMap(expr Expression) ([]KeyValuePair, Diagnostics) {
+ type exprMap interface {
+ ExprMap() []KeyValuePair
+ }
+
+ physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
+ _, supported := expr.(exprMap)
+ return supported
+ })
+
+ if exM, supported := physExpr.(exprMap); supported {
+ if pairs := exM.ExprMap(); pairs != nil {
+ return pairs, nil
+ }
+ }
+ return nil, Diagnostics{
+ &Diagnostic{
+ Severity: DiagError,
+ Summary: "Invalid expression",
+ Detail: "A static map expression is required.",
+ Subject: expr.StartRange().Ptr(),
+ },
+ }
+}
+
+// KeyValuePair represents a pair of expressions that serve as a single item
+// within a map or object definition construct.
+type KeyValuePair struct {
+ Key Expression
+ Value Expression
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_unwrap.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_unwrap.go
new file mode 100644
index 00000000000..6683fd54440
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/expr_unwrap.go
@@ -0,0 +1,71 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+type unwrapExpression interface {
+ UnwrapExpression() Expression
+}
+
+// UnwrapExpression removes any "wrapper" expressions from the given expression,
+// to recover the representation of the physical expression given in source
+// code.
+//
+// Sometimes wrapping expressions are used to modify expression behavior, e.g.
+// in extensions that need to make some local variables available to certain
+// sub-trees of the configuration. This can make it difficult to reliably
+// type-assert on the physical AST types used by the underlying syntax.
+//
+// Unwrapping an expression may modify its behavior by stripping away any
+// additional constraints or capabilities being applied to the Value and
+// Variables methods, so this function should generally only be used prior
+// to operations that concern themselves with the static syntax of the input
+// configuration, and not with the effective value of the expression.
+//
+// Wrapper expression types must support unwrapping by implementing a method
+// called UnwrapExpression that takes no arguments and returns the embedded
+// Expression. Implementations of this method should peel away only one level
+// of wrapping, if multiple are present. This method may return nil to
+// indicate _dynamically_ that no wrapped expression is available, for
+// expression types that might only behave as wrappers in certain cases.
+func UnwrapExpression(expr Expression) Expression {
+ for {
+ unwrap, wrapped := expr.(unwrapExpression)
+ if !wrapped {
+ return expr
+ }
+ innerExpr := unwrap.UnwrapExpression()
+ if innerExpr == nil {
+ return expr
+ }
+ expr = innerExpr
+ }
+}
+
+// UnwrapExpressionUntil is similar to UnwrapExpression except it gives the
+// caller an opportunity to test each level of unwrapping to see each a
+// particular expression is accepted.
+//
+// This could be used, for example, to unwrap until a particular other
+// interface is satisfied, regardless of wrap wrapping level it is satisfied
+// at.
+//
+// The given callback function must return false to continue wrapping, or
+// true to accept and return the proposed expression given. If the callback
+// function rejects even the final, physical expression then the result of
+// this function is nil.
+func UnwrapExpressionUntil(expr Expression, until func(Expression) bool) Expression {
+ for {
+ if until(expr) {
+ return expr
+ }
+ unwrap, wrapped := expr.(unwrapExpression)
+ if !wrapped {
+ return nil
+ }
+ expr = unwrap.UnwrapExpression()
+ if expr == nil {
+ return nil
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/README.md b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/README.md
new file mode 100644
index 00000000000..1636f577a02
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/README.md
@@ -0,0 +1,209 @@
+# HCL Custom Static Decoding Extension
+
+This HCL extension provides a mechanism for defining arguments in an HCL-based
+language whose values are derived using custom decoding rules against the
+HCL expression syntax, overriding the usual behavior of normal expression
+evaluation.
+
+"Arguments", for the purpose of this extension, currently includes the
+following two contexts:
+
+* For applications using `hcldec` for dynamic decoding, a `hcldec.AttrSpec`
+ or `hcldec.BlockAttrsSpec` can be given a special type constraint that
+ opts in to custom decoding behavior for the attribute(s) that are selected
+ by that specification.
+
+* When working with the HCL native expression syntax, a function given in
+ the `hcl.EvalContext` during evaluation can have parameters with special
+ type constraints that opt in to custom decoding behavior for the argument
+ expression associated with that parameter in any call.
+
+The above use-cases are rather abstract, so we'll consider a motivating
+real-world example: sometimes we (language designers) need to allow users
+to specify type constraints directly in the language itself, such as in
+[Terraform's Input Variables](https://www.terraform.io/docs/configuration/variables.html).
+Terraform's `variable` blocks include an argument called `type` which takes
+a type constraint given using HCL expression building-blocks as defined by
+[the HCL `typeexpr` extension](../typeexpr/README.md).
+
+A "type constraint expression" of that sort is not an expression intended to
+be evaluated in the usual way. Instead, the physical expression is
+deconstructed using [the static analysis operations](../../spec.md#static-analysis)
+to produce a `cty.Type` as the result, rather than a `cty.Value`.
+
+The purpose of this Custom Static Decoding Extension, then, is to provide a
+bridge to allow that sort of custom decoding to be used via mechanisms that
+normally deal in `cty.Value`, such as `hcldec` and native syntax function
+calls as listed above.
+
+(Note: [`gohcl`](https://pkg.go.dev/github.com/hashicorp/hcl/v2/gohcl) has
+its own mechanism to support this use case, exploiting the fact that it is
+working directly with "normal" Go types. Decoding into a struct field of
+type `hcl.Expression` obtains the expression directly without evaluating it
+first. The Custom Static Decoding Extension is not necessary for that `gohcl`
+technique. You can also implement custom decoding by working directly with
+the lowest-level HCL API, which separates extraction of and evaluation of
+expressions into two steps.)
+
+## Custom Decoding Types
+
+This extension relies on a convention implemented in terms of
+[_Capsule Types_ in the underlying `cty` type system](https://github.com/zclconf/go-cty/blob/master/docs/types.md#capsule-types). `cty` allows a capsule type to carry arbitrary
+extension metadata values as an aid to creating higher-level abstractions like
+this extension.
+
+A custom argument decoding mode, then, is implemented by creating a new `cty`
+capsule type that implements the `ExtensionData` custom operation to return
+a decoding function when requested. For example:
+
+```go
+var keywordType cty.Type
+keywordType = cty.CapsuleWithOps("keyword", reflect.TypeOf(""), &cty.CapsuleOps{
+ ExtensionData: func(key interface{}) interface{} {
+ switch key {
+ case customdecode.CustomExpressionDecoder:
+ return customdecode.CustomExpressionDecoderFunc(
+ func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ kw := hcl.ExprAsKeyword(expr)
+ if kw == "" {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid keyword",
+ Detail: "A keyword is required",
+ Subject: expr.Range().Ptr(),
+ })
+ return cty.UnkownVal(keywordType), diags
+ }
+ return cty.CapsuleVal(keywordType, &kw)
+ },
+ )
+ default:
+ return nil
+ }
+ },
+})
+```
+
+The boilerplate here is a bit fussy, but the important part for our purposes
+is the `case customdecode.CustomExpressionDecoder:` clause, which uses
+a custom extension key type defined in this package to recognize when a
+component implementing this extension is checking to see if a target type
+has a custom decode implementation.
+
+In the above case we've defined a type that decodes expressions as static
+keywords, so a keyword like `foo` would decode as an encapsulated `"foo"`
+string, while any other sort of expression like `"baz"` or `1 + 1` would
+return an error.
+
+We could then use `keywordType` as a type constraint either for a function
+parameter or a `hcldec` attribute specification, which would require the
+argument for that function parameter or the expression for the matching
+attributes to be a static keyword, rather than an arbitrary expression.
+For example, in a `hcldec.AttrSpec`:
+
+```go
+keywordSpec := &hcldec.AttrSpec{
+ Name: "keyword",
+ Type: keywordType,
+}
+```
+
+The above would accept input like the following and would set its result to
+a `cty.Value` of `keywordType`, after decoding:
+
+```hcl
+keyword = foo
+```
+
+## The Expression and Expression Closure `cty` types
+
+Building on the above, this package also includes two capsule types that use
+the above mechanism to allow calling applications to capture expressions
+directly and thus defer analysis to a later step, after initial decoding.
+
+The `customdecode.ExpressionType` type encapsulates an `hcl.Expression` alone,
+for situations like our type constraint expression example above where it's
+the static structure of the expression we want to inspect, and thus any
+variables and functions defined in the evaluation context are irrelevant.
+
+The `customdecode.ExpressionClosureType` type encapsulates a
+`*customdecode.ExpressionClosure` value, which binds the given expression to
+the `hcl.EvalContext` it was asked to evaluate against and thus allows the
+receiver of that result to later perform normal evaluation of the expression
+with all the same variables and functions that would've been available to it
+naturally.
+
+Both of these types can be used as type constraints either for `hcldec`
+attribute specifications or for function arguments. Here's an example of
+`ExpressionClosureType` to implement a function that can evaluate
+an expression with some additional variables defined locally, which we'll
+call the `with(...)` function:
+
+```go
+var WithFunc = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "variables",
+ Type: cty.DynamicPseudoType,
+ },
+ {
+ Name: "expression",
+ Type: customdecode.ExpressionClosureType,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ varsVal := args[0]
+ exprVal := args[1]
+ if !varsVal.Type().IsObjectType() {
+ return cty.NilVal, function.NewArgErrorf(0, "must be an object defining local variables")
+ }
+ if !varsVal.IsKnown() {
+ // We can't predict our result type until the variables object
+ // is known.
+ return cty.DynamicPseudoType, nil
+ }
+ vars := varsVal.AsValueMap()
+ closure := customdecode.ExpressionClosureFromVal(exprVal)
+ result, err := evalWithLocals(vars, closure)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ return result.Type(), nil
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ varsVal := args[0]
+ exprVal := args[1]
+ vars := varsVal.AsValueMap()
+ closure := customdecode.ExpressionClosureFromVal(exprVal)
+ return evalWithLocals(vars, closure)
+ },
+})
+
+func evalWithLocals(locals map[string]cty.Value, closure *customdecode.ExpressionClosure) (cty.Value, error) {
+ childCtx := closure.EvalContext.NewChild()
+ childCtx.Variables = locals
+ val, diags := closure.Expression.Value(childCtx)
+ if diags.HasErrors() {
+ return cty.NilVal, function.NewArgErrorf(1, "couldn't evaluate expression: %s", diags.Error())
+ }
+ return val, nil
+}
+```
+
+If the above function were placed into an `hcl.EvalContext` as `with`, it
+could be used in a native syntax call to that function as follows:
+
+```hcl
+ foo = with({name = "Cory"}, "${greeting}, ${name}!")
+```
+
+The above assumes a variable in the main context called `greeting`, to which
+the `with` function adds `name` before evaluating the expression given in
+its second argument. This makes that second argument context-sensitive -- it
+would behave differently if the user wrote the same thing somewhere else -- so
+this capability should be used with care to make sure it doesn't cause confusion
+for the end-users of your language.
+
+There are some other examples of this capability to evaluate expressions in
+unusual ways in the `tryfunc` directory that is a sibling of this one.
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/customdecode.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/customdecode.go
new file mode 100644
index 00000000000..e0dda0df9e2
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/customdecode.go
@@ -0,0 +1,59 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package customdecode contains a HCL extension that allows, in certain
+// contexts, expression evaluation to be overridden by custom static analysis.
+//
+// This mechanism is only supported in certain specific contexts where
+// expressions are decoded with a specific target type in mind. For more
+// information, see the documentation on CustomExpressionDecoder.
+package customdecode
+
+import (
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type customDecoderImpl int
+
+// CustomExpressionDecoder is a value intended to be used as a cty capsule
+// type ExtensionData key for capsule types whose values are to be obtained
+// by static analysis of an expression rather than normal evaluation of that
+// expression.
+//
+// When a cooperating capsule type is asked for ExtensionData with this key,
+// it must return a non-nil CustomExpressionDecoderFunc value.
+//
+// This mechanism is not universally supported; instead, it's handled in a few
+// specific places where expressions are evaluated with the intent of producing
+// a cty.Value of a type given by the calling application.
+//
+// Specifically, this currently works for type constraints given in
+// hcldec.AttrSpec and hcldec.BlockAttrsSpec, and it works for arguments to
+// function calls in the HCL native syntax. HCL extensions implemented outside
+// of the main HCL module may also implement this; consult their own
+// documentation for details.
+const CustomExpressionDecoder = customDecoderImpl(1)
+
+// CustomExpressionDecoderFunc is the type of value that must be returned by
+// a capsule type handling the key CustomExpressionDecoder in its ExtensionData
+// implementation.
+//
+// If no error diagnostics are returned, the result value MUST be of the
+// capsule type that the decoder function was derived from. If the returned
+// error diagnostics prevent producing a value at all, return cty.NilVal.
+type CustomExpressionDecoderFunc func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
+
+// CustomExpressionDecoderForType takes any cty type and returns its
+// custom expression decoder implementation if it has one. If it is not a
+// capsule type or it does not implement a custom expression decoder, this
+// function returns nil.
+func CustomExpressionDecoderForType(ty cty.Type) CustomExpressionDecoderFunc {
+ if !ty.IsCapsuleType() {
+ return nil
+ }
+ if fn, ok := ty.CapsuleExtensionData(CustomExpressionDecoder).(CustomExpressionDecoderFunc); ok {
+ return fn
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/expression_type.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/expression_type.go
new file mode 100644
index 00000000000..2477f219074
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ext/customdecode/expression_type.go
@@ -0,0 +1,149 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package customdecode
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// ExpressionType is a cty capsule type that carries hcl.Expression values.
+//
+// This type implements custom decoding in the most general way possible: it
+// just captures whatever expression is given to it, with no further processing
+// whatsoever. It could therefore be useful in situations where an application
+// must defer processing of the expression content until a later step.
+//
+// ExpressionType only captures the expression, not the evaluation context it
+// was destined to be evaluated in. That means this type can be fine for
+// situations where the recipient of the value only intends to do static
+// analysis, but ExpressionClosureType is more appropriate in situations where
+// the recipient will eventually evaluate the given expression.
+var ExpressionType cty.Type
+
+// ExpressionVal returns a new cty value of type ExpressionType, wrapping the
+// given expression.
+func ExpressionVal(expr hcl.Expression) cty.Value {
+ return cty.CapsuleVal(ExpressionType, &expr)
+}
+
+// ExpressionFromVal returns the expression encapsulated in the given value, or
+// panics if the value is not a known value of ExpressionType.
+func ExpressionFromVal(v cty.Value) hcl.Expression {
+ if !v.Type().Equals(ExpressionType) {
+ panic("value is not of ExpressionType")
+ }
+ ptr := v.EncapsulatedValue().(*hcl.Expression)
+ return *ptr
+}
+
+// ExpressionClosureType is a cty capsule type that carries hcl.Expression
+// values along with their original evaluation contexts.
+//
+// This is similar to ExpressionType except that during custom decoding it
+// also captures the hcl.EvalContext that was provided, allowing callers to
+// evaluate the expression later in the same context where it would originally
+// have been evaluated, or a context derived from that one.
+var ExpressionClosureType cty.Type
+
+// ExpressionClosure is the type encapsulated in ExpressionClosureType
+type ExpressionClosure struct {
+ Expression hcl.Expression
+ EvalContext *hcl.EvalContext
+}
+
+// ExpressionClosureVal returns a new cty value of type ExpressionClosureType,
+// wrapping the given expression closure.
+func ExpressionClosureVal(closure *ExpressionClosure) cty.Value {
+ return cty.CapsuleVal(ExpressionClosureType, closure)
+}
+
+// Value evaluates the closure's expression using the closure's EvalContext,
+// returning the result.
+func (c *ExpressionClosure) Value() (cty.Value, hcl.Diagnostics) {
+ return c.Expression.Value(c.EvalContext)
+}
+
+// ExpressionClosureFromVal returns the expression closure encapsulated in the
+// given value, or panics if the value is not a known value of
+// ExpressionClosureType.
+//
+// The caller MUST NOT modify the returned closure or the EvalContext inside
+// it. To derive a new EvalContext, either create a child context or make
+// a copy.
+func ExpressionClosureFromVal(v cty.Value) *ExpressionClosure {
+ if !v.Type().Equals(ExpressionClosureType) {
+ panic("value is not of ExpressionClosureType")
+ }
+ return v.EncapsulatedValue().(*ExpressionClosure)
+}
+
+func init() {
+ // Getting hold of a reflect.Type for hcl.Expression is a bit tricky because
+ // it's an interface type, but we can do it with some indirection.
+ goExpressionType := reflect.TypeOf((*hcl.Expression)(nil)).Elem()
+
+ ExpressionType = cty.CapsuleWithOps("expression", goExpressionType, &cty.CapsuleOps{
+ ExtensionData: func(key interface{}) interface{} {
+ switch key {
+ case CustomExpressionDecoder:
+ return CustomExpressionDecoderFunc(
+ func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ return ExpressionVal(expr), nil
+ },
+ )
+ default:
+ return nil
+ }
+ },
+ TypeGoString: func(_ reflect.Type) string {
+ return "customdecode.ExpressionType"
+ },
+ GoString: func(raw interface{}) string {
+ exprPtr := raw.(*hcl.Expression)
+ return fmt.Sprintf("customdecode.ExpressionVal(%#v)", *exprPtr)
+ },
+ RawEquals: func(a, b interface{}) bool {
+ aPtr := a.(*hcl.Expression)
+ bPtr := b.(*hcl.Expression)
+ return reflect.DeepEqual(*aPtr, *bPtr)
+ },
+ })
+ ExpressionClosureType = cty.CapsuleWithOps("expression closure", reflect.TypeOf(ExpressionClosure{}), &cty.CapsuleOps{
+ ExtensionData: func(key interface{}) interface{} {
+ switch key {
+ case CustomExpressionDecoder:
+ return CustomExpressionDecoderFunc(
+ func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ return ExpressionClosureVal(&ExpressionClosure{
+ Expression: expr,
+ EvalContext: ctx,
+ }), nil
+ },
+ )
+ default:
+ return nil
+ }
+ },
+ TypeGoString: func(_ reflect.Type) string {
+ return "customdecode.ExpressionClosureType"
+ },
+ GoString: func(raw interface{}) string {
+ closure := raw.(*ExpressionClosure)
+ return fmt.Sprintf("customdecode.ExpressionClosureVal(%#v)", closure)
+ },
+ RawEquals: func(a, b interface{}) bool {
+ closureA := a.(*ExpressionClosure)
+ closureB := b.(*ExpressionClosure)
+ // The expression itself compares by deep equality, but EvalContexts
+ // conventionally compare by pointer identity, so we'll comply
+ // with both conventions here by testing them separately.
+ return closureA.EvalContext == closureB.EvalContext &&
+ reflect.DeepEqual(closureA.Expression, closureB.Expression)
+ },
+ })
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/diagnostics.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/diagnostics.go
new file mode 100644
index 00000000000..43689d74093
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/diagnostics.go
@@ -0,0 +1,26 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+// setDiagEvalContext is an internal helper that will impose a particular
+// EvalContext on a set of diagnostics in-place, for any diagnostic that
+// does not already have an EvalContext set.
+//
+// We generally expect diagnostics to be immutable, but this is safe to use
+// on any Diagnostics where none of the contained Diagnostic objects have yet
+// been seen by a caller. Its purpose is to apply additional context to a
+// set of diagnostics produced by a "deeper" component as the stack unwinds
+// during expression evaluation.
+func setDiagEvalContext(diags hcl.Diagnostics, expr hcl.Expression, ctx *hcl.EvalContext) {
+ for _, diag := range diags {
+ if diag.Expression == nil {
+ diag.Expression = expr
+ diag.EvalContext = ctx
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/didyoumean.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/didyoumean.go
new file mode 100644
index 00000000000..5b0e4681020
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/didyoumean.go
@@ -0,0 +1,27 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/agext/levenshtein"
+)
+
+// nameSuggestion tries to find a name from the given slice of suggested names
+// that is close to the given name and returns it if found. If no suggestion
+// is close enough, returns the empty string.
+//
+// The suggestions are tried in order, so earlier suggestions take precedence
+// if the given string is similar to two or more suggestions.
+//
+// This function is intended to be used with a relatively-small number of
+// suggestions. It's not optimized for hundreds or thousands of them.
+func nameSuggestion(given string, suggestions []string) string {
+ for _, suggestion := range suggestions {
+ dist := levenshtein.Distance(given, suggestion, nil)
+ if dist < 3 { // threshold determined experimentally
+ return suggestion
+ }
+ }
+ return ""
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/doc.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/doc.go
new file mode 100644
index 00000000000..defe3dbb785
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/doc.go
@@ -0,0 +1,10 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package hclsyntax contains the parser, AST, etc for HCL's native language,
+// as opposed to the JSON variant.
+//
+// In normal use applications should rarely depend on this package directly,
+// instead preferring the higher-level interface of the main hcl package and
+// its companion package hclparse.
+package hclsyntax
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go
new file mode 100644
index 00000000000..c5a448863c6
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go
@@ -0,0 +1,2077 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+ "sync"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/ext/customdecode"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// Expression is the abstract type for nodes that behave as HCL expressions.
+type Expression interface {
+ Node
+
+ // The hcl.Expression methods are duplicated here, rather than simply
+ // embedded, because both Node and hcl.Expression have a Range method
+ // and so they conflict.
+
+ Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
+ Variables() []hcl.Traversal
+ StartRange() hcl.Range
+}
+
+// Assert that Expression implements hcl.Expression
+var _ hcl.Expression = Expression(nil)
+
+// ParenthesesExpr represents an expression written in grouping
+// parentheses.
+//
+// The parser takes care of the precedence effect of the parentheses, so the
+// only purpose of this separate expression node is to capture the source range
+// of the parentheses themselves, rather than the source range of the
+// expression within. All of the other expression operations just pass through
+// to the underlying expression.
+type ParenthesesExpr struct {
+ Expression
+ SrcRange hcl.Range
+}
+
+var _ hcl.Expression = (*ParenthesesExpr)(nil)
+
+func (e *ParenthesesExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *ParenthesesExpr) walkChildNodes(w internalWalkFunc) {
+ // We override the walkChildNodes from the embedded Expression to
+ // ensure that both the parentheses _and_ the content are visible
+ // in a walk.
+ w(e.Expression)
+}
+
+// LiteralValueExpr is an expression that just always returns a given value.
+type LiteralValueExpr struct {
+ Val cty.Value
+ SrcRange hcl.Range
+}
+
+func (e *LiteralValueExpr) walkChildNodes(w internalWalkFunc) {
+ // Literal values have no child nodes
+}
+
+func (e *LiteralValueExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ return e.Val, nil
+}
+
+func (e *LiteralValueExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *LiteralValueExpr) StartRange() hcl.Range {
+ return e.SrcRange
+}
+
+// Implementation for hcl.AbsTraversalForExpr.
+func (e *LiteralValueExpr) AsTraversal() hcl.Traversal {
+ // This one's a little weird: the contract for AsTraversal is to interpret
+ // an expression as if it were traversal syntax, and traversal syntax
+ // doesn't have the special keywords "null", "true", and "false" so these
+ // are expected to be treated like variables in that case.
+ // Since our parser already turned them into LiteralValueExpr by the time
+ // we get here, we need to undo this and infer the name that would've
+ // originally led to our value.
+ // We don't do anything for any other values, since they don't overlap
+ // with traversal roots.
+
+ if e.Val.IsNull() {
+ // In practice the parser only generates null values of the dynamic
+ // pseudo-type for literals, so we can safely assume that any null
+ // was orignally the keyword "null".
+ return hcl.Traversal{
+ hcl.TraverseRoot{
+ Name: "null",
+ SrcRange: e.SrcRange,
+ },
+ }
+ }
+
+ switch e.Val {
+ case cty.True:
+ return hcl.Traversal{
+ hcl.TraverseRoot{
+ Name: "true",
+ SrcRange: e.SrcRange,
+ },
+ }
+ case cty.False:
+ return hcl.Traversal{
+ hcl.TraverseRoot{
+ Name: "false",
+ SrcRange: e.SrcRange,
+ },
+ }
+ default:
+ // No traversal is possible for any other value.
+ return nil
+ }
+}
+
+// ScopeTraversalExpr is an Expression that retrieves a value from the scope
+// using a traversal.
+type ScopeTraversalExpr struct {
+ Traversal hcl.Traversal
+ SrcRange hcl.Range
+}
+
+func (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) {
+ // Scope traversals have no child nodes
+}
+
+func (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ val, diags := e.Traversal.TraverseAbs(ctx)
+ setDiagEvalContext(diags, e, ctx)
+ return val, diags
+}
+
+func (e *ScopeTraversalExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *ScopeTraversalExpr) StartRange() hcl.Range {
+ return e.SrcRange
+}
+
+// Implementation for hcl.AbsTraversalForExpr.
+func (e *ScopeTraversalExpr) AsTraversal() hcl.Traversal {
+ return e.Traversal
+}
+
+// RelativeTraversalExpr is an Expression that retrieves a value from another
+// value using a _relative_ traversal.
+type RelativeTraversalExpr struct {
+ Source Expression
+ Traversal hcl.Traversal
+ SrcRange hcl.Range
+}
+
+func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Source)
+}
+
+func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ src, diags := e.Source.Value(ctx)
+ ret, travDiags := e.Traversal.TraverseRel(src)
+ setDiagEvalContext(travDiags, e, ctx)
+ diags = append(diags, travDiags...)
+ return ret, diags
+}
+
+func (e *RelativeTraversalExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *RelativeTraversalExpr) StartRange() hcl.Range {
+ return e.SrcRange
+}
+
+// Implementation for hcl.AbsTraversalForExpr.
+func (e *RelativeTraversalExpr) AsTraversal() hcl.Traversal {
+ // We can produce a traversal only if our source can.
+ st, diags := hcl.AbsTraversalForExpr(e.Source)
+ if diags.HasErrors() {
+ return nil
+ }
+
+ ret := make(hcl.Traversal, len(st)+len(e.Traversal))
+ copy(ret, st)
+ copy(ret[len(st):], e.Traversal)
+ return ret
+}
+
+// FunctionCallExpr is an Expression that calls a function from the EvalContext
+// and returns its result.
+type FunctionCallExpr struct {
+ Name string
+ Args []Expression
+
+ // If true, the final argument should be a tuple, list or set which will
+ // expand to be one argument per element.
+ ExpandFinal bool
+
+ NameRange hcl.Range
+ OpenParenRange hcl.Range
+ CloseParenRange hcl.Range
+}
+
+func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) {
+ for _, arg := range e.Args {
+ w(arg)
+ }
+}
+
+func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ var f function.Function
+ exists := false
+ hasNonNilMap := false
+ thisCtx := ctx
+ for thisCtx != nil {
+ if thisCtx.Functions == nil {
+ thisCtx = thisCtx.Parent()
+ continue
+ }
+ hasNonNilMap = true
+ f, exists = thisCtx.Functions[e.Name]
+ if exists {
+ break
+ }
+ thisCtx = thisCtx.Parent()
+ }
+
+ if !exists {
+ if !hasNonNilMap {
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Function calls not allowed",
+ Detail: "Functions may not be called here.",
+ Subject: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ },
+ }
+ }
+
+ extraUnknown := &functionCallUnknown{
+ name: e.Name,
+ }
+
+ // For historical reasons, we represent namespaced function names
+ // as strings with :: separating the names. If this was an attempt
+ // to call a namespaced function then we'll try to distinguish
+ // between an invalid namespace or an invalid name within a valid
+ // namespace in order to give the user better feedback about what
+ // is wrong.
+ //
+ // The parser guarantees that a function name will always
+ // be a series of valid identifiers separated by "::" with no
+ // other content, so we can be relatively unforgiving in our processing
+ // here.
+ if sepIdx := strings.LastIndex(e.Name, "::"); sepIdx != -1 {
+ namespace := e.Name[:sepIdx+2]
+ name := e.Name[sepIdx+2:]
+
+ avail := make([]string, 0, len(ctx.Functions))
+ for availName := range ctx.Functions {
+ if strings.HasPrefix(availName, namespace) {
+ avail = append(avail, availName)
+ }
+ }
+
+ extraUnknown.name = name
+ extraUnknown.namespace = namespace
+
+ if len(avail) == 0 {
+ // TODO: Maybe use nameSuggestion for the other available
+ // namespaces? But that'd require us to go scan the function
+ // table again, so we'll wait to see if it's really warranted.
+ // For now, we're assuming people are more likely to misremember
+ // the function names than the namespaces, because in many
+ // applications there will be relatively few namespaces compared
+ // to the number of distinct functions.
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Call to unknown function",
+ Detail: fmt.Sprintf("There are no functions in namespace %q.", namespace),
+ Subject: &e.NameRange,
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: extraUnknown,
+ },
+ }
+ } else {
+ suggestion := nameSuggestion(name, avail)
+ if suggestion != "" {
+ suggestion = fmt.Sprintf(" Did you mean %s%s?", namespace, suggestion)
+ }
+
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Call to unknown function",
+ Detail: fmt.Sprintf("There is no function named %q in namespace %s.%s", name, namespace, suggestion),
+ Subject: &e.NameRange,
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: extraUnknown,
+ },
+ }
+ }
+ }
+
+ avail := make([]string, 0, len(ctx.Functions))
+ for name := range ctx.Functions {
+ avail = append(avail, name)
+ }
+ suggestion := nameSuggestion(e.Name, avail)
+ if suggestion != "" {
+ suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
+ }
+
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Call to unknown function",
+ Detail: fmt.Sprintf("There is no function named %q.%s", e.Name, suggestion),
+ Subject: &e.NameRange,
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: extraUnknown,
+ },
+ }
+ }
+
+ diagExtra := functionCallDiagExtra{
+ calledFunctionName: e.Name,
+ }
+
+ params := f.Params()
+ varParam := f.VarParam()
+
+ args := e.Args
+ if e.ExpandFinal {
+ if len(args) < 1 {
+ // should never happen if the parser is behaving
+ panic("ExpandFinal set on function call with no arguments")
+ }
+ expandExpr := args[len(args)-1]
+ expandVal, expandDiags := expandExpr.Value(ctx)
+ diags = append(diags, expandDiags...)
+ if expandDiags.HasErrors() {
+ return cty.DynamicVal, diags
+ }
+
+ switch {
+ case expandVal.Type().Equals(cty.DynamicPseudoType):
+ if expandVal.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid expanding argument value",
+ Detail: "The expanding argument (indicated by ...) must not be null.",
+ Subject: expandExpr.Range().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: expandExpr,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ return cty.DynamicVal, diags
+ }
+ return cty.DynamicVal, diags
+ case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType():
+ if expandVal.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid expanding argument value",
+ Detail: "The expanding argument (indicated by ...) must not be null.",
+ Subject: expandExpr.Range().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: expandExpr,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ return cty.DynamicVal, diags
+ }
+ if !expandVal.IsKnown() {
+ return cty.DynamicVal, diags
+ }
+
+ // When expanding arguments from a collection, we must first unmark
+ // the collection itself, and apply any marks directly to the
+ // elements. This ensures that marks propagate correctly.
+ expandVal, marks := expandVal.Unmark()
+ newArgs := make([]Expression, 0, (len(args)-1)+expandVal.LengthInt())
+ newArgs = append(newArgs, args[:len(args)-1]...)
+ it := expandVal.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ newArgs = append(newArgs, &LiteralValueExpr{
+ Val: val.WithMarks(marks),
+ SrcRange: expandExpr.Range(),
+ })
+ }
+ args = newArgs
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid expanding argument value",
+ Detail: "The expanding argument (indicated by ...) must be of a tuple, list, or set type.",
+ Subject: expandExpr.Range().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: expandExpr,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ return cty.DynamicVal, diags
+ }
+ }
+
+ if len(args) < len(params) {
+ missing := params[len(args)]
+ qual := ""
+ if varParam != nil {
+ qual = " at least"
+ }
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Not enough function arguments",
+ Detail: fmt.Sprintf(
+ "Function %q expects%s %d argument(s). Missing value for %q.",
+ e.Name, qual, len(params), missing.Name,
+ ),
+ Subject: &e.CloseParenRange,
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ },
+ }
+ }
+
+ if varParam == nil && len(args) > len(params) {
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Too many function arguments",
+ Detail: fmt.Sprintf(
+ "Function %q expects only %d argument(s).",
+ e.Name, len(params),
+ ),
+ Subject: args[len(params)].StartRange().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ },
+ }
+ }
+
+ argVals := make([]cty.Value, len(args))
+
+ for i, argExpr := range args {
+ var param *function.Parameter
+ if i < len(params) {
+ param = ¶ms[i]
+ } else {
+ param = varParam
+ }
+
+ var val cty.Value
+ if decodeFn := customdecode.CustomExpressionDecoderForType(param.Type); decodeFn != nil {
+ var argDiags hcl.Diagnostics
+ val, argDiags = decodeFn(argExpr, ctx)
+ diags = append(diags, argDiags...)
+ if val == cty.NilVal {
+ val = cty.UnknownVal(param.Type)
+ }
+ } else {
+ var argDiags hcl.Diagnostics
+ val, argDiags = argExpr.Value(ctx)
+ if len(argDiags) > 0 {
+ diags = append(diags, argDiags...)
+ }
+
+ // Try to convert our value to the parameter type
+ var err error
+ val, err = convert.Convert(val, param.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid function argument",
+ Detail: fmt.Sprintf(
+ "Invalid value for %q parameter: %s.",
+ param.Name, err,
+ ),
+ Subject: argExpr.StartRange().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: argExpr,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ }
+ }
+
+ argVals[i] = val
+ }
+
+ if diags.HasErrors() {
+ // Don't try to execute the function if we already have errors with
+ // the arguments, because the result will probably be a confusing
+ // error message.
+ return cty.DynamicVal, diags
+ }
+
+ resultVal, err := f.Call(argVals)
+ if err != nil {
+ // For errors in the underlying call itself we also return the raw
+ // call error via an extra method on our "diagnostic extra" value.
+ diagExtra.functionCallError = err
+
+ switch terr := err.(type) {
+ case function.ArgError:
+ i := terr.Index
+ var param *function.Parameter
+ if i < len(params) {
+ param = ¶ms[i]
+ } else {
+ param = varParam
+ }
+
+ if param == nil || i > len(args)-1 {
+ // Getting here means that the function we called has a bug:
+ // it returned an arg error that refers to an argument index
+ // that wasn't present in the call. For that situation
+ // we'll degrade to a less specific error just to give
+ // some sort of answer, but best to still fix the buggy
+ // function so that it only returns argument indices that
+ // are in range.
+ switch {
+ case param != nil:
+ // In this case we'll assume that the function was trying
+ // to talk about a final variadic parameter but the caller
+ // didn't actually provide any arguments for it. That means
+ // we can at least still name the parameter in the
+ // error message, but our source range will be the call
+ // as a whole because we don't have an argument expression
+ // to highlight specifically.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid function argument",
+ Detail: fmt.Sprintf(
+ "Invalid value for %q parameter: %s.",
+ param.Name, err,
+ ),
+ Subject: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ default:
+ // This is the most degenerate case of all, where the
+ // index is out of range even for the declared parameters,
+ // and so we can't tell which parameter the function is
+ // trying to report an error for. Just a generic error
+ // report in that case.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Error in function call",
+ Detail: fmt.Sprintf(
+ "Call to function %q failed: %s.",
+ e.Name, err,
+ ),
+ Subject: e.StartRange().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ }
+ } else {
+ argExpr := args[i]
+
+ // TODO: we should also unpick a PathError here and show the
+ // path to the deep value where the error was detected.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid function argument",
+ Detail: fmt.Sprintf(
+ "Invalid value for %q parameter: %s.",
+ param.Name, err,
+ ),
+ Subject: argExpr.StartRange().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: argExpr,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ }
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Error in function call",
+ Detail: fmt.Sprintf(
+ "Call to function %q failed: %s.",
+ e.Name, err,
+ ),
+ Subject: e.StartRange().Ptr(),
+ Context: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ Extra: &diagExtra,
+ })
+ }
+
+ return cty.DynamicVal, diags
+ }
+
+ return resultVal, diags
+}
+
+func (e *FunctionCallExpr) Range() hcl.Range {
+ return hcl.RangeBetween(e.NameRange, e.CloseParenRange)
+}
+
+func (e *FunctionCallExpr) StartRange() hcl.Range {
+ return hcl.RangeBetween(e.NameRange, e.OpenParenRange)
+}
+
+// Implementation for hcl.ExprCall.
+func (e *FunctionCallExpr) ExprCall() *hcl.StaticCall {
+ ret := &hcl.StaticCall{
+ Name: e.Name,
+ NameRange: e.NameRange,
+ Arguments: make([]hcl.Expression, len(e.Args)),
+ ArgsRange: hcl.RangeBetween(e.OpenParenRange, e.CloseParenRange),
+ }
+ // Need to convert our own Expression objects into hcl.Expression.
+ for i, arg := range e.Args {
+ ret.Arguments[i] = arg
+ }
+ return ret
+}
+
+// FunctionCallDiagExtra is an interface implemented by the value in the "Extra"
+// field of some diagnostics returned by FunctionCallExpr.Value, giving
+// cooperating callers access to some machine-readable information about the
+// call that a diagnostic relates to.
+type FunctionCallDiagExtra interface {
+ // CalledFunctionName returns the name of the function being called at
+ // the time the diagnostic was generated, if any. Returns an empty string
+ // if there is no known called function.
+ CalledFunctionName() string
+
+ // FunctionCallError returns the error value returned by the implementation
+ // of the function being called, if any. Returns nil if the diagnostic was
+ // not returned in response to a call error.
+ //
+ // Some errors related to calling functions are generated by HCL itself
+ // rather than by the underlying function, in which case this method
+ // will return nil.
+ FunctionCallError() error
+}
+
+type functionCallDiagExtra struct {
+ calledFunctionName string
+ functionCallError error
+}
+
+func (e *functionCallDiagExtra) CalledFunctionName() string {
+ return e.calledFunctionName
+}
+
+func (e *functionCallDiagExtra) FunctionCallError() error {
+ return e.functionCallError
+}
+
+// FunctionCallUnknownDiagExtra is an interface implemented by a value in the Extra
+// field of some diagnostics to indicate when the error was caused by a call to
+// an unknown function.
+type FunctionCallUnknownDiagExtra interface {
+ CalledFunctionName() string
+ CalledFunctionNamespace() string
+}
+
+type functionCallUnknown struct {
+ name string
+ namespace string
+}
+
+func (e *functionCallUnknown) CalledFunctionName() string {
+ return e.name
+}
+
+func (e *functionCallUnknown) CalledFunctionNamespace() string {
+ return e.namespace
+}
+
+type ConditionalExpr struct {
+ Condition Expression
+ TrueResult Expression
+ FalseResult Expression
+
+ SrcRange hcl.Range
+}
+
+func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Condition)
+ w(e.TrueResult)
+ w(e.FalseResult)
+}
+
+func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ trueResult, trueDiags := e.TrueResult.Value(ctx)
+ falseResult, falseDiags := e.FalseResult.Value(ctx)
+ var diags hcl.Diagnostics
+
+ resultType := cty.DynamicPseudoType
+ convs := make([]convert.Conversion, 2)
+
+ switch {
+ // If either case is a dynamic null value (which would result from a
+ // literal null in the config), we know that it can convert to the expected
+ // type of the opposite case, and we don't need to speculatively reduce the
+ // final result type to DynamicPseudoType.
+
+ // If we know that either Type is a DynamicPseudoType, we can be certain
+ // that the other value can convert since it's a pass-through, and we don't
+ // need to unify the types. If the final evaluation results in the dynamic
+ // value being returned, there's no conversion we can do, so we return the
+ // value directly.
+ case trueResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
+ resultType = falseResult.Type()
+ convs[0] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
+ case falseResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
+ resultType = trueResult.Type()
+ convs[1] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
+ case trueResult.Type() == cty.DynamicPseudoType, falseResult.Type() == cty.DynamicPseudoType:
+ // the final resultType type is still unknown
+ // we don't need to get the conversion, because both are a noop.
+
+ default:
+ // Try to find a type that both results can be converted to.
+ resultType, convs = convert.UnifyUnsafe([]cty.Type{trueResult.Type(), falseResult.Type()})
+ }
+
+ if resultType == cty.NilType {
+ return cty.DynamicVal, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Inconsistent conditional result types",
+ Detail: fmt.Sprintf(
+ "The true and false result expressions must have consistent types. %s.",
+ describeConditionalTypeMismatch(trueResult.Type(), falseResult.Type()),
+ ),
+ Subject: hcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(),
+ Context: &e.SrcRange,
+ Expression: e,
+ EvalContext: ctx,
+ },
+ }
+ }
+
+ condResult, condDiags := e.Condition.Value(ctx)
+ diags = append(diags, condDiags...)
+ if condResult.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Null condition",
+ Detail: "The condition value is null. Conditions must either be true or false.",
+ Subject: e.Condition.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.Condition,
+ EvalContext: ctx,
+ })
+ return cty.UnknownVal(resultType), diags
+ }
+
+ // Now that we have all three values, collect all the marks for the result.
+ // Since it's possible that a condition value could be unknown, and the
+ // consumer needs to deal with any marks from either branch anyway, we must
+ // always combine them for consistent results.
+ condResult, condResultMarks := condResult.Unmark()
+ trueResult, trueResultMarks := trueResult.Unmark()
+ falseResult, falseResultMarks := falseResult.Unmark()
+ var resMarks []cty.ValueMarks
+ resMarks = append(resMarks, condResultMarks, trueResultMarks, falseResultMarks)
+
+ if !condResult.IsKnown() {
+ trueRange := trueResult.Range()
+ falseRange := falseResult.Range()
+
+ // if both branches are known to be null, then the result must still be null
+ if trueResult.IsNull() && falseResult.IsNull() {
+ return cty.NullVal(resultType).WithMarks(resMarks...), diags
+ }
+
+ // We might be able to offer a refined range for the result based on
+ // the two possible outcomes.
+ if trueResult.Type() == cty.Number && falseResult.Type() == cty.Number {
+ ref := cty.UnknownVal(cty.Number).Refine()
+ if trueRange.DefinitelyNotNull() && falseRange.DefinitelyNotNull() {
+ ref = ref.NotNull()
+ }
+
+ falseLo, falseLoInc := falseRange.NumberLowerBound()
+ falseHi, falseHiInc := falseRange.NumberUpperBound()
+ trueLo, trueLoInc := trueRange.NumberLowerBound()
+ trueHi, trueHiInc := trueRange.NumberUpperBound()
+
+ if falseLo.IsKnown() && trueLo.IsKnown() {
+ lo, loInc := falseLo, falseLoInc
+ switch {
+ case trueLo.LessThan(falseLo).True():
+ lo, loInc = trueLo, trueLoInc
+ case trueLo.Equals(falseLo).True():
+ loInc = trueLoInc || falseLoInc
+ }
+
+ ref = ref.NumberRangeLowerBound(lo, loInc)
+ }
+
+ if falseHi.IsKnown() && trueHi.IsKnown() {
+ hi, hiInc := falseHi, falseHiInc
+ switch {
+ case trueHi.GreaterThan(falseHi).True():
+ hi, hiInc = trueHi, trueHiInc
+ case trueHi.Equals(falseHi).True():
+ hiInc = trueHiInc || falseHiInc
+ }
+ ref = ref.NumberRangeUpperBound(hi, hiInc)
+ }
+
+ return ref.NewValue().WithMarks(resMarks...), diags
+ }
+
+ if trueResult.Type().IsCollectionType() && falseResult.Type().IsCollectionType() {
+ if trueResult.Type().Equals(falseResult.Type()) {
+ ref := cty.UnknownVal(resultType).Refine()
+ if trueRange.DefinitelyNotNull() && falseRange.DefinitelyNotNull() {
+ ref = ref.NotNull()
+ }
+
+ falseLo := falseRange.LengthLowerBound()
+ falseHi := falseRange.LengthUpperBound()
+ trueLo := trueRange.LengthLowerBound()
+ trueHi := trueRange.LengthUpperBound()
+
+ lo := falseLo
+ if trueLo < falseLo {
+ lo = trueLo
+ }
+
+ hi := falseHi
+ if trueHi > falseHi {
+ hi = trueHi
+ }
+
+ ref = ref.CollectionLengthLowerBound(lo).CollectionLengthUpperBound(hi)
+ return ref.NewValue().WithMarks(resMarks...), diags
+ }
+ }
+
+ ret := cty.UnknownVal(resultType)
+ if trueRange.DefinitelyNotNull() && falseRange.DefinitelyNotNull() {
+ ret = ret.RefineNotNull()
+ }
+ return ret.WithMarks(resMarks...), diags
+ }
+
+ condResult, err := convert.Convert(condResult, cty.Bool)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Incorrect condition type",
+ Detail: "The condition expression must be of type bool.",
+ Subject: e.Condition.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.Condition,
+ EvalContext: ctx,
+ })
+ return cty.UnknownVal(resultType), diags
+ }
+
+ if condResult.True() {
+ diags = append(diags, trueDiags...)
+ if convs[0] != nil {
+ var err error
+ trueResult, err = convs[0](trueResult)
+ if err != nil {
+ // Unsafe conversion failed with the concrete result value
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Inconsistent conditional result types",
+ Detail: fmt.Sprintf(
+ "The true result value has the wrong type: %s.",
+ err.Error(),
+ ),
+ Subject: e.TrueResult.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.TrueResult,
+ EvalContext: ctx,
+ })
+ trueResult = cty.UnknownVal(resultType)
+ }
+ }
+ return trueResult.WithMarks(resMarks...), diags
+ } else {
+ diags = append(diags, falseDiags...)
+ if convs[1] != nil {
+ var err error
+ falseResult, err = convs[1](falseResult)
+ if err != nil {
+ // Unsafe conversion failed with the concrete result value
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Inconsistent conditional result types",
+ Detail: fmt.Sprintf(
+ "The false result value has the wrong type: %s.",
+ err.Error(),
+ ),
+ Subject: e.FalseResult.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.FalseResult,
+ EvalContext: ctx,
+ })
+ falseResult = cty.UnknownVal(resultType)
+ }
+ }
+ return falseResult.WithMarks(resMarks...), diags
+ }
+}
+
+// describeConditionalTypeMismatch makes a best effort to describe the
+// difference between types in the true and false arms of a conditional
+// expression in a way that would be useful to someone trying to understand
+// why their conditional expression isn't valid.
+//
+// NOTE: This function is only designed to deal with situations
+// where trueTy and falseTy are different. Calling it with two equal
+// types will produce a nonsense result. This function also only really
+// deals with situations that type unification can't resolve, so we should
+// call this function only after trying type unification first.
+func describeConditionalTypeMismatch(trueTy, falseTy cty.Type) string {
+ // The main tricky cases here are when both trueTy and falseTy are
+ // of the same structural type kind, such as both being object types
+ // or both being tuple types. In that case the "FriendlyName" method
+ // returns only "object" or "tuple" and so we need to do some more
+ // work to describe what's different inside them.
+
+ switch {
+ case trueTy.IsObjectType() && falseTy.IsObjectType():
+ // We'll first gather up the attribute names and sort them. In the
+ // event that there are multiple attributes that disagree across
+ // the two types, we'll prefer to report the one that sorts lexically
+ // least just so that our error message is consistent between
+ // evaluations.
+ var trueAttrs, falseAttrs []string
+ for name := range trueTy.AttributeTypes() {
+ trueAttrs = append(trueAttrs, name)
+ }
+ sort.Strings(trueAttrs)
+ for name := range falseTy.AttributeTypes() {
+ falseAttrs = append(falseAttrs, name)
+ }
+ sort.Strings(falseAttrs)
+
+ for _, name := range trueAttrs {
+ if !falseTy.HasAttribute(name) {
+ return fmt.Sprintf("The 'true' value includes object attribute %q, which is absent in the 'false' value", name)
+ }
+ trueAty := trueTy.AttributeType(name)
+ falseAty := falseTy.AttributeType(name)
+ if !trueAty.Equals(falseAty) {
+ // For deeply-nested differences this will likely get very
+ // clunky quickly by nesting these messages inside one another,
+ // but we'll accept that for now in the interests of producing
+ // _some_ useful feedback, even if it isn't as concise as
+ // we'd prefer it to be. Deeply-nested structures in
+ // conditionals are thankfully not super common.
+ return fmt.Sprintf(
+ "Type mismatch for object attribute %q: %s",
+ name, describeConditionalTypeMismatch(trueAty, falseAty),
+ )
+ }
+ }
+ for _, name := range falseAttrs {
+ if !trueTy.HasAttribute(name) {
+ return fmt.Sprintf("The 'false' value includes object attribute %q, which is absent in the 'true' value", name)
+ }
+ // NOTE: We don't need to check the attribute types again, because
+ // any attribute that both types have in common would already have
+ // been checked in the previous loop.
+ }
+ case trueTy.IsTupleType() && falseTy.IsTupleType():
+ trueEtys := trueTy.TupleElementTypes()
+ falseEtys := falseTy.TupleElementTypes()
+
+ if trueCount, falseCount := len(trueEtys), len(falseEtys); trueCount != falseCount {
+ return fmt.Sprintf("The 'true' tuple has length %d, but the 'false' tuple has length %d", trueCount, falseCount)
+ }
+
+ // NOTE: Thanks to the condition above, we know that both tuples are
+ // of the same length and so they must have some differing types
+ // instead.
+ for i := range trueEtys {
+ trueEty := trueEtys[i]
+ falseEty := falseEtys[i]
+
+ if !trueEty.Equals(falseEty) {
+ // For deeply-nested differences this will likely get very
+ // clunky quickly by nesting these messages inside one another,
+ // but we'll accept that for now in the interests of producing
+ // _some_ useful feedback, even if it isn't as concise as
+ // we'd prefer it to be. Deeply-nested structures in
+ // conditionals are thankfully not super common.
+ return fmt.Sprintf(
+ "Type mismatch for tuple element %d: %s",
+ i, describeConditionalTypeMismatch(trueEty, falseEty),
+ )
+ }
+ }
+ case trueTy.IsCollectionType() && falseTy.IsCollectionType():
+ // For this case we're specifically interested in the situation where:
+ // - both collections are of the same kind, AND
+ // - the element types of both are either object or tuple types.
+ // This is just to avoid writing a useless statement like
+ // "The 'true' value is list of object, but the 'false' value is list of object".
+ // This still doesn't account for more awkward cases like collections
+ // of collections of structural types, but we won't let perfect be
+ // the enemy of the good.
+ trueEty := trueTy.ElementType()
+ falseEty := falseTy.ElementType()
+ if (trueTy.IsListType() && falseTy.IsListType()) || (trueTy.IsMapType() && falseTy.IsMapType()) || (trueTy.IsSetType() && falseTy.IsSetType()) {
+ if (trueEty.IsObjectType() && falseEty.IsObjectType()) || (trueEty.IsTupleType() && falseEty.IsTupleType()) {
+ noun := "collection"
+ switch { // NOTE: We now know that trueTy and falseTy have the same collection kind
+ case trueTy.IsListType():
+ noun = "list"
+ case trueTy.IsSetType():
+ noun = "set"
+ case trueTy.IsMapType():
+ noun = "map"
+ }
+ return fmt.Sprintf(
+ "Mismatched %s element types: %s",
+ noun, describeConditionalTypeMismatch(trueEty, falseEty),
+ )
+ }
+ }
+ }
+
+ // If we don't manage any more specialized message, we'll just report
+ // what the two types are.
+ trueName := trueTy.FriendlyName()
+ falseName := falseTy.FriendlyName()
+ if trueName == falseName {
+ // Absolute last resort for when we have no special rule above but
+ // we have two types with the same friendly name anyway. This is
+ // the most vague of all possible messages but is reserved for
+ // particularly awkward cases, like lists of lists of differing tuple
+ // types.
+ return "At least one deeply-nested attribute or element is not compatible across both the 'true' and the 'false' value"
+ }
+ return fmt.Sprintf(
+ "The 'true' value is %s, but the 'false' value is %s",
+ trueTy.FriendlyName(), falseTy.FriendlyName(),
+ )
+
+}
+
+func (e *ConditionalExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *ConditionalExpr) StartRange() hcl.Range {
+ return e.Condition.StartRange()
+}
+
+type IndexExpr struct {
+ Collection Expression
+ Key Expression
+
+ SrcRange hcl.Range
+ OpenRange hcl.Range
+ BracketRange hcl.Range
+}
+
+func (e *IndexExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Collection)
+ w(e.Key)
+}
+
+func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ coll, collDiags := e.Collection.Value(ctx)
+ key, keyDiags := e.Key.Value(ctx)
+ diags = append(diags, collDiags...)
+ diags = append(diags, keyDiags...)
+
+ val, indexDiags := hcl.Index(coll, key, &e.BracketRange)
+ setDiagEvalContext(indexDiags, e, ctx)
+ diags = append(diags, indexDiags...)
+ return val, diags
+}
+
+func (e *IndexExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *IndexExpr) StartRange() hcl.Range {
+ return e.OpenRange
+}
+
+type TupleConsExpr struct {
+ Exprs []Expression
+
+ SrcRange hcl.Range
+ OpenRange hcl.Range
+}
+
+func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) {
+ for _, expr := range e.Exprs {
+ w(expr)
+ }
+}
+
+func (e *TupleConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ var vals []cty.Value
+ var diags hcl.Diagnostics
+
+ vals = make([]cty.Value, len(e.Exprs))
+ for i, expr := range e.Exprs {
+ val, valDiags := expr.Value(ctx)
+ vals[i] = val
+ diags = append(diags, valDiags...)
+ }
+
+ return cty.TupleVal(vals), diags
+}
+
+func (e *TupleConsExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *TupleConsExpr) StartRange() hcl.Range {
+ return e.OpenRange
+}
+
+// Implementation for hcl.ExprList
+func (e *TupleConsExpr) ExprList() []hcl.Expression {
+ ret := make([]hcl.Expression, len(e.Exprs))
+ for i, expr := range e.Exprs {
+ ret[i] = expr
+ }
+ return ret
+}
+
+type ObjectConsExpr struct {
+ Items []ObjectConsItem
+
+ SrcRange hcl.Range
+ OpenRange hcl.Range
+}
+
+type ObjectConsItem struct {
+ KeyExpr Expression
+ ValueExpr Expression
+}
+
+func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) {
+ for _, item := range e.Items {
+ w(item.KeyExpr)
+ w(item.ValueExpr)
+ }
+}
+
+func (e *ObjectConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ var vals map[string]cty.Value
+ var diags hcl.Diagnostics
+ var marks []cty.ValueMarks
+
+ // This will get set to true if we fail to produce any of our keys,
+ // either because they are actually unknown or if the evaluation produces
+ // errors. In all of these case we must return DynamicPseudoType because
+ // we're unable to know the full set of keys our object has, and thus
+ // we can't produce a complete value of the intended type.
+ //
+ // We still evaluate all of the item keys and values to make sure that we
+ // get as complete as possible a set of diagnostics.
+ known := true
+
+ vals = make(map[string]cty.Value, len(e.Items))
+ for _, item := range e.Items {
+ key, keyDiags := item.KeyExpr.Value(ctx)
+ diags = append(diags, keyDiags...)
+
+ val, valDiags := item.ValueExpr.Value(ctx)
+ diags = append(diags, valDiags...)
+
+ if keyDiags.HasErrors() {
+ known = false
+ continue
+ }
+
+ if key.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Null value as key",
+ Detail: "Can't use a null value as a key.",
+ Subject: item.ValueExpr.Range().Ptr(),
+ Expression: item.KeyExpr,
+ EvalContext: ctx,
+ })
+ known = false
+ continue
+ }
+
+ key, keyMarks := key.Unmark()
+ marks = append(marks, keyMarks)
+
+ var err error
+ key, err = convert.Convert(key, cty.String)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Incorrect key type",
+ Detail: fmt.Sprintf("Can't use this value as a key: %s.", err.Error()),
+ Subject: item.KeyExpr.Range().Ptr(),
+ Expression: item.KeyExpr,
+ EvalContext: ctx,
+ })
+ known = false
+ continue
+ }
+
+ if !key.IsKnown() {
+ known = false
+ continue
+ }
+
+ keyStr := key.AsString()
+
+ vals[keyStr] = val
+ }
+
+ if !known {
+ return cty.DynamicVal, diags
+ }
+
+ return cty.ObjectVal(vals).WithMarks(marks...), diags
+}
+
+func (e *ObjectConsExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *ObjectConsExpr) StartRange() hcl.Range {
+ return e.OpenRange
+}
+
+// Implementation for hcl.ExprMap
+func (e *ObjectConsExpr) ExprMap() []hcl.KeyValuePair {
+ ret := make([]hcl.KeyValuePair, len(e.Items))
+ for i, item := range e.Items {
+ ret[i] = hcl.KeyValuePair{
+ Key: item.KeyExpr,
+ Value: item.ValueExpr,
+ }
+ }
+ return ret
+}
+
+// ObjectConsKeyExpr is a special wrapper used only for ObjectConsExpr keys,
+// which deals with the special case that a naked identifier in that position
+// must be interpreted as a literal string rather than evaluated directly.
+type ObjectConsKeyExpr struct {
+ Wrapped Expression
+ ForceNonLiteral bool
+}
+
+func (e *ObjectConsKeyExpr) literalName() string {
+ // This is our logic for deciding whether to behave like a literal string.
+ // We lean on our AbsTraversalForExpr implementation here, which already
+ // deals with some awkward cases like the expression being the result
+ // of the keywords "null", "true" and "false" which we'd want to interpret
+ // as keys here too.
+ return hcl.ExprAsKeyword(e.Wrapped)
+}
+
+func (e *ObjectConsKeyExpr) walkChildNodes(w internalWalkFunc) {
+ // We only treat our wrapped expression as a real expression if we're
+ // not going to interpret it as a literal.
+ if e.literalName() == "" {
+ w(e.Wrapped)
+ }
+}
+
+func (e *ObjectConsKeyExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ // Because we accept a naked identifier as a literal key rather than a
+ // reference, it's confusing to accept a traversal containing periods
+ // here since we can't tell if the user intends to create a key with
+ // periods or actually reference something. To avoid confusing downstream
+ // errors we'll just prohibit a naked multi-step traversal here and
+ // require the user to state their intent more clearly.
+ // (This is handled at evaluation time rather than parse time because
+ // an application using static analysis _can_ accept a naked multi-step
+ // traversal here, if desired.)
+ if !e.ForceNonLiteral {
+ if travExpr, isTraversal := e.Wrapped.(*ScopeTraversalExpr); isTraversal && len(travExpr.Traversal) > 1 {
+ var diags hcl.Diagnostics
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Ambiguous attribute key",
+ Detail: "If this expression is intended to be a reference, wrap it in parentheses. If it's instead intended as a literal name containing periods, wrap it in quotes to create a string literal.",
+ Subject: e.Range().Ptr(),
+ })
+ return cty.DynamicVal, diags
+ }
+
+ if ln := e.literalName(); ln != "" {
+ return cty.StringVal(ln), nil
+ }
+ }
+ return e.Wrapped.Value(ctx)
+}
+
+func (e *ObjectConsKeyExpr) Range() hcl.Range {
+ return e.Wrapped.Range()
+}
+
+func (e *ObjectConsKeyExpr) StartRange() hcl.Range {
+ return e.Wrapped.StartRange()
+}
+
+// Implementation for hcl.AbsTraversalForExpr.
+func (e *ObjectConsKeyExpr) AsTraversal() hcl.Traversal {
+ // If we're forcing a non-literal then we can never be interpreted
+ // as a traversal.
+ if e.ForceNonLiteral {
+ return nil
+ }
+
+ // We can produce a traversal only if our wrappee can.
+ st, diags := hcl.AbsTraversalForExpr(e.Wrapped)
+ if diags.HasErrors() {
+ return nil
+ }
+
+ return st
+}
+
+func (e *ObjectConsKeyExpr) UnwrapExpression() Expression {
+ return e.Wrapped
+}
+
+// ForExpr represents iteration constructs:
+//
+// tuple = [for i, v in list: upper(v) if i > 2]
+// object = {for k, v in map: k => upper(v)}
+// object_of_tuples = {for v in list: v.key: v...}
+type ForExpr struct {
+ KeyVar string // empty if ignoring the key
+ ValVar string
+
+ CollExpr Expression
+
+ KeyExpr Expression // nil when producing a tuple
+ ValExpr Expression
+ CondExpr Expression // null if no "if" clause is present
+
+ Group bool // set if the ellipsis is used on the value in an object for
+
+ SrcRange hcl.Range
+ OpenRange hcl.Range
+ CloseRange hcl.Range
+}
+
+func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ var marks []cty.ValueMarks
+
+ collVal, collDiags := e.CollExpr.Value(ctx)
+ diags = append(diags, collDiags...)
+
+ if collVal.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Iteration over null value",
+ Detail: "A null value cannot be used as the collection in a 'for' expression.",
+ Subject: e.CollExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CollExpr,
+ EvalContext: ctx,
+ })
+ return cty.DynamicVal, diags
+ }
+ if collVal.Type() == cty.DynamicPseudoType {
+ return cty.DynamicVal, diags
+ }
+ // Unmark collection before checking for iterability, because marked
+ // values cannot be iterated
+ collVal, collMarks := collVal.Unmark()
+ marks = append(marks, collMarks)
+ if !collVal.CanIterateElements() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Iteration over non-iterable value",
+ Detail: fmt.Sprintf(
+ "A value of type %s cannot be used as the collection in a 'for' expression.",
+ collVal.Type().FriendlyName(),
+ ),
+ Subject: e.CollExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CollExpr,
+ EvalContext: ctx,
+ })
+ return cty.DynamicVal, diags
+ }
+
+ // Grab the CondExpr marks when we're returning early with an unknown
+ var condMarks cty.ValueMarks
+
+ // Before we start we'll do an early check to see if any CondExpr we've
+ // been given is of the wrong type. This isn't 100% reliable (it may
+ // be DynamicVal until real values are given) but it should catch some
+ // straightforward cases and prevent a barrage of repeated errors.
+ if e.CondExpr != nil {
+ childCtx := ctx.NewChild()
+ childCtx.Variables = map[string]cty.Value{}
+ if e.KeyVar != "" {
+ childCtx.Variables[e.KeyVar] = cty.DynamicVal
+ }
+ childCtx.Variables[e.ValVar] = cty.DynamicVal
+
+ result, condDiags := e.CondExpr.Value(childCtx)
+ diags = append(diags, condDiags...)
+ if result.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Condition is null",
+ Detail: "The value of the 'if' clause must not be null.",
+ Subject: e.CondExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CondExpr,
+ EvalContext: ctx,
+ })
+ return cty.DynamicVal, diags
+ }
+
+ _, condMarks = result.Unmark()
+
+ _, err := convert.Convert(result, cty.Bool)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' condition",
+ Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
+ Subject: e.CondExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CondExpr,
+ EvalContext: ctx,
+ })
+ return cty.DynamicVal, diags
+ }
+ if condDiags.HasErrors() {
+ return cty.DynamicVal, diags
+ }
+ }
+
+ if !collVal.IsKnown() {
+ return cty.DynamicVal.WithMarks(append(marks, condMarks)...), diags
+ }
+
+ if e.KeyExpr != nil {
+ // Producing an object
+ var vals map[string]cty.Value
+ var groupVals map[string][]cty.Value
+ if e.Group {
+ groupVals = map[string][]cty.Value{}
+ } else {
+ vals = map[string]cty.Value{}
+ }
+
+ it := collVal.ElementIterator()
+
+ known := true
+ for it.Next() {
+ k, v := it.Element()
+ childCtx := ctx.NewChild()
+ childCtx.Variables = map[string]cty.Value{}
+ if e.KeyVar != "" {
+ childCtx.Variables[e.KeyVar] = k
+ }
+ childCtx.Variables[e.ValVar] = v
+
+ if e.CondExpr != nil {
+ includeRaw, condDiags := e.CondExpr.Value(childCtx)
+ diags = append(diags, condDiags...)
+ if includeRaw.IsNull() {
+ if known {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' condition",
+ Detail: "The value of the 'if' clause must not be null.",
+ Subject: e.CondExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CondExpr,
+ EvalContext: childCtx,
+ })
+ }
+ known = false
+ continue
+ }
+
+ // Extract and merge marks from the include expression into the
+ // main set of marks
+ _, includeMarks := includeRaw.Unmark()
+ marks = append(marks, includeMarks)
+
+ include, err := convert.Convert(includeRaw, cty.Bool)
+ if err != nil {
+ if known {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' condition",
+ Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
+ Subject: e.CondExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CondExpr,
+ EvalContext: childCtx,
+ })
+ }
+ known = false
+ continue
+ }
+ if !include.IsKnown() {
+ known = false
+ continue
+ }
+
+ // Extract and merge marks from the include expression into the
+ // main set of marks
+ includeUnmarked, _ := include.Unmark()
+ marks = append(marks, includeMarks)
+ if includeUnmarked.False() {
+ // Skip this element
+ continue
+ }
+ }
+
+ keyRaw, keyDiags := e.KeyExpr.Value(childCtx)
+ diags = append(diags, keyDiags...)
+ if keyRaw.IsNull() {
+ if known {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid object key",
+ Detail: "Key expression in 'for' expression must not produce a null value.",
+ Subject: e.KeyExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.KeyExpr,
+ EvalContext: childCtx,
+ })
+ }
+ known = false
+ continue
+ }
+
+ _, keyMarks := keyRaw.Unmark()
+ marks = append(marks, keyMarks)
+
+ if !keyRaw.IsKnown() {
+ known = false
+ continue
+ }
+
+ key, err := convert.Convert(keyRaw, cty.String)
+ if err != nil {
+ if known {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid object key",
+ Detail: fmt.Sprintf("The key expression produced an invalid result: %s.", err.Error()),
+ Subject: e.KeyExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.KeyExpr,
+ EvalContext: childCtx,
+ })
+ }
+ known = false
+ continue
+ }
+
+ key, _ = key.Unmark()
+
+ val, valDiags := e.ValExpr.Value(childCtx)
+ diags = append(diags, valDiags...)
+
+ if e.Group {
+ k := key.AsString()
+ groupVals[k] = append(groupVals[k], val)
+ } else {
+ k := key.AsString()
+ if _, exists := vals[k]; exists {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Duplicate object key",
+ Detail: fmt.Sprintf(
+ "Two different items produced the key %q in this 'for' expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.",
+ k,
+ ),
+ Subject: e.KeyExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.KeyExpr,
+ EvalContext: childCtx,
+ })
+ } else {
+ vals[key.AsString()] = val
+ }
+ }
+ }
+
+ if !known {
+ return cty.DynamicVal.WithMarks(marks...), diags
+ }
+
+ if e.Group {
+ vals = map[string]cty.Value{}
+ for k, gvs := range groupVals {
+ vals[k] = cty.TupleVal(gvs)
+ }
+ }
+
+ return cty.ObjectVal(vals).WithMarks(marks...), diags
+
+ } else {
+ // Producing a tuple
+ vals := []cty.Value{}
+
+ it := collVal.ElementIterator()
+
+ known := true
+ for it.Next() {
+ k, v := it.Element()
+ childCtx := ctx.NewChild()
+ childCtx.Variables = map[string]cty.Value{}
+ if e.KeyVar != "" {
+ childCtx.Variables[e.KeyVar] = k
+ }
+ childCtx.Variables[e.ValVar] = v
+
+ if e.CondExpr != nil {
+ includeRaw, condDiags := e.CondExpr.Value(childCtx)
+ diags = append(diags, condDiags...)
+ if includeRaw.IsNull() {
+ if known {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' condition",
+ Detail: "The value of the 'if' clause must not be null.",
+ Subject: e.CondExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CondExpr,
+ EvalContext: childCtx,
+ })
+ }
+ known = false
+ continue
+ }
+
+ // Extract and merge marks from the include expression into the
+ // main set of marks
+ _, includeMarks := includeRaw.Unmark()
+ marks = append(marks, includeMarks)
+
+ if !includeRaw.IsKnown() {
+ // We will eventually return DynamicVal, but we'll continue
+ // iterating in case there are other diagnostics to gather
+ // for later elements.
+ known = false
+ continue
+ }
+
+ include, err := convert.Convert(includeRaw, cty.Bool)
+ if err != nil {
+ if known {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' condition",
+ Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
+ Subject: e.CondExpr.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.CondExpr,
+ EvalContext: childCtx,
+ })
+ }
+ known = false
+ continue
+ }
+
+ includeUnmarked, _ := include.Unmark()
+ if includeUnmarked.False() {
+ // Skip this element
+ continue
+ }
+ }
+
+ val, valDiags := e.ValExpr.Value(childCtx)
+ diags = append(diags, valDiags...)
+ vals = append(vals, val)
+ }
+
+ if !known {
+ return cty.DynamicVal.WithMarks(marks...), diags
+ }
+
+ return cty.TupleVal(vals).WithMarks(marks...), diags
+ }
+}
+
+func (e *ForExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.CollExpr)
+
+ scopeNames := map[string]struct{}{}
+ if e.KeyVar != "" {
+ scopeNames[e.KeyVar] = struct{}{}
+ }
+ if e.ValVar != "" {
+ scopeNames[e.ValVar] = struct{}{}
+ }
+
+ if e.KeyExpr != nil {
+ w(ChildScope{
+ LocalNames: scopeNames,
+ Expr: e.KeyExpr,
+ })
+ }
+ w(ChildScope{
+ LocalNames: scopeNames,
+ Expr: e.ValExpr,
+ })
+ if e.CondExpr != nil {
+ w(ChildScope{
+ LocalNames: scopeNames,
+ Expr: e.CondExpr,
+ })
+ }
+}
+
+func (e *ForExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *ForExpr) StartRange() hcl.Range {
+ return e.OpenRange
+}
+
+type SplatExpr struct {
+ Source Expression
+ Each Expression
+ Item *AnonSymbolExpr
+
+ SrcRange hcl.Range
+ MarkerRange hcl.Range
+}
+
+func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ sourceVal, diags := e.Source.Value(ctx)
+ if diags.HasErrors() {
+ // We'll evaluate our "Each" expression here just to see if it
+ // produces any more diagnostics we can report. Since we're not
+ // assigning a value to our AnonSymbolExpr here it will return
+ // DynamicVal, which should short-circuit any use of it.
+ _, itemDiags := e.Item.Value(ctx)
+ diags = append(diags, itemDiags...)
+ return cty.DynamicVal, diags
+ }
+
+ sourceTy := sourceVal.Type()
+
+ // A "special power" of splat expressions is that they can be applied
+ // both to tuples/lists and to other values, and in the latter case
+ // the value will be treated as an implicit single-item tuple, or as
+ // an empty tuple if the value is null.
+ //nolint:staticcheck // QF1001: Demorgan's law wouldn't improve readability.
+ autoUpgrade := !(sourceTy.IsTupleType() || sourceTy.IsListType() || sourceTy.IsSetType())
+
+ if sourceVal.IsNull() {
+ if autoUpgrade {
+ return cty.EmptyTupleVal.WithSameMarks(sourceVal), diags
+ }
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Splat of null value",
+ Detail: "Splat expressions (with the * symbol) cannot be applied to null sequences.",
+ Subject: e.Source.Range().Ptr(),
+ Context: hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),
+ Expression: e.Source,
+ EvalContext: ctx,
+ })
+ return cty.DynamicVal, diags
+ }
+
+ if sourceTy == cty.DynamicPseudoType {
+ // If we don't even know the _type_ of our source value yet then
+ // we'll need to defer all processing, since we can't decide our
+ // result type either.
+ return cty.DynamicVal.WithSameMarks(sourceVal), diags
+ }
+
+ upgradedUnknown := false
+ if autoUpgrade {
+ // If we're upgrading an unknown value to a tuple/list, the result
+ // cannot be known. Otherwise a tuple containing an unknown value will
+ // upgrade to a different number of elements depending on whether
+ // sourceVal becomes null or not.
+ // We record this condition here so we can process any remaining
+ // expression after the * to verify the result of the traversal. For
+ // example, it is valid to use a splat on a single object to retrieve a
+ // list of a single attribute, but we still need to check if that
+ // attribute actually exists.
+ if !sourceVal.IsKnown() {
+ unmarkedVal, _ := sourceVal.Unmark()
+ sourceRng := unmarkedVal.Range()
+ if sourceRng.CouldBeNull() {
+ upgradedUnknown = true
+ }
+ }
+
+ sourceVal = cty.TupleVal([]cty.Value{sourceVal}).WithSameMarks(sourceVal)
+ sourceTy = sourceVal.Type()
+ }
+
+ // We'll compute our result type lazily if we need it. In the normal case
+ // it's inferred automatically from the value we construct.
+ resultTy := func() (cty.Type, hcl.Diagnostics) {
+ chiCtx := ctx.NewChild()
+ var diags hcl.Diagnostics
+ switch {
+ case sourceTy.IsListType() || sourceTy.IsSetType():
+ ety := sourceTy.ElementType()
+ e.Item.setValue(chiCtx, cty.UnknownVal(ety))
+ val, itemDiags := e.Each.Value(chiCtx)
+ diags = append(diags, itemDiags...)
+ e.Item.clearValue(chiCtx) // clean up our temporary value
+ return cty.List(val.Type()), diags
+ case sourceTy.IsTupleType():
+ etys := sourceTy.TupleElementTypes()
+ resultTys := make([]cty.Type, 0, len(etys))
+ for _, ety := range etys {
+ e.Item.setValue(chiCtx, cty.UnknownVal(ety))
+ val, itemDiags := e.Each.Value(chiCtx)
+ diags = append(diags, itemDiags...)
+ e.Item.clearValue(chiCtx) // clean up our temporary value
+ resultTys = append(resultTys, val.Type())
+ }
+ return cty.Tuple(resultTys), diags
+ default:
+ // Should never happen because of our promotion to list above.
+ return cty.DynamicPseudoType, diags
+ }
+ }
+
+ if !sourceVal.IsKnown() {
+ // We can't produce a known result in this case, but we'll still
+ // indicate what the result type would be, allowing any downstream type
+ // checking to proceed.
+ ty, tyDiags := resultTy()
+ diags = append(diags, tyDiags...)
+ ret := cty.UnknownVal(ty)
+ if ty != cty.DynamicPseudoType {
+ ret = ret.RefineNotNull()
+ }
+ if ty.IsListType() && sourceVal.Type().IsCollectionType() {
+ // We can refine the length of an unknown list result based on
+ // the source collection's own length.
+ sv, _ := sourceVal.Unmark()
+ sourceRng := sv.Range()
+ ret = ret.Refine().
+ CollectionLengthLowerBound(sourceRng.LengthLowerBound()).
+ CollectionLengthUpperBound(sourceRng.LengthUpperBound()).
+ NewValue()
+ }
+ return ret.WithSameMarks(sourceVal), diags
+ }
+
+ // Unmark the collection, and save the marks to apply to the returned
+ // collection result
+ sourceVal, marks := sourceVal.Unmark()
+ vals := make([]cty.Value, 0, sourceVal.LengthInt())
+ it := sourceVal.ElementIterator()
+ if ctx == nil {
+ // we need a context to use our AnonSymbolExpr, so we'll just
+ // make an empty one here to use as a placeholder.
+ ctx = ctx.NewChild()
+ }
+ isKnown := true
+ for it.Next() {
+ _, sourceItem := it.Element()
+ e.Item.setValue(ctx, sourceItem)
+ newItem, itemDiags := e.Each.Value(ctx)
+ diags = append(diags, itemDiags...)
+ if itemDiags.HasErrors() {
+ isKnown = false
+ }
+ vals = append(vals, newItem)
+ }
+ e.Item.clearValue(ctx) // clean up our temporary value
+
+ if upgradedUnknown {
+ return cty.DynamicVal.WithMarks(marks), diags
+ }
+
+ if !isKnown {
+ // We'll ingore the resultTy diagnostics in this case since they
+ // will just be the same errors we saw while iterating above.
+ ty, _ := resultTy()
+ return cty.UnknownVal(ty).WithMarks(marks), diags
+ }
+
+ switch {
+ case sourceTy.IsListType() || sourceTy.IsSetType():
+ if len(vals) == 0 {
+ ty, tyDiags := resultTy()
+ diags = append(diags, tyDiags...)
+ return cty.ListValEmpty(ty.ElementType()).WithMarks(marks), diags
+ }
+ // Unfortunately it's possible for a nested splat on scalar values to
+ // generate non-homogenously-typed vals, and we discovered this bad
+ // interaction after the two conflicting behaviors were both
+ // well-established so it isn't clear how to change them without
+ // breaking existing code. Therefore we just make that an error for
+ // now, to avoid crashing trying to constuct an impossible list.
+ if !cty.CanListVal(vals) {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid nested splat expressions",
+ Detail: "The second level of splat expression produced elements of different types, so it isn't possible to construct a valid list to represent the top-level result.\n\nConsider using a for expression instead, to produce a tuple-typed result which can therefore have non-homogenous element types.",
+ Subject: e.Each.Range().Ptr(),
+ Context: e.Range().Ptr(), // encourage a diagnostic renderer to also include the "source" part of the expression in its code snippet
+ })
+ return cty.DynamicVal, diags
+ }
+ return cty.ListVal(vals).WithMarks(marks), diags
+ default:
+ return cty.TupleVal(vals).WithMarks(marks), diags
+ }
+}
+
+func (e *SplatExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Source)
+ w(e.Each)
+}
+
+func (e *SplatExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *SplatExpr) StartRange() hcl.Range {
+ return e.MarkerRange
+}
+
+// AnonSymbolExpr is used as a placeholder for a value in an expression that
+// can be applied dynamically to any value at runtime.
+//
+// This is a rather odd, synthetic expression. It is used as part of the
+// representation of splat expressions as a placeholder for the current item
+// being visited in the splat evaluation.
+//
+// AnonSymbolExpr cannot be evaluated in isolation. If its Value is called
+// directly then cty.DynamicVal will be returned. Instead, it is evaluated
+// in terms of another node (i.e. a splat expression) which temporarily
+// assigns it a value.
+type AnonSymbolExpr struct {
+ SrcRange hcl.Range
+
+ // values and its associated lock are used to isolate concurrent
+ // evaluations of a symbol from one another. It is the calling application's
+ // responsibility to ensure that the same splat expression is not evalauted
+ // concurrently within the _same_ EvalContext, but it is fine and safe to
+ // do cuncurrent evaluations with distinct EvalContexts.
+ values map[*hcl.EvalContext]cty.Value
+ valuesLock sync.RWMutex
+}
+
+func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ if ctx == nil {
+ return cty.DynamicVal, nil
+ }
+
+ e.valuesLock.RLock()
+ defer e.valuesLock.RUnlock()
+
+ val, exists := e.values[ctx]
+ if !exists {
+ return cty.DynamicVal, nil
+ }
+ return val, nil
+}
+
+// setValue sets a temporary local value for the expression when evaluated
+// in the given context, which must be non-nil.
+func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
+ e.valuesLock.Lock()
+ defer e.valuesLock.Unlock()
+
+ if e.values == nil {
+ e.values = make(map[*hcl.EvalContext]cty.Value)
+ }
+ if ctx == nil {
+ panic("can't setValue for a nil EvalContext")
+ }
+ e.values[ctx] = val
+}
+
+func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) {
+ e.valuesLock.Lock()
+ defer e.valuesLock.Unlock()
+
+ if e.values == nil {
+ return
+ }
+ if ctx == nil {
+ panic("can't clearValue for a nil EvalContext")
+ }
+ delete(e.values, ctx)
+}
+
+func (e *AnonSymbolExpr) walkChildNodes(w internalWalkFunc) {
+ // AnonSymbolExpr is a leaf node in the tree
+}
+
+func (e *AnonSymbolExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *AnonSymbolExpr) StartRange() hcl.Range {
+ return e.SrcRange
+}
+
+// ExprSyntaxError is a placeholder for an invalid expression that could not
+// be parsed due to syntax errors.
+type ExprSyntaxError struct {
+ Placeholder cty.Value
+ ParseDiags hcl.Diagnostics
+ SrcRange hcl.Range
+}
+
+func (e *ExprSyntaxError) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ return e.Placeholder, e.ParseDiags
+}
+
+func (e *ExprSyntaxError) walkChildNodes(w internalWalkFunc) {
+ // ExprSyntaxError is a leaf node in the tree
+}
+
+func (e *ExprSyntaxError) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *ExprSyntaxError) StartRange() hcl.Range {
+ return e.SrcRange
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_ops.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_ops.go
new file mode 100644
index 00000000000..da146ef830f
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_ops.go
@@ -0,0 +1,365 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/function/stdlib"
+)
+
+type Operation struct {
+ Impl function.Function
+ Type cty.Type
+
+ // ShortCircuit is an optional callback for binary operations which, if set,
+ // will be called with the result of evaluating the LHS and RHS expressions
+ // and their individual diagnostics. The LHS and RHS values are guaranteed
+ // to be unmarked and of the correct type.
+ //
+ // ShortCircuit may return cty.NilVal to allow evaluation to proceed as
+ // normal, or it may return a non-nil value with diagnostics to return
+ // before the main Impl is called. The returned diagnostics should match
+ // the side of the Operation which was taken.
+ ShortCircuit func(lhs, rhs cty.Value, lhsDiags, rhsDiags hcl.Diagnostics) (cty.Value, hcl.Diagnostics)
+}
+
+var (
+ OpLogicalOr = &Operation{
+ Impl: stdlib.OrFunc,
+ Type: cty.Bool,
+
+ ShortCircuit: func(lhs, rhs cty.Value, lhsDiags, rhsDiags hcl.Diagnostics) (cty.Value, hcl.Diagnostics) {
+ switch {
+ // if both are unknown, we don't short circuit anything
+ case !lhs.IsKnown() && !rhs.IsKnown():
+ // short-circuit left-to-right when encountering a good unknown
+ // value and both are unknown.
+ if !lhsDiags.HasErrors() {
+ return cty.UnknownVal(cty.Bool).RefineNotNull(), lhsDiags
+ }
+ // If the LHS has an error, the RHS might too. Don't
+ // short-circuit so both diags get collected.
+ return cty.NilVal, nil
+
+ // for ||, a single true is the controlling condition
+ case lhs.IsKnown() && lhs.True():
+ return cty.True, lhsDiags
+ case rhs.IsKnown() && rhs.True():
+ return cty.True, rhsDiags
+
+ // if the opposing side is false we can't short-circuit based on
+ // boolean logic, so an unknown becomes the controlling condition
+ case !lhs.IsKnown() && rhs.False():
+ return cty.UnknownVal(cty.Bool).RefineNotNull(), lhsDiags
+ case !rhs.IsKnown() && lhs.False():
+ return cty.UnknownVal(cty.Bool).RefineNotNull(), rhsDiags
+ }
+
+ return cty.NilVal, nil
+ },
+ }
+ OpLogicalAnd = &Operation{
+ Impl: stdlib.AndFunc,
+ Type: cty.Bool,
+
+ ShortCircuit: func(lhs, rhs cty.Value, lhsDiags, rhsDiags hcl.Diagnostics) (cty.Value, hcl.Diagnostics) {
+
+ switch {
+ case !lhs.IsKnown() && !rhs.IsKnown():
+ // short-circuit left-to-right when encountering a good unknown
+ // value and both are unknown.
+ if !lhsDiags.HasErrors() {
+ return cty.UnknownVal(cty.Bool).RefineNotNull(), lhsDiags
+ }
+ // If the LHS has an error, the RHS might too. Don't
+ // short-circuit so both diags get collected.
+ return cty.NilVal, nil
+
+ // For &&, a single false is the controlling condition
+ case lhs.IsKnown() && lhs.False():
+ return cty.False, lhsDiags
+ case rhs.IsKnown() && rhs.False():
+ return cty.False, rhsDiags
+
+ // if the opposing side is true we can't short-circuit based on
+ // boolean logic, so an unknown becomes the controlling condition
+ case !lhs.IsKnown() && rhs.True():
+ return cty.UnknownVal(cty.Bool).RefineNotNull(), lhsDiags
+ case !rhs.IsKnown() && lhs.True():
+ return cty.UnknownVal(cty.Bool).RefineNotNull(), rhsDiags
+ }
+ return cty.NilVal, nil
+ },
+ }
+ OpLogicalNot = &Operation{
+ Impl: stdlib.NotFunc,
+ Type: cty.Bool,
+ }
+
+ OpEqual = &Operation{
+ Impl: stdlib.EqualFunc,
+ Type: cty.Bool,
+ }
+ OpNotEqual = &Operation{
+ Impl: stdlib.NotEqualFunc,
+ Type: cty.Bool,
+ }
+
+ OpGreaterThan = &Operation{
+ Impl: stdlib.GreaterThanFunc,
+ Type: cty.Bool,
+ }
+ OpGreaterThanOrEqual = &Operation{
+ Impl: stdlib.GreaterThanOrEqualToFunc,
+ Type: cty.Bool,
+ }
+ OpLessThan = &Operation{
+ Impl: stdlib.LessThanFunc,
+ Type: cty.Bool,
+ }
+ OpLessThanOrEqual = &Operation{
+ Impl: stdlib.LessThanOrEqualToFunc,
+ Type: cty.Bool,
+ }
+
+ OpAdd = &Operation{
+ Impl: stdlib.AddFunc,
+ Type: cty.Number,
+ }
+ OpSubtract = &Operation{
+ Impl: stdlib.SubtractFunc,
+ Type: cty.Number,
+ }
+ OpMultiply = &Operation{
+ Impl: stdlib.MultiplyFunc,
+ Type: cty.Number,
+ }
+ OpDivide = &Operation{
+ Impl: stdlib.DivideFunc,
+ Type: cty.Number,
+ }
+ OpModulo = &Operation{
+ Impl: stdlib.ModuloFunc,
+ Type: cty.Number,
+ }
+ OpNegate = &Operation{
+ Impl: stdlib.NegateFunc,
+ Type: cty.Number,
+ }
+)
+
+var binaryOps []map[TokenType]*Operation
+
+func init() {
+ // This operation table maps from the operator's token type
+ // to the AST operation type. All expressions produced from
+ // binary operators are BinaryOp nodes.
+ //
+ // Binary operator groups are listed in order of precedence, with
+ // the *lowest* precedence first. Operators within the same group
+ // have left-to-right associativity.
+ binaryOps = []map[TokenType]*Operation{
+ {
+ TokenOr: OpLogicalOr,
+ },
+ {
+ TokenAnd: OpLogicalAnd,
+ },
+ {
+ TokenEqualOp: OpEqual,
+ TokenNotEqual: OpNotEqual,
+ },
+ {
+ TokenGreaterThan: OpGreaterThan,
+ TokenGreaterThanEq: OpGreaterThanOrEqual,
+ TokenLessThan: OpLessThan,
+ TokenLessThanEq: OpLessThanOrEqual,
+ },
+ {
+ TokenPlus: OpAdd,
+ TokenMinus: OpSubtract,
+ },
+ {
+ TokenStar: OpMultiply,
+ TokenSlash: OpDivide,
+ TokenPercent: OpModulo,
+ },
+ }
+}
+
+type BinaryOpExpr struct {
+ LHS Expression
+ Op *Operation
+ RHS Expression
+
+ SrcRange hcl.Range
+}
+
+func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.LHS)
+ w(e.RHS)
+}
+
+func (e *BinaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ impl := e.Op.Impl // assumed to be a function taking exactly two arguments
+ params := impl.Params()
+ lhsParam := params[0]
+ rhsParam := params[1]
+
+ var diags hcl.Diagnostics
+
+ givenLHSVal, lhsDiags := e.LHS.Value(ctx)
+ lhsVal, err := convert.Convert(givenLHSVal, lhsParam.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid operand",
+ Detail: fmt.Sprintf("Unsuitable value for left operand: %s.", err),
+ Subject: e.LHS.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.LHS,
+ EvalContext: ctx,
+ })
+ }
+
+ givenRHSVal, rhsDiags := e.RHS.Value(ctx)
+ rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid operand",
+ Detail: fmt.Sprintf("Unsuitable value for right operand: %s.", err),
+ Subject: e.RHS.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.RHS,
+ EvalContext: ctx,
+ })
+ }
+
+ // diags so far only contains conversion errors, which should cover
+ // incorrect parameter types.
+ if diags.HasErrors() {
+ // Add the rest of the diagnostic in case that helps the user, but keep
+ // them separate as we continue for short-circuit handling.
+ diags = append(diags, lhsDiags...)
+ diags = append(diags, rhsDiags...)
+ return cty.UnknownVal(e.Op.Type), diags
+ }
+
+ lhsVal, lhsMarks := lhsVal.Unmark()
+ rhsVal, rhsMarks := rhsVal.Unmark()
+
+ if e.Op.ShortCircuit != nil {
+ forceResult, diags := e.Op.ShortCircuit(lhsVal, rhsVal, lhsDiags, rhsDiags)
+ if forceResult != cty.NilVal {
+ // It would be technically more correct to insert rhs diagnostics if
+ // forceResult is not known since we didn't really short-circuit. That
+ // would however not match the behavior of conditional expressions which
+ // do drop all diagnostics from the unevaluated expressions
+ return forceResult.WithMarks(lhsMarks, rhsMarks), diags
+ }
+ }
+
+ diags = append(diags, lhsDiags...)
+ diags = append(diags, rhsDiags...)
+ if diags.HasErrors() {
+ // Don't actually try the call if we have errors, since the this will
+ // probably just produce confusing duplicate diagnostics.
+ return cty.UnknownVal(e.Op.Type).WithMarks(lhsMarks, rhsMarks), diags
+ }
+
+ args := []cty.Value{lhsVal, rhsVal}
+ result, err := impl.Call(args)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ // FIXME: This diagnostic is useless.
+ Severity: hcl.DiagError,
+ Summary: "Operation failed",
+ Detail: fmt.Sprintf("Error during operation: %s.", err),
+ Subject: &e.SrcRange,
+ Expression: e,
+ EvalContext: ctx,
+ })
+ return cty.UnknownVal(e.Op.Type), diags
+ }
+
+ return result.WithMarks(lhsMarks, rhsMarks), diags
+}
+
+func (e *BinaryOpExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *BinaryOpExpr) StartRange() hcl.Range {
+ return e.LHS.StartRange()
+}
+
+type UnaryOpExpr struct {
+ Op *Operation
+ Val Expression
+
+ SrcRange hcl.Range
+ SymbolRange hcl.Range
+}
+
+func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Val)
+}
+
+func (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ impl := e.Op.Impl // assumed to be a function taking exactly one argument
+ params := impl.Params()
+ param := params[0]
+
+ givenVal, diags := e.Val.Value(ctx)
+
+ val, err := convert.Convert(givenVal, param.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid operand",
+ Detail: fmt.Sprintf("Unsuitable value for unary operand: %s.", err),
+ Subject: e.Val.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: e.Val,
+ EvalContext: ctx,
+ })
+ }
+
+ if diags.HasErrors() {
+ // Don't actually try the call if we have errors already, since the
+ // this will probably just produce a confusing duplicative diagnostic.
+ return cty.UnknownVal(e.Op.Type), diags
+ }
+
+ args := []cty.Value{val}
+ result, err := impl.Call(args)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ // FIXME: This diagnostic is useless.
+ Severity: hcl.DiagError,
+ Summary: "Operation failed",
+ Detail: fmt.Sprintf("Error during operation: %s.", err),
+ Subject: &e.SrcRange,
+ Expression: e,
+ EvalContext: ctx,
+ })
+ return cty.UnknownVal(e.Op.Type), diags
+ }
+
+ return result, diags
+}
+
+func (e *UnaryOpExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *UnaryOpExpr) StartRange() hcl.Range {
+ return e.SymbolRange
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_template.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_template.go
new file mode 100644
index 00000000000..5713c004dfb
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_template.go
@@ -0,0 +1,260 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+type TemplateExpr struct {
+ Parts []Expression
+
+ SrcRange hcl.Range
+}
+
+func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) {
+ for _, part := range e.Parts {
+ w(part)
+ }
+}
+
+func (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ buf := &bytes.Buffer{}
+ var diags hcl.Diagnostics
+ isKnown := true
+
+ // Maintain a set of marks for values used in the template
+ marks := make(cty.ValueMarks)
+
+ for _, part := range e.Parts {
+ partVal, partDiags := part.Value(ctx)
+ diags = append(diags, partDiags...)
+
+ if partVal.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid template interpolation value",
+ Detail: "The expression result is null. Cannot include a null value in a string template.",
+ Subject: part.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: part,
+ EvalContext: ctx,
+ })
+ continue
+ }
+
+ // Unmark the part and merge its marks into the set
+ unmarkedVal, partMarks := partVal.Unmark()
+ for k, v := range partMarks {
+ marks[k] = v
+ }
+
+ if !partVal.IsKnown() {
+ // If any part is unknown then the result as a whole must be
+ // unknown too. We'll keep on processing the rest of the parts
+ // anyway, because we want to still emit any diagnostics resulting
+ // from evaluating those.
+ isKnown = false
+ continue
+ }
+
+ strVal, err := convert.Convert(unmarkedVal, cty.String)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid template interpolation value",
+ Detail: fmt.Sprintf(
+ "Cannot include the given value in a string template: %s.",
+ err.Error(),
+ ),
+ Subject: part.Range().Ptr(),
+ Context: &e.SrcRange,
+ Expression: part,
+ EvalContext: ctx,
+ })
+ continue
+ }
+
+ // If we're just continuing to validate after we found an unknown value
+ // then we'll skip appending so that "buf" will contain only the
+ // known prefix of the result.
+ if isKnown && !diags.HasErrors() {
+ buf.WriteString(strVal.AsString())
+ }
+ }
+
+ var ret cty.Value
+ if !isKnown {
+ ret = cty.UnknownVal(cty.String)
+ if !diags.HasErrors() { // Invalid input means our partial result buffer is suspect
+ if knownPrefix := buf.String(); knownPrefix != "" {
+ byteLen := len(knownPrefix)
+ // Impose a reasonable upper limit to avoid producing too long a prefix.
+ // The 128 B is about 10% of the safety limits in cty's msgpack decoder.
+ // @see https://github.com/zclconf/go-cty/blob/v1.13.2/cty/msgpack/unknown.go#L170-L175
+ //
+ // This operation is safe because StringPrefix removes incomplete trailing grapheme clusters.
+ if byteLen > 128 { // arbitrarily-decided threshold
+ byteLen = 128
+ }
+ ret = ret.Refine().StringPrefix(knownPrefix[:byteLen]).NewValue()
+ }
+ }
+ } else {
+ ret = cty.StringVal(buf.String())
+ }
+
+ // A template rendering result is never null.
+ ret = ret.RefineNotNull()
+
+ // Apply the full set of marks to the returned value
+ return ret.WithMarks(marks), diags
+}
+
+func (e *TemplateExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *TemplateExpr) StartRange() hcl.Range {
+ return e.Parts[0].StartRange()
+}
+
+// IsStringLiteral returns true if and only if the template consists only of
+// single string literal, as would be created for a simple quoted string like
+// "foo".
+//
+// If this function returns true, then calling Value on the same expression
+// with a nil EvalContext will return the literal value.
+//
+// Note that "${"foo"}", "${1}", etc aren't considered literal values for the
+// purposes of this method, because the intent of this method is to identify
+// situations where the user seems to be explicitly intending literal string
+// interpretation, not situations that result in literals as a technicality
+// of the template expression unwrapping behavior.
+func (e *TemplateExpr) IsStringLiteral() bool {
+ if len(e.Parts) != 1 {
+ return false
+ }
+ _, ok := e.Parts[0].(*LiteralValueExpr)
+ return ok
+}
+
+// TemplateJoinExpr is used to convert tuples of strings produced by template
+// constructs (i.e. for loops) into flat strings, by converting the values
+// tos strings and joining them. This AST node is not used directly; it's
+// produced as part of the AST of a "for" loop in a template.
+type TemplateJoinExpr struct {
+ Tuple Expression
+}
+
+func (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Tuple)
+}
+
+func (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ tuple, diags := e.Tuple.Value(ctx)
+
+ if tuple.IsNull() {
+ // This indicates a bug in the code that constructed the AST.
+ panic("TemplateJoinExpr got null tuple")
+ }
+ if tuple.Type() == cty.DynamicPseudoType {
+ return cty.UnknownVal(cty.String), diags
+ }
+ if !tuple.Type().IsTupleType() {
+ // This indicates a bug in the code that constructed the AST.
+ panic("TemplateJoinExpr got non-tuple tuple")
+ }
+ if !tuple.IsKnown() {
+ return cty.UnknownVal(cty.String), diags
+ }
+
+ tuple, marks := tuple.Unmark()
+ allMarks := []cty.ValueMarks{marks}
+ buf := &bytes.Buffer{}
+ it := tuple.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+
+ if val.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid template interpolation value",
+ Detail: "An iteration result is null. Cannot include a null value in a string template.",
+ Subject: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ })
+ continue
+ }
+ if val.Type() == cty.DynamicPseudoType {
+ return cty.UnknownVal(cty.String).WithMarks(marks), diags
+ }
+ strVal, err := convert.Convert(val, cty.String)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid template interpolation value",
+ Detail: fmt.Sprintf(
+ "Cannot include one of the interpolation results into the string template: %s.",
+ err.Error(),
+ ),
+ Subject: e.Range().Ptr(),
+ Expression: e,
+ EvalContext: ctx,
+ })
+ continue
+ }
+ if !val.IsKnown() {
+ return cty.UnknownVal(cty.String).WithMarks(marks), diags
+ }
+
+ strVal, strValMarks := strVal.Unmark()
+ if len(strValMarks) > 0 {
+ allMarks = append(allMarks, strValMarks)
+ }
+ buf.WriteString(strVal.AsString())
+ }
+
+ return cty.StringVal(buf.String()).WithMarks(allMarks...), diags
+}
+
+func (e *TemplateJoinExpr) Range() hcl.Range {
+ return e.Tuple.Range()
+}
+
+func (e *TemplateJoinExpr) StartRange() hcl.Range {
+ return e.Tuple.StartRange()
+}
+
+// TemplateWrapExpr is used instead of a TemplateExpr when a template
+// consists _only_ of a single interpolation sequence. In that case, the
+// template's result is the single interpolation's result, verbatim with
+// no type conversions.
+type TemplateWrapExpr struct {
+ Wrapped Expression
+
+ SrcRange hcl.Range
+}
+
+func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) {
+ w(e.Wrapped)
+}
+
+func (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
+ return e.Wrapped.Value(ctx)
+}
+
+func (e *TemplateWrapExpr) Range() hcl.Range {
+ return e.SrcRange
+}
+
+func (e *TemplateWrapExpr) StartRange() hcl.Range {
+ return e.SrcRange
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_vars.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_vars.go
new file mode 100644
index 00000000000..6c3e472caba
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_vars.go
@@ -0,0 +1,83 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+// Generated by expression_vars_gen.go. DO NOT EDIT.
+// Run 'go generate' on this package to update the set of functions here.
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+func (e *AnonSymbolExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *BinaryOpExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *ConditionalExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *ExprSyntaxError) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *ForExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *FunctionCallExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *IndexExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *LiteralValueExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *ObjectConsExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *ObjectConsKeyExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *RelativeTraversalExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *ScopeTraversalExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *SplatExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *TemplateExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *TemplateJoinExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *TemplateWrapExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *TupleConsExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
+
+func (e *UnaryOpExpr) Variables() []hcl.Traversal {
+ return Variables(e)
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/file.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/file.go
new file mode 100644
index 00000000000..7be626ffd66
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/file.go
@@ -0,0 +1,23 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+// File is the top-level object resulting from parsing a configuration file.
+type File struct {
+ Body *Body
+ Bytes []byte
+}
+
+func (f *File) AsHCLFile() *hcl.File {
+ return &hcl.File{
+ Body: f.Body,
+ Bytes: f.Bytes,
+
+ // TODO: The Nav object, once we have an implementation of it
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/generate.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/generate.go
new file mode 100644
index 00000000000..66486074c7c
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/generate.go
@@ -0,0 +1,12 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+//go:generate go run expression_vars_gen.go
+//go:generate ruby unicode2ragel.rb --url=http://www.unicode.org/Public/9.0.0/ucd/DerivedCoreProperties.txt -m UnicodeDerived -p ID_Start,ID_Continue -o unicode_derived.rl
+//go:generate ragel -Z scan_tokens.rl
+//go:generate gofmt -w scan_tokens.go
+//go:generate ragel -Z scan_string_lit.rl
+//go:generate gofmt -w scan_string_lit.go
+//go:generate go run golang.org/x/tools/cmd/stringer -type TokenType -output token_type_string.go
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/keywords.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/keywords.go
new file mode 100644
index 00000000000..5124ae95c33
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/keywords.go
@@ -0,0 +1,24 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+)
+
+type Keyword []byte
+
+var forKeyword = Keyword([]byte{'f', 'o', 'r'})
+var inKeyword = Keyword([]byte{'i', 'n'})
+var ifKeyword = Keyword([]byte{'i', 'f'})
+var elseKeyword = Keyword([]byte{'e', 'l', 's', 'e'})
+var endifKeyword = Keyword([]byte{'e', 'n', 'd', 'i', 'f'})
+var endforKeyword = Keyword([]byte{'e', 'n', 'd', 'f', 'o', 'r'})
+
+func (kw Keyword) TokenMatches(token Token) bool {
+ if token.Type != TokenIdent {
+ return false
+ }
+ return bytes.Equal([]byte(kw), token.Bytes)
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/navigation.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/navigation.go
new file mode 100644
index 00000000000..83e1d4efb5d
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/navigation.go
@@ -0,0 +1,62 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+type navigation struct {
+ root *Body
+}
+
+// Implementation of hcled.ContextString
+func (n navigation) ContextString(offset int) string {
+ // We will walk our top-level blocks until we find one that contains
+ // the given offset, and then construct a representation of the header
+ // of the block.
+
+ var block *Block
+ for _, candidate := range n.root.Blocks {
+ if candidate.Range().ContainsOffset(offset) {
+ block = candidate
+ break
+ }
+ }
+
+ if block == nil {
+ return ""
+ }
+
+ if len(block.Labels) == 0 {
+ // Easy case!
+ return block.Type
+ }
+
+ buf := &bytes.Buffer{}
+ buf.WriteString(block.Type)
+ for _, label := range block.Labels {
+ fmt.Fprintf(buf, " %q", label)
+ }
+ return buf.String()
+}
+
+func (n navigation) ContextDefRange(offset int) hcl.Range {
+ var block *Block
+ for _, candidate := range n.root.Blocks {
+ if candidate.Range().ContainsOffset(offset) {
+ block = candidate
+ break
+ }
+ }
+
+ if block == nil {
+ return hcl.Range{}
+ }
+
+ return block.DefRange()
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/node.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/node.go
new file mode 100644
index 00000000000..6ead6091c6e
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/node.go
@@ -0,0 +1,25 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+// Node is the abstract type that every AST node implements.
+//
+// This is a closed interface, so it cannot be implemented from outside of
+// this package.
+type Node interface {
+ // This is the mechanism by which the public-facing walk functions
+ // are implemented. Implementations should call the given function
+ // for each child node and then replace that node with its return value.
+ // The return value might just be the same node, for non-transforming
+ // walks.
+ walkChildNodes(w internalWalkFunc)
+
+ Range() hcl.Range
+}
+
+type internalWalkFunc func(Node)
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser.go
new file mode 100644
index 00000000000..fec7861a29f
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser.go
@@ -0,0 +1,2232 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+ "unicode/utf8"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type parser struct {
+ *peeker
+
+ // set to true if any recovery is attempted. The parser can use this
+ // to attempt to reduce error noise by suppressing "bad token" errors
+ // in recovery mode, assuming that the recovery heuristics have failed
+ // in this case and left the peeker in a wrong place.
+ recovery bool
+}
+
+func (p *parser) ParseBody(end TokenType) (*Body, hcl.Diagnostics) {
+ attrs := Attributes{}
+ blocks := Blocks{}
+ var diags hcl.Diagnostics
+
+ startRange := p.PrevRange()
+ var endRange hcl.Range
+
+Token:
+ for {
+ next := p.Peek()
+ if next.Type == end {
+ endRange = p.NextRange()
+ p.Read()
+ break Token
+ }
+
+ switch next.Type {
+ case TokenNewline:
+ p.Read()
+ continue
+ case TokenIdent:
+ item, itemDiags := p.ParseBodyItem()
+ diags = append(diags, itemDiags...)
+ switch titem := item.(type) {
+ case *Block:
+ blocks = append(blocks, titem)
+ case *Attribute:
+ if existing, exists := attrs[titem.Name]; exists {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Attribute redefined",
+ Detail: fmt.Sprintf(
+ "The argument %q was already set at %s. Each argument may be set only once.",
+ titem.Name, existing.NameRange.String(),
+ ),
+ Subject: &titem.NameRange,
+ })
+ } else {
+ attrs[titem.Name] = titem
+ }
+ default:
+ // This should never happen for valid input, but may if a
+ // syntax error was detected in ParseBodyItem that prevented
+ // it from even producing a partially-broken item. In that
+ // case, it would've left at least one error in the diagnostics
+ // slice we already dealt with above.
+ //
+ // We'll assume ParseBodyItem attempted recovery to leave
+ // us in a reasonable position to try parsing the next item.
+ continue
+ }
+ default:
+ bad := p.Read()
+ if !p.recovery {
+ switch bad.Type {
+ case TokenOQuote:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid argument name",
+ Detail: "Argument names must not be quoted.",
+ Subject: &bad.Range,
+ })
+ case TokenEOF:
+ switch end {
+ case TokenCBrace:
+ // If we're looking for a closing brace then we're parsing a block
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed configuration block",
+ Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.",
+ Subject: &startRange,
+ })
+ default:
+ // The only other "end" should itself be TokenEOF (for
+ // the top-level body) and so we shouldn't get here,
+ // but we'll return a generic error message anyway to
+ // be resilient.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed configuration body",
+ Detail: "Found end of file before the end of this configuration body.",
+ Subject: &startRange,
+ })
+ }
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Argument or block definition required",
+ Detail: "An argument or block definition is required here.",
+ Subject: &bad.Range,
+ })
+ }
+ }
+ endRange = p.PrevRange() // arbitrary, but somewhere inside the body means better diagnostics
+
+ p.recover(end) // attempt to recover to the token after the end of this body
+ break Token
+ }
+ }
+
+ return &Body{
+ Attributes: attrs,
+ Blocks: blocks,
+
+ SrcRange: hcl.RangeBetween(startRange, endRange),
+ EndRange: hcl.Range{
+ Filename: endRange.Filename,
+ Start: endRange.End,
+ End: endRange.End,
+ },
+ }, diags
+}
+
+func (p *parser) ParseBodyItem() (Node, hcl.Diagnostics) {
+ ident := p.Read()
+ if ident.Type != TokenIdent {
+ p.recoverAfterBodyItem()
+ return nil, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Argument or block definition required",
+ Detail: "An argument or block definition is required here.",
+ Subject: &ident.Range,
+ },
+ }
+ }
+
+ next := p.Peek()
+
+ switch next.Type {
+ case TokenEqual:
+ return p.finishParsingBodyAttribute(ident, false)
+ case TokenOQuote, TokenOBrace, TokenIdent:
+ return p.finishParsingBodyBlock(ident)
+ default:
+ p.recoverAfterBodyItem()
+ return nil, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Argument or block definition required",
+ Detail: "An argument or block definition is required here. To set an argument, use the equals sign \"=\" to introduce the argument value.",
+ Subject: &ident.Range,
+ },
+ }
+ }
+}
+
+// parseSingleAttrBody is a weird variant of ParseBody that deals with the
+// body of a nested block containing only one attribute value all on a single
+// line, like foo { bar = baz } . It expects to find a single attribute item
+// immediately followed by the end token type with no intervening newlines.
+func (p *parser) parseSingleAttrBody(end TokenType) (*Body, hcl.Diagnostics) {
+ ident := p.Read()
+ if ident.Type != TokenIdent {
+ p.recoverAfterBodyItem()
+ return nil, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Argument or block definition required",
+ Detail: "An argument or block definition is required here.",
+ Subject: &ident.Range,
+ },
+ }
+ }
+
+ var attr *Attribute
+ var diags hcl.Diagnostics
+
+ next := p.Peek()
+
+ switch next.Type {
+ case TokenEqual:
+ node, attrDiags := p.finishParsingBodyAttribute(ident, true)
+ diags = append(diags, attrDiags...)
+ attr = node.(*Attribute)
+ case TokenOQuote, TokenOBrace, TokenIdent:
+ p.recoverAfterBodyItem()
+ return nil, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Argument definition required",
+ Detail: fmt.Sprintf("A single-line block definition can contain only a single argument. If you meant to define argument %q, use an equals sign to assign it a value. To define a nested block, place it on a line of its own within its parent block.", ident.Bytes),
+ Subject: hcl.RangeBetween(ident.Range, next.Range).Ptr(),
+ },
+ }
+ default:
+ p.recoverAfterBodyItem()
+ return nil, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Argument or block definition required",
+ Detail: "An argument or block definition is required here. To set an argument, use the equals sign \"=\" to introduce the argument value.",
+ Subject: &ident.Range,
+ },
+ }
+ }
+
+ return &Body{
+ Attributes: Attributes{
+ string(ident.Bytes): attr,
+ },
+
+ SrcRange: attr.SrcRange,
+ EndRange: hcl.Range{
+ Filename: attr.SrcRange.Filename,
+ Start: attr.SrcRange.End,
+ End: attr.SrcRange.End,
+ },
+ }, diags
+
+}
+
+func (p *parser) finishParsingBodyAttribute(ident Token, singleLine bool) (Node, hcl.Diagnostics) {
+ eqTok := p.Read() // eat equals token
+ if eqTok.Type != TokenEqual {
+ // should never happen if caller behaves
+ panic("finishParsingBodyAttribute called with next not equals")
+ }
+
+ var endRange hcl.Range
+
+ expr, diags := p.ParseExpression()
+ if p.recovery && diags.HasErrors() {
+ // recovery within expressions tends to be tricky, so we've probably
+ // landed somewhere weird. We'll try to reset to the start of a body
+ // item so parsing can continue.
+ endRange = p.PrevRange()
+ p.recoverAfterBodyItem()
+ } else {
+ endRange = p.PrevRange()
+ if !singleLine {
+ end := p.Peek()
+ if end.Type != TokenNewline && end.Type != TokenEOF {
+ if !p.recovery {
+ summary := "Missing newline after argument"
+ detail := "An argument definition must end with a newline."
+
+ if end.Type == TokenComma {
+ summary = "Unexpected comma after argument"
+ detail = "Argument definitions must be separated by newlines, not commas. " + detail
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: summary,
+ Detail: detail,
+ Subject: &end.Range,
+ Context: hcl.RangeBetween(ident.Range, end.Range).Ptr(),
+ })
+ }
+ endRange = p.PrevRange()
+ p.recoverAfterBodyItem()
+ } else {
+ endRange = p.PrevRange()
+ p.Read() // eat newline
+ }
+ }
+ }
+
+ return &Attribute{
+ Name: string(ident.Bytes),
+ Expr: expr,
+
+ SrcRange: hcl.RangeBetween(ident.Range, endRange),
+ NameRange: ident.Range,
+ EqualsRange: eqTok.Range,
+ }, diags
+}
+
+func (p *parser) finishParsingBodyBlock(ident Token) (Node, hcl.Diagnostics) {
+ var blockType = string(ident.Bytes)
+ var diags hcl.Diagnostics
+ var labels []string
+ var labelRanges []hcl.Range
+
+ var oBrace Token
+
+Token:
+ for {
+ tok := p.Peek()
+
+ switch tok.Type {
+
+ case TokenOBrace:
+ oBrace = p.Read()
+ break Token
+
+ case TokenOQuote:
+ label, labelRange, labelDiags := p.parseQuotedStringLiteral()
+ diags = append(diags, labelDiags...)
+ labels = append(labels, label)
+ labelRanges = append(labelRanges, labelRange)
+ // parseQuoteStringLiteral recovers up to the closing quote
+ // if it encounters problems, so we can continue looking for
+ // more labels and eventually the block body even.
+
+ case TokenIdent:
+ tok = p.Read() // eat token
+ label, labelRange := string(tok.Bytes), tok.Range
+ labels = append(labels, label)
+ labelRanges = append(labelRanges, labelRange)
+
+ default:
+ switch tok.Type {
+ case TokenEqual:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid block definition",
+ Detail: "The equals sign \"=\" indicates an argument definition, and must not be used when defining a block.",
+ Subject: &tok.Range,
+ Context: hcl.RangeBetween(ident.Range, tok.Range).Ptr(),
+ })
+ case TokenNewline:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid block definition",
+ Detail: "A block definition must have block content delimited by \"{\" and \"}\", starting on the same line as the block header.",
+ Subject: &tok.Range,
+ Context: hcl.RangeBetween(ident.Range, tok.Range).Ptr(),
+ })
+ default:
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid block definition",
+ Detail: "Either a quoted string block label or an opening brace (\"{\") is expected here.",
+ Subject: &tok.Range,
+ Context: hcl.RangeBetween(ident.Range, tok.Range).Ptr(),
+ })
+ }
+ }
+
+ p.recoverAfterBodyItem()
+
+ return &Block{
+ Type: blockType,
+ Labels: labels,
+ Body: &Body{
+ SrcRange: ident.Range,
+ EndRange: ident.Range,
+ },
+
+ TypeRange: ident.Range,
+ LabelRanges: labelRanges,
+ OpenBraceRange: ident.Range, // placeholder
+ CloseBraceRange: ident.Range, // placeholder
+ }, diags
+ }
+ }
+
+ // Once we fall out here, the peeker is pointed just after our opening
+ // brace, so we can begin our nested body parsing.
+ var body *Body
+ var bodyDiags hcl.Diagnostics
+ switch p.Peek().Type {
+ case TokenNewline, TokenEOF, TokenCBrace:
+ body, bodyDiags = p.ParseBody(TokenCBrace)
+ default:
+ // Special one-line, single-attribute block parsing mode.
+ body, bodyDiags = p.parseSingleAttrBody(TokenCBrace)
+ switch p.Peek().Type {
+ case TokenCBrace:
+ p.Read() // the happy path - just consume the closing brace
+ case TokenComma:
+ // User seems to be trying to use the object-constructor
+ // comma-separated style, which isn't permitted for blocks.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid single-argument block definition",
+ Detail: "Single-line block syntax can include only one argument definition. To define multiple arguments, use the multi-line block syntax with one argument definition per line.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ p.recover(TokenCBrace)
+ case TokenNewline:
+ // We don't allow weird mixtures of single and multi-line syntax.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid single-argument block definition",
+ Detail: "An argument definition on the same line as its containing block creates a single-line block definition, which must also be closed on the same line. Place the block's closing brace immediately after the argument definition.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ p.recover(TokenCBrace)
+ default:
+ // Some other weird thing is going on. Since we can't guess a likely
+ // user intent for this one, we'll skip it if we're already in
+ // recovery mode.
+ if !p.recovery {
+ switch p.Peek().Type {
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed configuration block",
+ Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.",
+ Subject: oBrace.Range.Ptr(),
+ Context: hcl.RangeBetween(ident.Range, oBrace.Range).Ptr(),
+ })
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid single-argument block definition",
+ Detail: "A single-line block definition must end with a closing brace immediately after its single argument definition.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ }
+ }
+ p.recover(TokenCBrace)
+ }
+ }
+ diags = append(diags, bodyDiags...)
+ cBraceRange := p.PrevRange()
+
+ eol := p.Peek()
+ if eol.Type == TokenNewline || eol.Type == TokenEOF {
+ p.Read() // eat newline
+ } else {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing newline after block definition",
+ Detail: "A block definition must end with a newline.",
+ Subject: &eol.Range,
+ Context: hcl.RangeBetween(ident.Range, eol.Range).Ptr(),
+ })
+ }
+ p.recoverAfterBodyItem()
+ }
+
+ // We must never produce a nil body, since the caller may attempt to
+ // do analysis of a partial result when there's an error, so we'll
+ // insert a placeholder if we otherwise failed to produce a valid
+ // body due to one of the syntax error paths above.
+ if body == nil && diags.HasErrors() {
+ body = &Body{
+ SrcRange: hcl.RangeBetween(oBrace.Range, cBraceRange),
+ EndRange: cBraceRange,
+ }
+ }
+
+ return &Block{
+ Type: blockType,
+ Labels: labels,
+ Body: body,
+
+ TypeRange: ident.Range,
+ LabelRanges: labelRanges,
+ OpenBraceRange: oBrace.Range,
+ CloseBraceRange: cBraceRange,
+ }, diags
+}
+
+func (p *parser) ParseExpression() (Expression, hcl.Diagnostics) {
+ return p.parseTernaryConditional()
+}
+
+func (p *parser) parseTernaryConditional() (Expression, hcl.Diagnostics) {
+ // The ternary conditional operator (.. ? .. : ..) behaves somewhat
+ // like a binary operator except that the "symbol" is itself
+ // an expression enclosed in two punctuation characters.
+ // The middle expression is parsed as if the ? and : symbols
+ // were parentheses. The "rhs" (the "false expression") is then
+ // treated right-associatively so it behaves similarly to the
+ // middle in terms of precedence.
+
+ startRange := p.NextRange()
+ var condExpr, trueExpr, falseExpr Expression
+ var diags hcl.Diagnostics
+
+ condExpr, condDiags := p.parseBinaryOps(binaryOps)
+ diags = append(diags, condDiags...)
+ if p.recovery && condDiags.HasErrors() {
+ return condExpr, diags
+ }
+
+ questionMark := p.Peek()
+ if questionMark.Type != TokenQuestion {
+ return condExpr, diags
+ }
+
+ p.Read() // eat question mark
+
+ trueExpr, trueDiags := p.ParseExpression()
+ diags = append(diags, trueDiags...)
+ if p.recovery && trueDiags.HasErrors() {
+ return condExpr, diags
+ }
+
+ colon := p.Peek()
+ if colon.Type != TokenColon {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing false expression in conditional",
+ Detail: "The conditional operator (...?...:...) requires a false expression, delimited by a colon.",
+ Subject: &colon.Range,
+ Context: hcl.RangeBetween(startRange, colon.Range).Ptr(),
+ })
+ return condExpr, diags
+ }
+
+ p.Read() // eat colon
+
+ falseExpr, falseDiags := p.ParseExpression()
+ diags = append(diags, falseDiags...)
+ if p.recovery && falseDiags.HasErrors() {
+ return condExpr, diags
+ }
+
+ return &ConditionalExpr{
+ Condition: condExpr,
+ TrueResult: trueExpr,
+ FalseResult: falseExpr,
+
+ SrcRange: hcl.RangeBetween(startRange, falseExpr.Range()),
+ }, diags
+}
+
+// parseBinaryOps calls itself recursively to work through all of the
+// operator precedence groups, and then eventually calls parseExpressionTerm
+// for each operand.
+func (p *parser) parseBinaryOps(ops []map[TokenType]*Operation) (Expression, hcl.Diagnostics) {
+ if len(ops) == 0 {
+ // We've run out of operators, so now we'll just try to parse a term.
+ return p.parseExpressionWithTraversals()
+ }
+
+ thisLevel := ops[0]
+ remaining := ops[1:]
+
+ var lhs, rhs Expression
+ var operation *Operation
+ var diags hcl.Diagnostics
+
+ // Parse a term that might be the first operand of a binary
+ // operation or it might just be a standalone term.
+ // We won't know until we've parsed it and can look ahead
+ // to see if there's an operator token for this level.
+ lhs, lhsDiags := p.parseBinaryOps(remaining)
+ diags = append(diags, lhsDiags...)
+ if p.recovery && lhsDiags.HasErrors() {
+ return lhs, diags
+ }
+
+ // We'll keep eating up operators until we run out, so that operators
+ // with the same precedence will combine in a left-associative manner:
+ // a+b+c => (a+b)+c, not a+(b+c)
+ //
+ // Should we later want to have right-associative operators, a way
+ // to achieve that would be to call back up to ParseExpression here
+ // instead of iteratively parsing only the remaining operators.
+ for {
+ next := p.Peek()
+ var newOp *Operation
+ var ok bool
+ if newOp, ok = thisLevel[next.Type]; !ok {
+ break
+ }
+
+ // Are we extending an expression started on the previous iteration?
+ if operation != nil {
+ lhs = &BinaryOpExpr{
+ LHS: lhs,
+ Op: operation,
+ RHS: rhs,
+
+ SrcRange: hcl.RangeBetween(lhs.Range(), rhs.Range()),
+ }
+ }
+
+ operation = newOp
+ p.Read() // eat operator token
+ var rhsDiags hcl.Diagnostics
+ rhs, rhsDiags = p.parseBinaryOps(remaining)
+ diags = append(diags, rhsDiags...)
+ if p.recovery && rhsDiags.HasErrors() {
+ return lhs, diags
+ }
+ }
+
+ if operation == nil {
+ return lhs, diags
+ }
+
+ return &BinaryOpExpr{
+ LHS: lhs,
+ Op: operation,
+ RHS: rhs,
+
+ SrcRange: hcl.RangeBetween(lhs.Range(), rhs.Range()),
+ }, diags
+}
+
+func (p *parser) parseExpressionWithTraversals() (Expression, hcl.Diagnostics) {
+ term, diags := p.parseExpressionTerm()
+ ret, moreDiags := p.parseExpressionTraversals(term)
+ diags = append(diags, moreDiags...)
+ return ret, diags
+}
+
+func (p *parser) parseExpressionTraversals(from Expression) (Expression, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ ret := from
+
+Traversal:
+ for {
+ next := p.Peek()
+
+ switch next.Type {
+ case TokenDot:
+ // Attribute access or splat
+ dot := p.Read()
+ attrTok := p.Peek()
+
+ switch attrTok.Type {
+ case TokenIdent:
+ attrTok = p.Read() // eat token
+ name := string(attrTok.Bytes)
+ rng := hcl.RangeBetween(dot.Range, attrTok.Range)
+ step := hcl.TraverseAttr{
+ Name: name,
+ SrcRange: rng,
+ }
+
+ ret = makeRelativeTraversal(ret, step, rng)
+
+ case TokenNumberLit:
+ // This is a weird form we inherited from HIL, allowing numbers
+ // to be used as attributes as a weird way of writing [n].
+ // This was never actually a first-class thing in HIL, but
+ // HIL tolerated sequences like .0. in its variable names and
+ // calling applications like Terraform exploited that to
+ // introduce indexing syntax where none existed.
+ numTok := p.Read() // eat token
+ attrTok = numTok
+
+ // This syntax is ambiguous if multiple indices are used in
+ // succession, like foo.0.1.baz: that actually parses as
+ // a fractional number 0.1. Since we're only supporting this
+ // syntax for compatibility with legacy Terraform
+ // configurations, and Terraform does not tend to have lists
+ // of lists, we'll choose to reject that here with a helpful
+ // error message, rather than failing later because the index
+ // isn't a whole number.
+ if dotIdx := bytes.IndexByte(numTok.Bytes, '.'); dotIdx >= 0 {
+ first := numTok.Bytes[:dotIdx]
+ second := numTok.Bytes[dotIdx+1:]
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid legacy index syntax",
+ Detail: fmt.Sprintf("When using the legacy index syntax, chaining two indexes together is not permitted. Use the proper index syntax instead, like [%s][%s].", first, second),
+ Subject: &attrTok.Range,
+ })
+ rng := hcl.RangeBetween(dot.Range, numTok.Range)
+ step := hcl.TraverseIndex{
+ Key: cty.DynamicVal,
+ SrcRange: rng,
+ }
+ ret = makeRelativeTraversal(ret, step, rng)
+ break
+ }
+
+ numVal, numDiags := p.numberLitValue(numTok)
+ diags = append(diags, numDiags...)
+
+ rng := hcl.RangeBetween(dot.Range, numTok.Range)
+ step := hcl.TraverseIndex{
+ Key: numVal,
+ SrcRange: rng,
+ }
+
+ ret = makeRelativeTraversal(ret, step, rng)
+
+ case TokenStar:
+ // "Attribute-only" splat expression.
+ // (This is a kinda weird construct inherited from HIL, which
+ // behaves a bit like a [*] splat except that it is only able
+ // to do attribute traversals into each of its elements,
+ // whereas foo[*] can support _any_ traversal.
+ marker := p.Read() // eat star
+ trav := make(hcl.Traversal, 0, 1)
+ var firstRange, lastRange hcl.Range
+ firstRange = p.NextRange()
+ lastRange = marker.Range
+ for p.Peek().Type == TokenDot {
+ dot := p.Read()
+
+ if p.Peek().Type == TokenNumberLit {
+ // Continuing the "weird stuff inherited from HIL"
+ // theme, we also allow numbers as attribute names
+ // inside splats and interpret them as indexing
+ // into a list, for expressions like:
+ // foo.bar.*.baz.0.foo
+ numTok := p.Read()
+
+ // Weird special case if the user writes something
+ // like foo.bar.*.baz.0.0.foo, where 0.0 parses
+ // as a number.
+ if dotIdx := bytes.IndexByte(numTok.Bytes, '.'); dotIdx >= 0 {
+ first := numTok.Bytes[:dotIdx]
+ second := numTok.Bytes[dotIdx+1:]
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid legacy index syntax",
+ Detail: fmt.Sprintf("When using the legacy index syntax, chaining two indexes together is not permitted. Use the proper index syntax with a full splat expression [*] instead, like [%s][%s].", first, second),
+ Subject: &attrTok.Range,
+ })
+ trav = append(trav, hcl.TraverseIndex{
+ Key: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(dot.Range, numTok.Range),
+ })
+ lastRange = numTok.Range
+ continue
+ }
+
+ numVal, numDiags := p.numberLitValue(numTok)
+ diags = append(diags, numDiags...)
+ trav = append(trav, hcl.TraverseIndex{
+ Key: numVal,
+ SrcRange: hcl.RangeBetween(dot.Range, numTok.Range),
+ })
+ lastRange = numTok.Range
+ continue
+ }
+
+ if p.Peek().Type != TokenIdent {
+ if !p.recovery {
+ if p.Peek().Type == TokenStar {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Nested splat expression not allowed",
+ Detail: "A splat expression (*) cannot be used inside another attribute-only splat expression.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ } else {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid attribute name",
+ Detail: "An attribute name is required after a dot.",
+ Subject: &attrTok.Range,
+ })
+ }
+ }
+ p.setRecovery()
+ continue Traversal
+ }
+
+ attrTok := p.Read()
+ trav = append(trav, hcl.TraverseAttr{
+ Name: string(attrTok.Bytes),
+ SrcRange: hcl.RangeBetween(dot.Range, attrTok.Range),
+ })
+ lastRange = attrTok.Range
+ }
+
+ itemExpr := &AnonSymbolExpr{
+ SrcRange: hcl.RangeBetween(dot.Range, marker.Range),
+ }
+ var travExpr Expression
+ if len(trav) == 0 {
+ travExpr = itemExpr
+ } else {
+ travExpr = &RelativeTraversalExpr{
+ Source: itemExpr,
+ Traversal: trav,
+ SrcRange: hcl.RangeBetween(firstRange, lastRange),
+ }
+ }
+
+ ret = &SplatExpr{
+ Source: ret,
+ Each: travExpr,
+ Item: itemExpr,
+
+ SrcRange: hcl.RangeBetween(from.Range(), lastRange),
+ MarkerRange: hcl.RangeBetween(dot.Range, marker.Range),
+ }
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid attribute name",
+ Detail: "An attribute name is required after a dot.",
+ Subject: &attrTok.Range,
+ })
+ // This leaves the peeker in a bad place, so following items
+ // will probably be misparsed until we hit something that
+ // allows us to re-sync.
+ //
+ // Returning an ExprSyntaxError allows us to pass more information
+ // about the invalid expression to the caller, which can then
+ // use this for example for completions that happen after typing
+ // a dot in an editor.
+ ret = &ExprSyntaxError{
+ Placeholder: cty.DynamicVal,
+ ParseDiags: diags,
+ SrcRange: hcl.RangeBetween(from.Range(), dot.Range),
+ }
+
+ p.setRecovery()
+ }
+
+ case TokenOBrack:
+ // Indexing of a collection.
+ // This may or may not be a hcl.Traverser, depending on whether
+ // the key value is something constant.
+
+ open := p.Read()
+ switch p.Peek().Type {
+ case TokenStar:
+ // This is a full splat expression, like foo[*], which consumes
+ // the rest of the traversal steps after it using a recursive
+ // call to this function.
+ p.Read() // consume star
+ close := p.Read()
+ if close.Type != TokenCBrack && !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing close bracket on splat index",
+ Detail: "The star for a full splat operator must be immediately followed by a closing bracket (\"]\").",
+ Subject: &close.Range,
+ })
+ close = p.recover(TokenCBrack)
+ }
+ // Splat expressions use a special "anonymous symbol" as a
+ // placeholder in an expression to be evaluated once for each
+ // item in the source expression.
+ itemExpr := &AnonSymbolExpr{
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }
+ // Now we'll recursively call this same function to eat any
+ // remaining traversal steps against the anonymous symbol.
+ travExpr, nestedDiags := p.parseExpressionTraversals(itemExpr)
+ diags = append(diags, nestedDiags...)
+
+ ret = &SplatExpr{
+ Source: ret,
+ Each: travExpr,
+ Item: itemExpr,
+
+ SrcRange: hcl.RangeBetween(from.Range(), travExpr.Range()),
+ MarkerRange: hcl.RangeBetween(open.Range, close.Range),
+ }
+
+ default:
+
+ var close Token
+ p.PushIncludeNewlines(false) // arbitrary newlines allowed in brackets
+ keyExpr, keyDiags := p.ParseExpression()
+ diags = append(diags, keyDiags...)
+ if p.recovery && keyDiags.HasErrors() {
+ close = p.recover(TokenCBrack)
+ } else {
+ close = p.Read()
+ if close.Type != TokenCBrack && !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing close bracket on index",
+ Detail: "The index operator must end with a closing bracket (\"]\").",
+ Subject: &close.Range,
+ })
+ close = p.recover(TokenCBrack)
+ }
+ }
+ p.PopIncludeNewlines()
+
+ if lit, isLit := keyExpr.(*LiteralValueExpr); isLit {
+ litKey, _ := lit.Value(nil)
+ rng := hcl.RangeBetween(open.Range, close.Range)
+ step := hcl.TraverseIndex{
+ Key: litKey,
+ SrcRange: rng,
+ }
+ ret = makeRelativeTraversal(ret, step, rng)
+ } else if tmpl, isTmpl := keyExpr.(*TemplateExpr); isTmpl && tmpl.IsStringLiteral() {
+ litKey, _ := tmpl.Value(nil)
+ rng := hcl.RangeBetween(open.Range, close.Range)
+ step := hcl.TraverseIndex{
+ Key: litKey,
+ SrcRange: rng,
+ }
+ ret = makeRelativeTraversal(ret, step, rng)
+ } else {
+ rng := hcl.RangeBetween(open.Range, close.Range)
+ ret = &IndexExpr{
+ Collection: ret,
+ Key: keyExpr,
+
+ SrcRange: hcl.RangeBetween(from.Range(), rng),
+ OpenRange: open.Range,
+ BracketRange: rng,
+ }
+ }
+ }
+
+ default:
+ break Traversal
+ }
+ }
+
+ return ret, diags
+}
+
+// makeRelativeTraversal takes an expression and a traverser and returns
+// a traversal expression that combines the two. If the given expression
+// is already a traversal, it is extended in place (mutating it) and
+// returned. If it isn't, a new RelativeTraversalExpr is created and returned.
+func makeRelativeTraversal(expr Expression, next hcl.Traverser, rng hcl.Range) Expression {
+ switch texpr := expr.(type) {
+ case *ScopeTraversalExpr:
+ texpr.Traversal = append(texpr.Traversal, next)
+ texpr.SrcRange = hcl.RangeBetween(texpr.SrcRange, rng)
+ return texpr
+ case *RelativeTraversalExpr:
+ texpr.Traversal = append(texpr.Traversal, next)
+ texpr.SrcRange = hcl.RangeBetween(texpr.SrcRange, rng)
+ return texpr
+ default:
+ return &RelativeTraversalExpr{
+ Source: expr,
+ Traversal: hcl.Traversal{next},
+ SrcRange: hcl.RangeBetween(expr.Range(), rng),
+ }
+ }
+}
+
+func (p *parser) parseExpressionTerm() (Expression, hcl.Diagnostics) {
+ start := p.Peek()
+
+ switch start.Type {
+ case TokenOParen:
+ oParen := p.Read() // eat open paren
+
+ p.PushIncludeNewlines(false)
+
+ expr, diags := p.ParseExpression()
+ if diags.HasErrors() {
+ // attempt to place the peeker after our closing paren
+ // before we return, so that the next parser has some
+ // chance of finding a valid expression.
+ p.recover(TokenCParen)
+ p.PopIncludeNewlines()
+ return expr, diags
+ }
+
+ close := p.Peek()
+ if close.Type != TokenCParen {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unbalanced parentheses",
+ Detail: "Expected a closing parenthesis to terminate the expression.",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(start.Range, close.Range).Ptr(),
+ })
+ p.setRecovery()
+ }
+
+ cParen := p.Read() // eat closing paren
+ p.PopIncludeNewlines()
+
+ // Our parser's already taken care of the precedence effect of the
+ // parentheses by considering them to be a kind of "term", but we
+ // still need to include the parentheses in our AST so we can give
+ // an accurate representation of the source range that includes the
+ // open and closing parentheses.
+ expr = &ParenthesesExpr{
+ Expression: expr,
+ SrcRange: hcl.RangeBetween(oParen.Range, cParen.Range),
+ }
+
+ return expr, diags
+
+ case TokenNumberLit:
+ tok := p.Read() // eat number token
+
+ numVal, diags := p.numberLitValue(tok)
+ return &LiteralValueExpr{
+ Val: numVal,
+ SrcRange: tok.Range,
+ }, diags
+
+ case TokenIdent:
+ tok := p.Read() // eat identifier token
+
+ if p.Peek().Type == TokenOParen || p.Peek().Type == TokenDoubleColon {
+ return p.finishParsingFunctionCall(tok)
+ }
+
+ name := string(tok.Bytes)
+ switch name {
+ case "true":
+ return &LiteralValueExpr{
+ Val: cty.True,
+ SrcRange: tok.Range,
+ }, nil
+ case "false":
+ return &LiteralValueExpr{
+ Val: cty.False,
+ SrcRange: tok.Range,
+ }, nil
+ case "null":
+ return &LiteralValueExpr{
+ Val: cty.NullVal(cty.DynamicPseudoType),
+ SrcRange: tok.Range,
+ }, nil
+ default:
+ return &ScopeTraversalExpr{
+ Traversal: hcl.Traversal{
+ hcl.TraverseRoot{
+ Name: name,
+ SrcRange: tok.Range,
+ },
+ },
+ SrcRange: tok.Range,
+ }, nil
+ }
+
+ case TokenOQuote, TokenOHeredoc:
+ open := p.Read() // eat opening marker
+ closer := p.oppositeBracket(open.Type)
+ exprs, passthru, _, diags := p.parseTemplateInner(closer, tokenOpensFlushHeredoc(open))
+
+ closeRange := p.PrevRange()
+
+ if passthru {
+ if len(exprs) != 1 {
+ panic("passthru set with len(exprs) != 1")
+ }
+ return &TemplateWrapExpr{
+ Wrapped: exprs[0],
+ SrcRange: hcl.RangeBetween(open.Range, closeRange),
+ }, diags
+ }
+
+ return &TemplateExpr{
+ Parts: exprs,
+ SrcRange: hcl.RangeBetween(open.Range, closeRange),
+ }, diags
+
+ case TokenMinus:
+ tok := p.Read() // eat minus token
+
+ // Important to use parseExpressionWithTraversals rather than parseExpression
+ // here, otherwise we can capture a following binary expression into
+ // our negation.
+ // e.g. -46+5 should parse as (-46)+5, not -(46+5)
+ operand, diags := p.parseExpressionWithTraversals()
+ return &UnaryOpExpr{
+ Op: OpNegate,
+ Val: operand,
+
+ SrcRange: hcl.RangeBetween(tok.Range, operand.Range()),
+ SymbolRange: tok.Range,
+ }, diags
+
+ case TokenBang:
+ tok := p.Read() // eat bang token
+
+ // Important to use parseExpressionWithTraversals rather than parseExpression
+ // here, otherwise we can capture a following binary expression into
+ // our negation.
+ operand, diags := p.parseExpressionWithTraversals()
+ return &UnaryOpExpr{
+ Op: OpLogicalNot,
+ Val: operand,
+
+ SrcRange: hcl.RangeBetween(tok.Range, operand.Range()),
+ SymbolRange: tok.Range,
+ }, diags
+
+ case TokenOBrack:
+ return p.parseTupleCons()
+
+ case TokenOBrace:
+ return p.parseObjectCons()
+
+ default:
+ var diags hcl.Diagnostics
+ if !p.recovery {
+ switch start.Type {
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing expression",
+ Detail: "Expected the start of an expression, but found the end of the file.",
+ Subject: &start.Range,
+ })
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid expression",
+ Detail: "Expected the start of an expression, but found an invalid expression token.",
+ Subject: &start.Range,
+ })
+ }
+ }
+ p.setRecovery()
+
+ // Return a placeholder so that the AST is still structurally sound
+ // even in the presence of parse errors.
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: start.Range,
+ }, diags
+ }
+}
+
+func (p *parser) numberLitValue(tok Token) (cty.Value, hcl.Diagnostics) {
+ // The cty.ParseNumberVal is always the same behavior as converting a
+ // string to a number, ensuring we always interpret decimal numbers in
+ // the same way.
+ numVal, err := cty.ParseNumberVal(string(tok.Bytes))
+ if err != nil {
+ ret := cty.UnknownVal(cty.Number)
+ return ret, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Invalid number literal",
+ // FIXME: not a very good error message, but convert only
+ // gives us "a number is required", so not much help either.
+ Detail: "Failed to recognize the value of this number literal.",
+ Subject: &tok.Range,
+ },
+ }
+ }
+ return numVal, nil
+}
+
+// finishParsingFunctionCall parses a function call assuming that the function
+// name was already read, and so the peeker should be pointing at the opening
+// parenthesis after the name, or at the double-colon after the initial
+// function scope name.
+func (p *parser) finishParsingFunctionCall(name Token) (Expression, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ openTok := p.Read()
+ if openTok.Type != TokenOParen && openTok.Type != TokenDoubleColon {
+ // should never happen if callers behave
+ panic("finishParsingFunctionCall called with unsupported next token")
+ }
+
+ nameStr := string(name.Bytes)
+ nameEndPos := name.Range.End
+ for openTok.Type == TokenDoubleColon {
+ nextName := p.Read()
+ if nextName.Type != TokenIdent {
+ diag := hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing function name",
+ Detail: "Function scope resolution symbol :: must be followed by a function name in this scope.",
+ Subject: &nextName.Range,
+ Context: hcl.RangeBetween(name.Range, nextName.Range).Ptr(),
+ }
+ diags = append(diags, &diag)
+ p.recoverOver(TokenOParen)
+ return &ExprSyntaxError{
+ ParseDiags: hcl.Diagnostics{&diag},
+ Placeholder: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(name.Range, nextName.Range),
+ }, diags
+ }
+
+ // Initial versions of HCLv2 didn't support function namespaces, and
+ // so for backward compatibility we just treat namespaced functions
+ // as weird names with "::" separators in them, saved as a string
+ // to keep the API unchanged. FunctionCallExpr also has some special
+ // handling of names containing :: when referring to a function that
+ // doesn't exist in EvalContext, to return better error messages
+ // when namespaces are used incorrectly.
+ nameStr = nameStr + "::" + string(nextName.Bytes)
+ nameEndPos = nextName.Range.End
+
+ openTok = p.Read()
+ }
+
+ nameRange := hcl.Range{
+ Filename: name.Range.Filename,
+ Start: name.Range.Start,
+ End: nameEndPos,
+ }
+
+ if openTok.Type != TokenOParen {
+ diag := hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing open parenthesis",
+ Detail: "Function selector must be followed by an open parenthesis to begin the function call.",
+ Subject: &openTok.Range,
+ Context: hcl.RangeBetween(name.Range, openTok.Range).Ptr(),
+ }
+
+ diags = append(diags, &diag)
+ p.recoverOver(TokenOParen)
+ return &ExprSyntaxError{
+ ParseDiags: hcl.Diagnostics{&diag},
+ Placeholder: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(name.Range, openTok.Range),
+ }, diags
+ }
+
+ var args []Expression
+ var expandFinal bool
+ var closeTok Token
+
+ // Arbitrary newlines are allowed inside the function call parentheses.
+ p.PushIncludeNewlines(false)
+
+Token:
+ for {
+ tok := p.Peek()
+
+ if tok.Type == TokenCParen {
+ closeTok = p.Read() // eat closing paren
+ break Token
+ }
+
+ arg, argDiags := p.ParseExpression()
+ args = append(args, arg)
+ diags = append(diags, argDiags...)
+ if p.recovery && argDiags.HasErrors() {
+ // if there was a parse error in the argument then we've
+ // probably been left in a weird place in the token stream,
+ // so we'll bail out with a partial argument list.
+ recoveredTok := p.recover(TokenCParen)
+
+ // record the recovered token, if one was found
+ if recoveredTok.Type == TokenCParen {
+ closeTok = recoveredTok
+ }
+ break Token
+ }
+
+ sep := p.Read()
+ if sep.Type == TokenCParen {
+ closeTok = sep
+ break Token
+ }
+
+ if sep.Type == TokenEllipsis {
+ expandFinal = true
+
+ if p.Peek().Type != TokenCParen {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing closing parenthesis",
+ Detail: "An expanded function argument (with ...) must be immediately followed by closing parentheses.",
+ Subject: &sep.Range,
+ Context: hcl.RangeBetween(name.Range, sep.Range).Ptr(),
+ })
+ }
+ closeTok = p.recover(TokenCParen)
+ } else {
+ closeTok = p.Read() // eat closing paren
+ }
+ break Token
+ }
+
+ if sep.Type != TokenComma {
+ switch sep.Type {
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unterminated function call",
+ Detail: "There is no closing parenthesis for this function call before the end of the file. This may be caused by incorrect parenthesis nesting elsewhere in this file.",
+ Subject: hcl.RangeBetween(name.Range, openTok.Range).Ptr(),
+ })
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing argument separator",
+ Detail: "A comma is required to separate each function argument from the next.",
+ Subject: &sep.Range,
+ Context: hcl.RangeBetween(name.Range, sep.Range).Ptr(),
+ })
+ }
+ closeTok = p.recover(TokenCParen)
+ break Token
+ }
+
+ if p.Peek().Type == TokenCParen {
+ // A trailing comma after the last argument gets us in here.
+ closeTok = p.Read() // eat closing paren
+ break Token
+ }
+
+ }
+
+ p.PopIncludeNewlines()
+
+ return &FunctionCallExpr{
+ Name: nameStr,
+ Args: args,
+
+ ExpandFinal: expandFinal,
+
+ NameRange: nameRange,
+ OpenParenRange: openTok.Range,
+ CloseParenRange: closeTok.Range,
+ }, diags
+}
+
+func (p *parser) parseTupleCons() (Expression, hcl.Diagnostics) {
+ open := p.Read()
+ if open.Type != TokenOBrack {
+ // Should never happen if callers are behaving
+ panic("parseTupleCons called without peeker pointing to open bracket")
+ }
+
+ p.PushIncludeNewlines(false)
+ defer p.PopIncludeNewlines()
+
+ if forKeyword.TokenMatches(p.Peek()) {
+ return p.finishParsingForExpr(open)
+ }
+
+ var close Token
+
+ var diags hcl.Diagnostics
+ var exprs []Expression
+
+ for {
+ next := p.Peek()
+ if next.Type == TokenCBrack {
+ close = p.Read() // eat closer
+ break
+ }
+
+ expr, exprDiags := p.ParseExpression()
+ exprs = append(exprs, expr)
+ diags = append(diags, exprDiags...)
+
+ if p.recovery && exprDiags.HasErrors() {
+ // If expression parsing failed then we are probably in a strange
+ // place in the token stream, so we'll bail out and try to reset
+ // to after our closing bracket to allow parsing to continue.
+ close = p.recover(TokenCBrack)
+ break
+ }
+
+ next = p.Peek()
+ if next.Type == TokenCBrack {
+ close = p.Read() // eat closer
+ break
+ }
+
+ if next.Type != TokenComma {
+ if !p.recovery {
+ switch next.Type {
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unterminated tuple constructor expression",
+ Detail: "There is no corresponding closing bracket before the end of the file. This may be caused by incorrect bracket nesting elsewhere in this file.",
+ Subject: open.Range.Ptr(),
+ })
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing item separator",
+ Detail: "Expected a comma to mark the beginning of the next item.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
+ })
+ }
+ }
+ close = p.recover(TokenCBrack)
+ break
+ }
+
+ p.Read() // eat comma
+
+ }
+
+ return &TupleConsExpr{
+ Exprs: exprs,
+
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ OpenRange: open.Range,
+ }, diags
+}
+
+func (p *parser) parseObjectCons() (Expression, hcl.Diagnostics) {
+ open := p.Read()
+ if open.Type != TokenOBrace {
+ // Should never happen if callers are behaving
+ panic("parseObjectCons called without peeker pointing to open brace")
+ }
+
+ // We must temporarily stop looking at newlines here while we check for
+ // a "for" keyword, since for expressions are _not_ newline-sensitive,
+ // even though object constructors are.
+ p.PushIncludeNewlines(false)
+ isFor := forKeyword.TokenMatches(p.Peek())
+ p.PopIncludeNewlines()
+ if isFor {
+ return p.finishParsingForExpr(open)
+ }
+
+ p.PushIncludeNewlines(true)
+ defer p.PopIncludeNewlines()
+
+ var close Token
+
+ var diags hcl.Diagnostics
+ var items []ObjectConsItem
+
+ for {
+ next := p.Peek()
+ if next.Type == TokenNewline {
+ p.Read() // eat newline
+ continue
+ }
+
+ if next.Type == TokenCBrace {
+ close = p.Read() // eat closer
+ break
+ }
+
+ // Wrapping parens are not explicitly represented in the AST, but
+ // we want to use them here to disambiguate intepreting a mapping
+ // key as a full expression rather than just a name, and so
+ // we'll remember this was present and use it to force the
+ // behavior of our final ObjectConsKeyExpr.
+ forceNonLiteral := (p.Peek().Type == TokenOParen)
+
+ var key Expression
+ var keyDiags hcl.Diagnostics
+ key, keyDiags = p.ParseExpression()
+ diags = append(diags, keyDiags...)
+
+ if p.recovery && keyDiags.HasErrors() {
+ // If expression parsing failed then we are probably in a strange
+ // place in the token stream, so we'll bail out and try to reset
+ // to after our closing brace to allow parsing to continue.
+ close = p.recover(TokenCBrace)
+ break
+ }
+
+ // We wrap up the key expression in a special wrapper that deals
+ // with our special case that naked identifiers as object keys
+ // are interpreted as literal strings.
+ key = &ObjectConsKeyExpr{
+ Wrapped: key,
+ ForceNonLiteral: forceNonLiteral,
+ }
+
+ next = p.Peek()
+ if next.Type != TokenEqual && next.Type != TokenColon {
+ if !p.recovery {
+ switch next.Type {
+ case TokenNewline, TokenComma:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing attribute value",
+ Detail: "Expected an attribute value, introduced by an equals sign (\"=\").",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
+ })
+ case TokenIdent:
+ // Although this might just be a plain old missing equals
+ // sign before a reference, one way to get here is to try
+ // to write an attribute name containing a period followed
+ // by a digit, which was valid in HCL1, like this:
+ // foo1.2_bar = "baz"
+ // We can't know exactly what the user intended here, but
+ // we'll augment our message with an extra hint in this case
+ // in case it is helpful.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing key/value separator",
+ Detail: "Expected an equals sign (\"=\") to mark the beginning of the attribute value. If you intended to given an attribute name containing periods or spaces, write the name in quotes to create a string literal.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
+ })
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unterminated object constructor expression",
+ Detail: "There is no corresponding closing brace before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.",
+ Subject: open.Range.Ptr(),
+ })
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing key/value separator",
+ Detail: "Expected an equals sign (\"=\") to mark the beginning of the attribute value.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
+ })
+ }
+ }
+ close = p.recover(TokenCBrace)
+ break
+ }
+
+ p.Read() // eat equals sign or colon
+
+ value, valueDiags := p.ParseExpression()
+ diags = append(diags, valueDiags...)
+
+ if p.recovery && valueDiags.HasErrors() {
+ // If the value is an ExprSyntaxError, we can add an item with it, even though we will recover afterwards
+ // This allows downstream consumers to still retrieve this first invalid item, even though following items
+ // won't be parsed. This is useful for supplying completions.
+ if exprSyntaxError, ok := value.(*ExprSyntaxError); ok {
+ items = append(items, ObjectConsItem{
+ KeyExpr: key,
+ ValueExpr: exprSyntaxError,
+ })
+ }
+
+ // If expression parsing failed then we are probably in a strange
+ // place in the token stream, so we'll bail out and try to reset
+ // to after our closing brace to allow parsing to continue.
+ close = p.recover(TokenCBrace)
+ break
+ }
+
+ items = append(items, ObjectConsItem{
+ KeyExpr: key,
+ ValueExpr: value,
+ })
+
+ next = p.Peek()
+ if next.Type == TokenCBrace {
+ close = p.Read() // eat closer
+ break
+ }
+
+ if next.Type != TokenComma && next.Type != TokenNewline {
+ if !p.recovery {
+ switch next.Type {
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unterminated object constructor expression",
+ Detail: "There is no corresponding closing brace before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.",
+ Subject: open.Range.Ptr(),
+ })
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing attribute separator",
+ Detail: "Expected a newline or comma to mark the beginning of the next attribute.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
+ })
+ }
+ }
+ close = p.recover(TokenCBrace)
+ break
+ }
+
+ p.Read() // eat comma or newline
+
+ }
+
+ return &ObjectConsExpr{
+ Items: items,
+
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ OpenRange: open.Range,
+ }, diags
+}
+
+func (p *parser) finishParsingForExpr(open Token) (Expression, hcl.Diagnostics) {
+ p.PushIncludeNewlines(false)
+ defer p.PopIncludeNewlines()
+ introducer := p.Read()
+ if !forKeyword.TokenMatches(introducer) {
+ // Should never happen if callers are behaving
+ panic("finishParsingForExpr called without peeker pointing to 'for' identifier")
+ }
+
+ var makeObj bool
+ var closeType TokenType
+ switch open.Type {
+ case TokenOBrace:
+ makeObj = true
+ closeType = TokenCBrace
+ case TokenOBrack:
+ makeObj = false // making a tuple
+ closeType = TokenCBrack
+ default:
+ // Should never happen if callers are behaving
+ panic("finishParsingForExpr called with invalid open token")
+ }
+
+ var diags hcl.Diagnostics
+ var keyName, valName string
+
+ if p.Peek().Type != TokenIdent {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "For expression requires variable name after 'for'.",
+ Subject: p.Peek().Range.Ptr(),
+ Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
+ })
+ }
+ close := p.recover(closeType)
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+
+ valName = string(p.Read().Bytes)
+
+ if p.Peek().Type == TokenComma {
+ // What we just read was actually the key, then.
+ keyName = valName
+ p.Read() // eat comma
+
+ if p.Peek().Type != TokenIdent {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "For expression requires value variable name after comma.",
+ Subject: p.Peek().Range.Ptr(),
+ Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
+ })
+ }
+ close := p.recover(closeType)
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+
+ valName = string(p.Read().Bytes)
+ }
+
+ if !inKeyword.TokenMatches(p.Peek()) {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "For expression requires the 'in' keyword after its name declarations.",
+ Subject: p.Peek().Range.Ptr(),
+ Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
+ })
+ }
+ close := p.recover(closeType)
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+ p.Read() // eat 'in' keyword
+
+ collExpr, collDiags := p.ParseExpression()
+ diags = append(diags, collDiags...)
+ if p.recovery && collDiags.HasErrors() {
+ close := p.recover(closeType)
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+
+ if p.Peek().Type != TokenColon {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "For expression requires a colon after the collection expression.",
+ Subject: p.Peek().Range.Ptr(),
+ Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
+ })
+ }
+ close := p.recover(closeType)
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+ p.Read() // eat colon
+
+ var keyExpr, valExpr Expression
+ var keyDiags, valDiags hcl.Diagnostics
+ valExpr, valDiags = p.ParseExpression()
+ if p.Peek().Type == TokenFatArrow {
+ // What we just parsed was actually keyExpr
+ p.Read() // eat the fat arrow
+ keyExpr, keyDiags = valExpr, valDiags
+
+ valExpr, valDiags = p.ParseExpression()
+ }
+ diags = append(diags, keyDiags...)
+ diags = append(diags, valDiags...)
+ if p.recovery && (keyDiags.HasErrors() || valDiags.HasErrors()) {
+ close := p.recover(closeType)
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+
+ group := false
+ var ellipsis Token
+ if p.Peek().Type == TokenEllipsis {
+ ellipsis = p.Read()
+ group = true
+ }
+
+ var condExpr Expression
+ var condDiags hcl.Diagnostics
+ if ifKeyword.TokenMatches(p.Peek()) {
+ p.Read() // eat "if"
+ condExpr, condDiags = p.ParseExpression()
+ diags = append(diags, condDiags...)
+ if p.recovery && condDiags.HasErrors() {
+ close := p.recover(p.oppositeBracket(open.Type))
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ }, diags
+ }
+ }
+
+ var close Token
+ if p.Peek().Type == closeType {
+ close = p.Read()
+ } else {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "Extra characters after the end of the 'for' expression.",
+ Subject: p.Peek().Range.Ptr(),
+ Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
+ })
+ }
+ close = p.recover(closeType)
+ }
+
+ if !makeObj {
+ if keyExpr != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "Key expression is not valid when building a tuple.",
+ Subject: keyExpr.Range().Ptr(),
+ Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
+ })
+ }
+
+ if group {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "Grouping ellipsis (...) cannot be used when building a tuple.",
+ Subject: &ellipsis.Range,
+ Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
+ })
+ }
+ } else {
+ if keyExpr == nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' expression",
+ Detail: "Key expression is required when building an object.",
+ Subject: valExpr.Range().Ptr(),
+ Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
+ })
+ }
+ }
+
+ return &ForExpr{
+ KeyVar: keyName,
+ ValVar: valName,
+ CollExpr: collExpr,
+ KeyExpr: keyExpr,
+ ValExpr: valExpr,
+ CondExpr: condExpr,
+ Group: group,
+
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ OpenRange: open.Range,
+ CloseRange: close.Range,
+ }, diags
+}
+
+// parseQuotedStringLiteral is a helper for parsing quoted strings that
+// aren't allowed to contain any interpolations, such as block labels.
+func (p *parser) parseQuotedStringLiteral() (string, hcl.Range, hcl.Diagnostics) {
+ oQuote := p.Read()
+ if oQuote.Type != TokenOQuote {
+ return "", oQuote.Range, hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: "Invalid string literal",
+ Detail: "A quoted string is required here.",
+ Subject: &oQuote.Range,
+ },
+ }
+ }
+
+ var diags hcl.Diagnostics
+ ret := &bytes.Buffer{}
+ var endRange hcl.Range
+
+Token:
+ for {
+ tok := p.Read()
+ switch tok.Type {
+
+ case TokenCQuote:
+ endRange = tok.Range
+ break Token
+
+ case TokenQuotedLit:
+ s, sDiags := ParseStringLiteralToken(tok)
+ diags = append(diags, sDiags...)
+ ret.WriteString(s)
+
+ case TokenTemplateControl, TokenTemplateInterp:
+ which := "$"
+ if tok.Type == TokenTemplateControl {
+ which = "%"
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid string literal",
+ Detail: fmt.Sprintf(
+ "Template sequences are not allowed in this string. To include a literal %q, double it (as \"%s%s\") to escape it.",
+ which, which, which,
+ ),
+ Subject: &tok.Range,
+ Context: hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),
+ })
+
+ // Now that we're returning an error callers won't attempt to use
+ // the result for any real operations, but they might try to use
+ // the partial AST for other analyses, so we'll leave a marker
+ // to indicate that there was something invalid in the string to
+ // help avoid misinterpretation of the partial result
+ ret.WriteString(which)
+ ret.WriteString("{ ... }")
+
+ p.recover(TokenTemplateSeqEnd) // we'll try to keep parsing after the sequence ends
+
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unterminated string literal",
+ Detail: "Unable to find the closing quote mark before the end of the file.",
+ Subject: &tok.Range,
+ Context: hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),
+ })
+ endRange = tok.Range
+ break Token
+
+ default:
+ // Should never happen, as long as the scanner is behaving itself
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid string literal",
+ Detail: "This item is not valid in a string literal.",
+ Subject: &tok.Range,
+ Context: hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),
+ })
+ p.recover(TokenCQuote)
+ endRange = tok.Range
+ break Token
+
+ }
+
+ }
+
+ return ret.String(), hcl.RangeBetween(oQuote.Range, endRange), diags
+}
+
+// ParseStringLiteralToken processes the given token, which must be either a
+// TokenQuotedLit or a TokenStringLit, returning the string resulting from
+// resolving any escape sequences.
+//
+// If any error diagnostics are returned, the returned string may be incomplete
+// or otherwise invalid.
+func ParseStringLiteralToken(tok Token) (string, hcl.Diagnostics) {
+ var quoted bool
+ switch tok.Type {
+ case TokenQuotedLit:
+ quoted = true
+ case TokenStringLit:
+ quoted = false
+ default:
+ panic("ParseStringLiteralToken can only be used with TokenStringLit and TokenQuotedLit tokens")
+ }
+ var diags hcl.Diagnostics
+
+ ret := make([]byte, 0, len(tok.Bytes))
+ slices := scanStringLit(tok.Bytes, quoted)
+
+ // We will mutate rng constantly as we walk through our token slices below.
+ // Any diagnostics must take a copy of this rng rather than simply pointing
+ // to it, e.g. by using rng.Ptr() rather than &rng.
+ rng := tok.Range
+ rng.End = rng.Start
+
+Slices:
+ for _, slice := range slices {
+ if len(slice) == 0 {
+ continue
+ }
+
+ // Advance the start of our range to where the previous token ended
+ rng.Start = rng.End
+
+ // Advance the end of our range to after our token.
+ b := slice
+ for len(b) > 0 {
+ adv, ch, _ := textseg.ScanGraphemeClusters(b, true)
+ rng.End.Byte += adv
+ switch ch[0] {
+ case '\r', '\n':
+ rng.End.Line++
+ rng.End.Column = 1
+ default:
+ rng.End.Column++
+ }
+ b = b[adv:]
+ }
+
+ TokenType:
+ switch slice[0] {
+ case '\\':
+ if !quoted {
+ // If we're not in quoted mode then just treat this token as
+ // normal. (Slices can still start with backslash even if we're
+ // not specifically looking for backslash sequences.)
+ break TokenType
+ }
+ if len(slice) < 2 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid escape sequence",
+ Detail: "Backslash must be followed by an escape sequence selector character.",
+ Subject: rng.Ptr(),
+ })
+ break TokenType
+ }
+
+ switch slice[1] {
+
+ case 'n':
+ ret = append(ret, '\n')
+ continue Slices
+ case 'r':
+ ret = append(ret, '\r')
+ continue Slices
+ case 't':
+ ret = append(ret, '\t')
+ continue Slices
+ case '"':
+ ret = append(ret, '"')
+ continue Slices
+ case '\\':
+ ret = append(ret, '\\')
+ continue Slices
+ case 'u', 'U':
+ if slice[1] == 'u' && len(slice) != 6 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid escape sequence",
+ Detail: "The \\u escape sequence must be followed by four hexadecimal digits.",
+ Subject: rng.Ptr(),
+ })
+ break TokenType
+ } else if slice[1] == 'U' && len(slice) != 10 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid escape sequence",
+ Detail: "The \\U escape sequence must be followed by eight hexadecimal digits.",
+ Subject: rng.Ptr(),
+ })
+ break TokenType
+ }
+
+ numHex := string(slice[2:])
+ num, err := strconv.ParseUint(numHex, 16, 32)
+ if err != nil {
+ // Should never happen because the scanner won't match
+ // a sequence of digits that isn't valid.
+ panic(err)
+ }
+
+ r := rune(num)
+ l := utf8.RuneLen(r)
+ if l == -1 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid escape sequence",
+ Detail: fmt.Sprintf("Cannot encode character U+%04x in UTF-8.", num),
+ Subject: rng.Ptr(),
+ })
+ break TokenType
+ }
+ for i := 0; i < l; i++ {
+ ret = append(ret, 0)
+ }
+ rb := ret[len(ret)-l:]
+ utf8.EncodeRune(rb, r)
+
+ continue Slices
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid escape sequence",
+ Detail: fmt.Sprintf("The symbol %q is not a valid escape sequence selector.", slice[1:]),
+ Subject: rng.Ptr(),
+ })
+ ret = append(ret, slice[1:]...)
+ continue Slices
+ }
+
+ case '$', '%':
+ if len(slice) != 3 {
+ // Not long enough to be our escape sequence, so it's literal.
+ break TokenType
+ }
+
+ if slice[1] == slice[0] && slice[2] == '{' {
+ ret = append(ret, slice[0])
+ ret = append(ret, '{')
+ continue Slices
+ }
+
+ break TokenType
+ }
+
+ // If we fall out here or break out of here from the switch above
+ // then this slice is just a literal.
+ ret = append(ret, slice...)
+ }
+
+ return string(ret), diags
+}
+
+// setRecovery turns on recovery mode without actually doing any recovery.
+// This can be used when a parser knowingly leaves the peeker in a useless
+// place and wants to suppress errors that might result from that decision.
+func (p *parser) setRecovery() {
+ p.recovery = true
+}
+
+// recover seeks forward in the token stream until it finds TokenType "end",
+// then returns with the peeker pointed at the following token.
+//
+// If the given token type is a bracketer, this function will additionally
+// count nested instances of the brackets to try to leave the peeker at
+// the end of the _current_ instance of that bracketer, skipping over any
+// nested instances. This is a best-effort operation and may have
+// unpredictable results on input with bad bracketer nesting.
+func (p *parser) recover(end TokenType) Token {
+ start := p.oppositeBracket(end)
+ p.recovery = true
+
+ nest := 0
+ for {
+ tok := p.Read()
+ ty := tok.Type
+ if end == TokenTemplateSeqEnd && ty == TokenTemplateControl {
+ // normalize so that our matching behavior can work, since
+ // TokenTemplateControl/TokenTemplateInterp are asymmetrical
+ // with TokenTemplateSeqEnd and thus we need to count both
+ // openers if that's the closer we're looking for.
+ ty = TokenTemplateInterp
+ }
+
+ switch ty {
+ case start:
+ nest++
+ case end:
+ if nest < 1 {
+ return tok
+ }
+
+ nest--
+ case TokenEOF:
+ return tok
+ }
+ }
+}
+
+// recoverOver seeks forward in the token stream until it finds a block
+// starting with TokenType "start", then finds the corresponding end token,
+// leaving the peeker pointed at the token after that end token.
+//
+// The given token type _must_ be a bracketer. For example, if the given
+// start token is TokenOBrace then the parser will be left at the _end_ of
+// the next brace-delimited block encountered, or at EOF if no such block
+// is found or it is unclosed.
+func (p *parser) recoverOver(start TokenType) {
+ end := p.oppositeBracket(start)
+
+ // find the opening bracket first
+Token:
+ for {
+ tok := p.Read()
+ switch tok.Type {
+ case start, TokenEOF:
+ break Token
+ }
+ }
+
+ // Now use our existing recover function to locate the _end_ of the
+ // container we've found.
+ p.recover(end)
+}
+
+func (p *parser) recoverAfterBodyItem() {
+ p.recovery = true
+ var open []TokenType
+
+Token:
+ for {
+ tok := p.Read()
+
+ switch tok.Type {
+
+ case TokenNewline:
+ if len(open) == 0 {
+ break Token
+ }
+
+ case TokenEOF:
+ break Token
+
+ case TokenOBrace, TokenOBrack, TokenOParen, TokenOQuote, TokenOHeredoc, TokenTemplateInterp, TokenTemplateControl:
+ open = append(open, tok.Type)
+
+ case TokenCBrace, TokenCBrack, TokenCParen, TokenCQuote, TokenCHeredoc:
+ opener := p.oppositeBracket(tok.Type)
+ for len(open) > 0 && open[len(open)-1] != opener {
+ open = open[:len(open)-1]
+ }
+ if len(open) > 0 {
+ open = open[:len(open)-1]
+ }
+
+ case TokenTemplateSeqEnd:
+ for len(open) > 0 && open[len(open)-1] != TokenTemplateInterp && open[len(open)-1] != TokenTemplateControl {
+ open = open[:len(open)-1]
+ }
+ if len(open) > 0 {
+ open = open[:len(open)-1]
+ }
+
+ }
+ }
+}
+
+// oppositeBracket finds the bracket that opposes the given bracketer, or
+// NilToken if the given token isn't a bracketer.
+//
+// "Bracketer", for the sake of this function, is one end of a matching
+// open/close set of tokens that establish a bracketing context.
+func (p *parser) oppositeBracket(ty TokenType) TokenType {
+ switch ty {
+
+ case TokenOBrace:
+ return TokenCBrace
+ case TokenOBrack:
+ return TokenCBrack
+ case TokenOParen:
+ return TokenCParen
+ case TokenOQuote:
+ return TokenCQuote
+ case TokenOHeredoc:
+ return TokenCHeredoc
+
+ case TokenCBrace:
+ return TokenOBrace
+ case TokenCBrack:
+ return TokenOBrack
+ case TokenCParen:
+ return TokenOParen
+ case TokenCQuote:
+ return TokenOQuote
+ case TokenCHeredoc:
+ return TokenOHeredoc
+
+ case TokenTemplateControl:
+ return TokenTemplateSeqEnd
+ case TokenTemplateInterp:
+ return TokenTemplateSeqEnd
+ case TokenTemplateSeqEnd:
+ // This is ambigous, but we return Interp here because that's
+ // what's assumed by the "recover" method.
+ return TokenTemplateInterp
+
+ default:
+ return TokenNil
+ }
+}
+
+func errPlaceholderExpr(rng hcl.Range) Expression {
+ return &LiteralValueExpr{
+ Val: cty.DynamicVal,
+ SrcRange: rng,
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_template.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_template.go
new file mode 100644
index 00000000000..19e988064d8
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_template.go
@@ -0,0 +1,865 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "fmt"
+ "strings"
+ "unicode"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func (p *parser) ParseTemplate() (Expression, hcl.Diagnostics) {
+ return p.parseTemplate(TokenEOF, false)
+}
+
+func (p *parser) parseTemplate(end TokenType, flushHeredoc bool) (Expression, hcl.Diagnostics) {
+ exprs, passthru, rng, diags := p.parseTemplateInner(end, flushHeredoc)
+
+ if passthru {
+ if len(exprs) != 1 {
+ panic("passthru set with len(exprs) != 1")
+ }
+ return &TemplateWrapExpr{
+ Wrapped: exprs[0],
+ SrcRange: rng,
+ }, diags
+ }
+
+ return &TemplateExpr{
+ Parts: exprs,
+ SrcRange: rng,
+ }, diags
+}
+
+func (p *parser) parseTemplateInner(end TokenType, flushHeredoc bool) ([]Expression, bool, hcl.Range, hcl.Diagnostics) {
+ parts, diags := p.parseTemplateParts(end)
+ if flushHeredoc {
+ flushHeredocTemplateParts(parts) // Trim off leading spaces on lines per the flush heredoc spec
+ }
+ meldConsecutiveStringLiterals(parts)
+ tp := templateParser{
+ Tokens: parts.Tokens,
+ SrcRange: parts.SrcRange,
+ }
+ exprs, exprsDiags := tp.parseRoot()
+ diags = append(diags, exprsDiags...)
+
+ passthru := false
+ if len(parts.Tokens) == 2 { // one real token and one synthetic "end" token
+ if _, isInterp := parts.Tokens[0].(*templateInterpToken); isInterp {
+ passthru = true
+ }
+ }
+
+ return exprs, passthru, parts.SrcRange, diags
+}
+
+type templateParser struct {
+ Tokens []templateToken
+ SrcRange hcl.Range
+
+ pos int
+}
+
+func (p *templateParser) parseRoot() ([]Expression, hcl.Diagnostics) {
+ var exprs []Expression
+ var diags hcl.Diagnostics
+
+ for {
+ next := p.Peek()
+ if _, isEnd := next.(*templateEndToken); isEnd {
+ break
+ }
+
+ expr, exprDiags := p.parseExpr()
+ diags = append(diags, exprDiags...)
+ exprs = append(exprs, expr)
+ }
+
+ return exprs, diags
+}
+
+func (p *templateParser) parseExpr() (Expression, hcl.Diagnostics) {
+ next := p.Peek()
+ switch tok := next.(type) {
+
+ case *templateLiteralToken:
+ p.Read() // eat literal
+ return &LiteralValueExpr{
+ Val: cty.StringVal(tok.Val),
+ SrcRange: tok.SrcRange,
+ }, nil
+
+ case *templateInterpToken:
+ p.Read() // eat interp
+ return tok.Expr, nil
+
+ case *templateIfToken:
+ return p.parseIf()
+
+ case *templateForToken:
+ return p.parseFor()
+
+ case *templateEndToken:
+ p.Read() // eat erroneous token
+ return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{
+ {
+ // This is a particularly unhelpful diagnostic, so callers
+ // should attempt to pre-empt it and produce a more helpful
+ // diagnostic that is context-aware.
+ Severity: hcl.DiagError,
+ Summary: "Unexpected end of template",
+ Detail: "The control directives within this template are unbalanced.",
+ Subject: &tok.SrcRange,
+ },
+ }
+
+ case *templateEndCtrlToken:
+ p.Read() // eat erroneous token
+ return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{
+ {
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Unexpected %s directive", tok.Name()),
+ Detail: "The control directives within this template are unbalanced.",
+ Subject: &tok.SrcRange,
+ },
+ }
+
+ default:
+ // should never happen, because above should be exhaustive
+ panic(fmt.Sprintf("unhandled template token type %T", next))
+ }
+}
+
+func (p *templateParser) parseIf() (Expression, hcl.Diagnostics) {
+ open := p.Read()
+ openIf, isIf := open.(*templateIfToken)
+ if !isIf {
+ // should never happen if caller is behaving
+ panic("parseIf called with peeker not pointing at if token")
+ }
+
+ var ifExprs, elseExprs []Expression
+ var diags hcl.Diagnostics
+ var endifRange hcl.Range
+
+ currentExprs := &ifExprs
+Token:
+ for {
+ next := p.Peek()
+ if end, isEnd := next.(*templateEndToken); isEnd {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unexpected end of template",
+ Detail: fmt.Sprintf(
+ "The if directive at %s is missing its corresponding endif directive.",
+ openIf.SrcRange,
+ ),
+ Subject: &end.SrcRange,
+ })
+ return errPlaceholderExpr(end.SrcRange), diags
+ }
+ if end, isCtrlEnd := next.(*templateEndCtrlToken); isCtrlEnd {
+ p.Read() // eat end directive
+
+ switch end.Type {
+
+ case templateElse:
+ if currentExprs == &ifExprs {
+ currentExprs = &elseExprs
+ continue Token
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unexpected else directive",
+ Detail: fmt.Sprintf(
+ "Already in the else clause for the if started at %s.",
+ openIf.SrcRange,
+ ),
+ Subject: &end.SrcRange,
+ })
+
+ case templateEndIf:
+ endifRange = end.SrcRange
+ break Token
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Unexpected %s directive", end.Name()),
+ Detail: fmt.Sprintf(
+ "Expecting an endif directive for the if started at %s.",
+ openIf.SrcRange,
+ ),
+ Subject: &end.SrcRange,
+ })
+ }
+
+ return errPlaceholderExpr(end.SrcRange), diags
+ }
+
+ expr, exprDiags := p.parseExpr()
+ diags = append(diags, exprDiags...)
+ *currentExprs = append(*currentExprs, expr)
+ }
+
+ if len(ifExprs) == 0 {
+ ifExprs = append(ifExprs, &LiteralValueExpr{
+ Val: cty.StringVal(""),
+ SrcRange: hcl.Range{
+ Filename: openIf.SrcRange.Filename,
+ Start: openIf.SrcRange.End,
+ End: openIf.SrcRange.End,
+ },
+ })
+ }
+ if len(elseExprs) == 0 {
+ elseExprs = append(elseExprs, &LiteralValueExpr{
+ Val: cty.StringVal(""),
+ SrcRange: hcl.Range{
+ Filename: endifRange.Filename,
+ Start: endifRange.Start,
+ End: endifRange.Start,
+ },
+ })
+ }
+
+ trueExpr := &TemplateExpr{
+ Parts: ifExprs,
+ SrcRange: hcl.RangeBetween(ifExprs[0].Range(), ifExprs[len(ifExprs)-1].Range()),
+ }
+ falseExpr := &TemplateExpr{
+ Parts: elseExprs,
+ SrcRange: hcl.RangeBetween(elseExprs[0].Range(), elseExprs[len(elseExprs)-1].Range()),
+ }
+
+ return &ConditionalExpr{
+ Condition: openIf.CondExpr,
+ TrueResult: trueExpr,
+ FalseResult: falseExpr,
+
+ SrcRange: hcl.RangeBetween(openIf.SrcRange, endifRange),
+ }, diags
+}
+
+func (p *templateParser) parseFor() (Expression, hcl.Diagnostics) {
+ open := p.Read()
+ openFor, isFor := open.(*templateForToken)
+ if !isFor {
+ // should never happen if caller is behaving
+ panic("parseFor called with peeker not pointing at for token")
+ }
+
+ var contentExprs []Expression
+ var diags hcl.Diagnostics
+ var endforRange hcl.Range
+
+Token:
+ for {
+ next := p.Peek()
+ if end, isEnd := next.(*templateEndToken); isEnd {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unexpected end of template",
+ Detail: fmt.Sprintf(
+ "The for directive at %s is missing its corresponding endfor directive.",
+ openFor.SrcRange,
+ ),
+ Subject: &end.SrcRange,
+ })
+ return errPlaceholderExpr(end.SrcRange), diags
+ }
+ if end, isCtrlEnd := next.(*templateEndCtrlToken); isCtrlEnd {
+ p.Read() // eat end directive
+
+ switch end.Type {
+
+ case templateElse:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unexpected else directive",
+ Detail: "An else clause is not expected for a for directive.",
+ Subject: &end.SrcRange,
+ })
+
+ case templateEndFor:
+ endforRange = end.SrcRange
+ break Token
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Unexpected %s directive", end.Name()),
+ Detail: fmt.Sprintf(
+ "Expecting an endfor directive corresponding to the for directive at %s.",
+ openFor.SrcRange,
+ ),
+ Subject: &end.SrcRange,
+ })
+ }
+
+ return errPlaceholderExpr(end.SrcRange), diags
+ }
+
+ expr, exprDiags := p.parseExpr()
+ diags = append(diags, exprDiags...)
+ contentExprs = append(contentExprs, expr)
+ }
+
+ if len(contentExprs) == 0 {
+ contentExprs = append(contentExprs, &LiteralValueExpr{
+ Val: cty.StringVal(""),
+ SrcRange: hcl.Range{
+ Filename: openFor.SrcRange.Filename,
+ Start: openFor.SrcRange.End,
+ End: openFor.SrcRange.End,
+ },
+ })
+ }
+
+ contentExpr := &TemplateExpr{
+ Parts: contentExprs,
+ SrcRange: hcl.RangeBetween(contentExprs[0].Range(), contentExprs[len(contentExprs)-1].Range()),
+ }
+
+ forExpr := &ForExpr{
+ KeyVar: openFor.KeyVar,
+ ValVar: openFor.ValVar,
+
+ CollExpr: openFor.CollExpr,
+ ValExpr: contentExpr,
+
+ SrcRange: hcl.RangeBetween(openFor.SrcRange, endforRange),
+ OpenRange: openFor.SrcRange,
+ CloseRange: endforRange,
+ }
+
+ return &TemplateJoinExpr{
+ Tuple: forExpr,
+ }, diags
+}
+
+func (p *templateParser) Peek() templateToken {
+ return p.Tokens[p.pos]
+}
+
+func (p *templateParser) Read() templateToken {
+ ret := p.Peek()
+ if _, end := ret.(*templateEndToken); !end {
+ p.pos++
+ }
+ return ret
+}
+
+// parseTemplateParts produces a flat sequence of "template tokens", which are
+// either literal values (with any "trimming" already applied), interpolation
+// sequences, or control flow markers.
+//
+// A further pass is required on the result to turn it into an AST.
+func (p *parser) parseTemplateParts(end TokenType) (*templateParts, hcl.Diagnostics) {
+ var parts []templateToken
+ var diags hcl.Diagnostics
+
+ startRange := p.NextRange()
+ ltrimNext := false
+ nextCanTrimPrev := false
+ var endRange hcl.Range
+
+Token:
+ for {
+ next := p.Read()
+ if next.Type == end {
+ // all done!
+ endRange = next.Range
+ break
+ }
+
+ ltrim := ltrimNext
+ ltrimNext = false
+ canTrimPrev := nextCanTrimPrev
+ nextCanTrimPrev = false
+
+ switch next.Type {
+ case TokenStringLit, TokenQuotedLit:
+ str, strDiags := ParseStringLiteralToken(next)
+ diags = append(diags, strDiags...)
+
+ if ltrim {
+ str = strings.TrimLeftFunc(str, unicode.IsSpace)
+ }
+
+ parts = append(parts, &templateLiteralToken{
+ Val: str,
+ SrcRange: next.Range,
+ })
+ nextCanTrimPrev = true
+
+ case TokenTemplateInterp:
+ // if the opener is ${~ then we want to eat any trailing whitespace
+ // in the preceding literal token, assuming it is indeed a literal
+ // token.
+ if canTrimPrev && len(next.Bytes) == 3 && next.Bytes[2] == '~' && len(parts) > 0 {
+ prevExpr := parts[len(parts)-1]
+ if lexpr, ok := prevExpr.(*templateLiteralToken); ok {
+ lexpr.Val = strings.TrimRightFunc(lexpr.Val, unicode.IsSpace)
+ }
+ }
+
+ p.PushIncludeNewlines(false)
+ expr, exprDiags := p.ParseExpression()
+ diags = append(diags, exprDiags...)
+ close := p.Peek()
+ if close.Type != TokenTemplateSeqEnd {
+ if !p.recovery {
+ switch close.Type {
+ case TokenEOF:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed template interpolation sequence",
+ Detail: "There is no closing brace for this interpolation sequence before the end of the file. This might be caused by incorrect nesting inside the given expression.",
+ Subject: &startRange,
+ })
+ case TokenColon:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Extra characters after interpolation expression",
+ Detail: "Template interpolation doesn't expect a colon at this location. Did you intend this to be a literal sequence to be processed as part of another language? If so, you can escape it by starting with \"$${\" instead of just \"${\".",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(startRange, close.Range).Ptr(),
+ })
+ default:
+ if (close.Type == TokenCQuote || close.Type == TokenOQuote) && end == TokenCQuote {
+ // We'll get here if we're processing a _quoted_
+ // template and we find an errant quote inside an
+ // interpolation sequence, which suggests that
+ // the interpolation sequence is missing its terminator.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed template interpolation sequence",
+ Detail: "There is no closing brace for this interpolation sequence before the end of the quoted template. This might be caused by incorrect nesting inside the given expression.",
+ Subject: &startRange,
+ })
+ } else {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Extra characters after interpolation expression",
+ Detail: "Expected a closing brace to end the interpolation expression, but found extra characters.\n\nThis can happen when you include interpolation syntax for another language, such as shell scripting, but forget to escape the interpolation start token. If this is an embedded sequence for another language, escape it by starting with \"$${\" instead of just \"${\".",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(startRange, close.Range).Ptr(),
+ })
+ }
+ }
+ }
+ p.recover(TokenTemplateSeqEnd)
+ } else {
+ p.Read() // eat closing brace
+
+ // If the closer is ~} then we want to eat any leading
+ // whitespace on the next token, if it turns out to be a
+ // literal token.
+ if len(close.Bytes) == 2 && close.Bytes[0] == '~' {
+ ltrimNext = true
+ }
+ }
+ p.PopIncludeNewlines()
+ parts = append(parts, &templateInterpToken{
+ Expr: expr,
+ SrcRange: hcl.RangeBetween(next.Range, close.Range),
+ })
+
+ case TokenTemplateControl:
+ // if the opener is %{~ then we want to eat any trailing whitespace
+ // in the preceding literal token, assuming it is indeed a literal
+ // token.
+ if canTrimPrev && len(next.Bytes) == 3 && next.Bytes[2] == '~' && len(parts) > 0 {
+ prevExpr := parts[len(parts)-1]
+ if lexpr, ok := prevExpr.(*templateLiteralToken); ok {
+ lexpr.Val = strings.TrimRightFunc(lexpr.Val, unicode.IsSpace)
+ }
+ }
+ p.PushIncludeNewlines(false)
+
+ kw := p.Peek()
+ if kw.Type != TokenIdent {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid template directive",
+ Detail: "A template directive keyword (\"if\", \"for\", etc) is expected at the beginning of a %{ sequence.",
+ Subject: &kw.Range,
+ Context: hcl.RangeBetween(next.Range, kw.Range).Ptr(),
+ })
+ }
+ p.recover(TokenTemplateSeqEnd)
+ p.PopIncludeNewlines()
+ continue Token
+ }
+ p.Read() // eat keyword token
+
+ switch {
+
+ case ifKeyword.TokenMatches(kw):
+ condExpr, exprDiags := p.ParseExpression()
+ diags = append(diags, exprDiags...)
+ parts = append(parts, &templateIfToken{
+ CondExpr: condExpr,
+ SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
+ })
+
+ case elseKeyword.TokenMatches(kw):
+ parts = append(parts, &templateEndCtrlToken{
+ Type: templateElse,
+ SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
+ })
+
+ case endifKeyword.TokenMatches(kw):
+ parts = append(parts, &templateEndCtrlToken{
+ Type: templateEndIf,
+ SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
+ })
+
+ case forKeyword.TokenMatches(kw):
+ var keyName, valName string
+ if p.Peek().Type != TokenIdent {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' directive",
+ Detail: "For directive requires variable name after 'for'.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ }
+ p.recover(TokenTemplateSeqEnd)
+ p.PopIncludeNewlines()
+ continue Token
+ }
+
+ valName = string(p.Read().Bytes)
+
+ if p.Peek().Type == TokenComma {
+ // What we just read was actually the key, then.
+ keyName = valName
+ p.Read() // eat comma
+
+ if p.Peek().Type != TokenIdent {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' directive",
+ Detail: "For directive requires value variable name after comma.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ }
+ p.recover(TokenTemplateSeqEnd)
+ p.PopIncludeNewlines()
+ continue Token
+ }
+
+ valName = string(p.Read().Bytes)
+ }
+
+ if !inKeyword.TokenMatches(p.Peek()) {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid 'for' directive",
+ Detail: "For directive requires 'in' keyword after names.",
+ Subject: p.Peek().Range.Ptr(),
+ })
+ }
+ p.recover(TokenTemplateSeqEnd)
+ p.PopIncludeNewlines()
+ continue Token
+ }
+ p.Read() // eat 'in' keyword
+
+ collExpr, collDiags := p.ParseExpression()
+ diags = append(diags, collDiags...)
+ parts = append(parts, &templateForToken{
+ KeyVar: keyName,
+ ValVar: valName,
+ CollExpr: collExpr,
+
+ SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
+ })
+
+ case endforKeyword.TokenMatches(kw):
+ parts = append(parts, &templateEndCtrlToken{
+ Type: templateEndFor,
+ SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
+ })
+
+ default:
+ if !p.recovery {
+ suggestions := []string{"if", "for", "else", "endif", "endfor"}
+ given := string(kw.Bytes)
+ suggestion := nameSuggestion(given, suggestions)
+ if suggestion != "" {
+ suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid template control keyword",
+ Detail: fmt.Sprintf("%q is not a valid template control keyword.%s", given, suggestion),
+ Subject: &kw.Range,
+ Context: hcl.RangeBetween(next.Range, kw.Range).Ptr(),
+ })
+ }
+ p.recover(TokenTemplateSeqEnd)
+ p.PopIncludeNewlines()
+ continue Token
+
+ }
+
+ close := p.Peek()
+ if close.Type != TokenTemplateSeqEnd {
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Extra characters in %s marker", kw.Bytes),
+ Detail: "Expected a closing brace to end the sequence, but found extra characters.",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(startRange, close.Range).Ptr(),
+ })
+ }
+ p.recover(TokenTemplateSeqEnd)
+ } else {
+ p.Read() // eat closing brace
+
+ // If the closer is ~} then we want to eat any leading
+ // whitespace on the next token, if it turns out to be a
+ // literal token.
+ if len(close.Bytes) == 2 && close.Bytes[0] == '~' {
+ ltrimNext = true
+ }
+ }
+ p.PopIncludeNewlines()
+
+ default:
+ if !p.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unterminated template string",
+ Detail: "No closing marker was found for the string.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(startRange, next.Range).Ptr(),
+ })
+ }
+ final := p.recover(end)
+ endRange = final.Range
+ break Token
+ }
+ }
+
+ if len(parts) == 0 {
+ // If a sequence has no content, we'll treat it as if it had an
+ // empty string in it because that's what the user probably means
+ // if they write "" in configuration.
+ parts = append(parts, &templateLiteralToken{
+ Val: "",
+ SrcRange: hcl.Range{
+ // Range is the zero-character span immediately after the
+ // opening quote.
+ Filename: startRange.Filename,
+ Start: startRange.End,
+ End: startRange.End,
+ },
+ })
+ }
+
+ // Always end with an end token, so the parser can produce diagnostics
+ // about unclosed items with proper position information.
+ parts = append(parts, &templateEndToken{
+ SrcRange: endRange,
+ })
+
+ ret := &templateParts{
+ Tokens: parts,
+ SrcRange: hcl.RangeBetween(startRange, endRange),
+ }
+
+ return ret, diags
+}
+
+// flushHeredocTemplateParts modifies in-place the line-leading literal strings
+// to apply the flush heredoc processing rule: find the line with the smallest
+// number of whitespace characters as prefix and then trim that number of
+// characters from all of the lines.
+//
+// This rule is applied to static tokens rather than to the rendered result,
+// so interpolating a string with leading whitespace cannot affect the chosen
+// prefix length.
+func flushHeredocTemplateParts(parts *templateParts) {
+ if len(parts.Tokens) == 0 {
+ // Nothing to do
+ return
+ }
+
+ const maxInt = int((^uint(0)) >> 1)
+
+ minSpaces := maxInt
+ newline := true
+ var adjust []*templateLiteralToken
+ for _, ttok := range parts.Tokens {
+ if newline {
+ newline = false
+ var spaces int
+ if lit, ok := ttok.(*templateLiteralToken); ok {
+ orig := lit.Val
+ trimmed := strings.TrimLeftFunc(orig, unicode.IsSpace)
+ // If a token is entirely spaces and ends with a newline
+ // then it's a "blank line" and thus not considered for
+ // space-prefix-counting purposes.
+ if len(trimmed) == 0 && strings.HasSuffix(orig, "\n") {
+ spaces = maxInt
+ } else {
+ spaceBytes := len(lit.Val) - len(trimmed)
+ spaces, _ = textseg.TokenCount([]byte(orig[:spaceBytes]), textseg.ScanGraphemeClusters)
+ adjust = append(adjust, lit)
+ }
+ } else if _, ok := ttok.(*templateEndToken); ok {
+ break // don't process the end token since it never has spaces before it
+ }
+ if spaces < minSpaces {
+ minSpaces = spaces
+ }
+ }
+ if lit, ok := ttok.(*templateLiteralToken); ok {
+ if strings.HasSuffix(lit.Val, "\n") {
+ newline = true // The following token, if any, begins a new line
+ }
+ }
+ }
+
+ for _, lit := range adjust {
+ // Since we want to count space _characters_ rather than space _bytes_,
+ // we can't just do a straightforward slice operation here and instead
+ // need to hunt for the split point with a scanner.
+ valBytes := []byte(lit.Val)
+ spaceByteCount := 0
+ for i := 0; i < minSpaces; i++ {
+ adv, _, _ := textseg.ScanGraphemeClusters(valBytes, true)
+ spaceByteCount += adv
+ valBytes = valBytes[adv:]
+ }
+ lit.Val = lit.Val[spaceByteCount:]
+ lit.SrcRange.Start.Column += minSpaces
+ lit.SrcRange.Start.Byte += spaceByteCount
+ }
+}
+
+// meldConsecutiveStringLiterals simplifies the AST output by combining a
+// sequence of string literal tokens into a single string literal. This must be
+// performed after any whitespace trimming operations.
+func meldConsecutiveStringLiterals(parts *templateParts) {
+ if len(parts.Tokens) == 0 {
+ return
+ }
+
+ // Loop over all tokens starting at the second element, as we want to join
+ // pairs of consecutive string literals.
+ i := 1
+ for i < len(parts.Tokens) {
+ if prevLiteral, ok := parts.Tokens[i-1].(*templateLiteralToken); ok {
+ if literal, ok := parts.Tokens[i].(*templateLiteralToken); ok {
+ // The current and previous tokens are both literals: combine
+ prevLiteral.Val = prevLiteral.Val + literal.Val
+ prevLiteral.SrcRange.End = literal.SrcRange.End
+
+ // Remove the current token from the slice
+ parts.Tokens = append(parts.Tokens[:i], parts.Tokens[i+1:]...)
+
+ // Continue without moving forward in the slice
+ continue
+ }
+ }
+
+ // Try the next pair of tokens
+ i++
+ }
+}
+
+type templateParts struct {
+ Tokens []templateToken
+ SrcRange hcl.Range
+}
+
+// templateToken is a higher-level token that represents a single atom within
+// the template language. Our template parsing first raises the raw token
+// stream to a sequence of templateToken, and then transforms the result into
+// an expression tree.
+type templateToken interface {
+ templateToken() templateToken
+}
+
+type templateLiteralToken struct {
+ Val string
+ SrcRange hcl.Range
+ isTemplateToken
+}
+
+type templateInterpToken struct {
+ Expr Expression
+ SrcRange hcl.Range
+ isTemplateToken
+}
+
+type templateIfToken struct {
+ CondExpr Expression
+ SrcRange hcl.Range
+ isTemplateToken
+}
+
+type templateForToken struct {
+ KeyVar string // empty if ignoring key
+ ValVar string
+ CollExpr Expression
+ SrcRange hcl.Range
+ isTemplateToken
+}
+
+type templateEndCtrlType int
+
+const (
+ templateEndIf templateEndCtrlType = iota
+ templateElse
+ templateEndFor
+)
+
+type templateEndCtrlToken struct {
+ Type templateEndCtrlType
+ SrcRange hcl.Range
+ isTemplateToken
+}
+
+func (t *templateEndCtrlToken) Name() string {
+ switch t.Type {
+ case templateEndIf:
+ return "endif"
+ case templateElse:
+ return "else"
+ case templateEndFor:
+ return "endfor"
+ default:
+ // should never happen
+ panic("invalid templateEndCtrlType")
+ }
+}
+
+type templateEndToken struct {
+ SrcRange hcl.Range
+ isTemplateToken
+}
+
+type isTemplateToken [0]int
+
+func (t isTemplateToken) templateToken() templateToken {
+ return t
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_traversal.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_traversal.go
new file mode 100644
index 00000000000..f7d4062f09e
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/parser_traversal.go
@@ -0,0 +1,211 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/zclconf/go-cty/cty"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// ParseTraversalAbs parses an absolute traversal that is assumed to consume
+// all of the remaining tokens in the peeker. The usual parser recovery
+// behavior is not supported here because traversals are not expected to
+// be parsed as part of a larger program.
+func (p *parser) ParseTraversalAbs() (hcl.Traversal, hcl.Diagnostics) {
+ return p.parseTraversal(false)
+}
+
+// ParseTraversalPartial parses an absolute traversal that is permitted
+// to contain splat ([*]) expressions. Only splat expressions within square
+// brackets are permitted ([*]); splat expressions within attribute names are
+// not permitted (.*).
+//
+// The meaning of partial here is that the traversal may be incomplete, in that
+// any splat expression indicates reference to a potentially unknown number of
+// elements.
+//
+// Traversals that include splats cannot be automatically traversed by HCL using
+// the TraversalAbs or TraversalRel methods. Instead, the caller must handle
+// the traversals manually.
+func (p *parser) ParseTraversalPartial() (hcl.Traversal, hcl.Diagnostics) {
+ return p.parseTraversal(true)
+}
+
+func (p *parser) parseTraversal(allowSplats bool) (hcl.Traversal, hcl.Diagnostics) {
+ var ret hcl.Traversal
+ var diags hcl.Diagnostics
+
+ // Absolute traversal must always begin with a variable name
+ varTok := p.Read()
+ if varTok.Type != TokenIdent {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Variable name required",
+ Detail: "Must begin with a variable name.",
+ Subject: &varTok.Range,
+ })
+ return ret, diags
+ }
+
+ varName := string(varTok.Bytes)
+ ret = append(ret, hcl.TraverseRoot{
+ Name: varName,
+ SrcRange: varTok.Range,
+ })
+
+ for {
+ next := p.Peek()
+
+ if next.Type == TokenEOF {
+ return ret, diags
+ }
+
+ switch next.Type {
+ case TokenDot:
+ // Attribute access
+ dot := p.Read() // eat dot
+ nameTok := p.Read()
+ if nameTok.Type != TokenIdent {
+ if nameTok.Type == TokenStar {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Attribute name required",
+ Detail: "Splat expressions (.*) may not be used here.",
+ Subject: &nameTok.Range,
+ Context: hcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(),
+ })
+ } else {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Attribute name required",
+ Detail: "Dot must be followed by attribute name.",
+ Subject: &nameTok.Range,
+ Context: hcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(),
+ })
+ }
+ return ret, diags
+ }
+
+ attrName := string(nameTok.Bytes)
+ ret = append(ret, hcl.TraverseAttr{
+ Name: attrName,
+ SrcRange: hcl.RangeBetween(dot.Range, nameTok.Range),
+ })
+ case TokenOBrack:
+ // Index
+ open := p.Read() // eat open bracket
+ next := p.Peek()
+
+ switch next.Type {
+ case TokenNumberLit:
+ tok := p.Read() // eat number
+ numVal, numDiags := p.numberLitValue(tok)
+ diags = append(diags, numDiags...)
+
+ close := p.Read()
+ if close.Type != TokenCBrack {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed index brackets",
+ Detail: "Index key must be followed by a closing bracket.",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
+ })
+ }
+
+ ret = append(ret, hcl.TraverseIndex{
+ Key: numVal,
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ })
+
+ if diags.HasErrors() {
+ return ret, diags
+ }
+
+ case TokenOQuote:
+ str, _, strDiags := p.parseQuotedStringLiteral()
+ diags = append(diags, strDiags...)
+
+ close := p.Read()
+ if close.Type != TokenCBrack {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed index brackets",
+ Detail: "Index key must be followed by a closing bracket.",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
+ })
+ }
+
+ ret = append(ret, hcl.TraverseIndex{
+ Key: cty.StringVal(str),
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ })
+
+ if diags.HasErrors() {
+ return ret, diags
+ }
+
+ case TokenStar:
+ if allowSplats {
+
+ p.Read() // Eat the star.
+ close := p.Read()
+ if close.Type != TokenCBrack {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unclosed index brackets",
+ Detail: "Index key must be followed by a closing bracket.",
+ Subject: &close.Range,
+ Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
+ })
+ }
+
+ ret = append(ret, hcl.TraverseSplat{
+ SrcRange: hcl.RangeBetween(open.Range, close.Range),
+ })
+
+ if diags.HasErrors() {
+ return ret, diags
+ }
+
+ continue
+ }
+
+ // Otherwise, return the error below for the star.
+ fallthrough
+ default:
+ if next.Type == TokenStar {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Attribute name required",
+ Detail: "Splat expressions ([*]) may not be used here.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(varTok.Range, next.Range).Ptr(),
+ })
+ } else {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Index value required",
+ Detail: "Index brackets must contain either a literal number or a literal string.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(varTok.Range, next.Range).Ptr(),
+ })
+ }
+ return ret, diags
+ }
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid character",
+ Detail: "Expected an attribute access or an index operator.",
+ Subject: &next.Range,
+ Context: hcl.RangeBetween(varTok.Range, next.Range).Ptr(),
+ })
+ return ret, diags
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/peeker.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/peeker.go
new file mode 100644
index 00000000000..74fa3fb3313
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/peeker.go
@@ -0,0 +1,215 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+ "fmt"
+ "path/filepath"
+ "runtime"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// This is set to true at init() time in tests, to enable more useful output
+// if a stack discipline error is detected. It should not be enabled in
+// normal mode since there is a performance penalty from accessing the
+// runtime stack to produce the traces, but could be temporarily set to
+// true for debugging if desired.
+var tracePeekerNewlinesStack = false
+
+type peeker struct {
+ Tokens Tokens
+ NextIndex int
+
+ IncludeComments bool
+ IncludeNewlinesStack []bool
+
+ // used only when tracePeekerNewlinesStack is set
+ newlineStackChanges []peekerNewlineStackChange
+}
+
+// for use in debugging the stack usage only
+type peekerNewlineStackChange struct {
+ Pushing bool // if false, then popping
+ Frame runtime.Frame
+ Include bool
+}
+
+func newPeeker(tokens Tokens, includeComments bool) *peeker {
+ return &peeker{
+ Tokens: tokens,
+ IncludeComments: includeComments,
+
+ IncludeNewlinesStack: []bool{true},
+ }
+}
+
+func (p *peeker) Peek() Token {
+ ret, _ := p.nextToken()
+ return ret
+}
+
+func (p *peeker) Read() Token {
+ ret, nextIdx := p.nextToken()
+ p.NextIndex = nextIdx
+ return ret
+}
+
+func (p *peeker) NextRange() hcl.Range {
+ return p.Peek().Range
+}
+
+func (p *peeker) PrevRange() hcl.Range {
+ if p.NextIndex == 0 {
+ return p.NextRange()
+ }
+
+ return p.Tokens[p.NextIndex-1].Range
+}
+
+func (p *peeker) nextToken() (Token, int) {
+ for i := p.NextIndex; i < len(p.Tokens); i++ {
+ tok := p.Tokens[i]
+ switch tok.Type {
+ case TokenComment:
+ if !p.IncludeComments {
+ // Single-line comment tokens, starting with # or //, absorb
+ // the trailing newline that terminates them as part of their
+ // bytes. When we're filtering out comments, we must as a
+ // special case transform these to newline tokens in order
+ // to properly parse newline-terminated block items.
+
+ if p.includingNewlines() {
+ if len(tok.Bytes) > 0 && tok.Bytes[len(tok.Bytes)-1] == '\n' {
+ fakeNewline := Token{
+ Type: TokenNewline,
+ Bytes: tok.Bytes[len(tok.Bytes)-1 : len(tok.Bytes)],
+
+ // We use the whole token range as the newline
+ // range, even though that's a little... weird,
+ // because otherwise we'd need to go count
+ // characters again in order to figure out the
+ // column of the newline, and that complexity
+ // isn't justified when ranges of newlines are
+ // so rarely printed anyway.
+ Range: tok.Range,
+ }
+ return fakeNewline, i + 1
+ }
+ }
+
+ continue
+ }
+ case TokenNewline:
+ if !p.includingNewlines() {
+ continue
+ }
+ }
+
+ return tok, i + 1
+ }
+
+ // if we fall out here then we'll return the EOF token, and leave
+ // our index pointed off the end of the array so we'll keep
+ // returning EOF in future too.
+ return p.Tokens[len(p.Tokens)-1], len(p.Tokens)
+}
+
+func (p *peeker) includingNewlines() bool {
+ return p.IncludeNewlinesStack[len(p.IncludeNewlinesStack)-1]
+}
+
+func (p *peeker) PushIncludeNewlines(include bool) {
+ if tracePeekerNewlinesStack {
+ // Record who called us so that we can more easily track down any
+ // mismanagement of the stack in the parser.
+ callers := []uintptr{0}
+ runtime.Callers(2, callers)
+ frames := runtime.CallersFrames(callers)
+ frame, _ := frames.Next()
+ p.newlineStackChanges = append(p.newlineStackChanges, peekerNewlineStackChange{
+ true, frame, include,
+ })
+ }
+
+ p.IncludeNewlinesStack = append(p.IncludeNewlinesStack, include)
+}
+
+func (p *peeker) PopIncludeNewlines() bool {
+ stack := p.IncludeNewlinesStack
+ remain, ret := stack[:len(stack)-1], stack[len(stack)-1]
+ p.IncludeNewlinesStack = remain
+
+ if tracePeekerNewlinesStack {
+ // Record who called us so that we can more easily track down any
+ // mismanagement of the stack in the parser.
+ callers := []uintptr{0}
+ runtime.Callers(2, callers)
+ frames := runtime.CallersFrames(callers)
+ frame, _ := frames.Next()
+ p.newlineStackChanges = append(p.newlineStackChanges, peekerNewlineStackChange{
+ false, frame, ret,
+ })
+ }
+
+ return ret
+}
+
+// AssertEmptyNewlinesStack checks if the IncludeNewlinesStack is empty, doing
+// panicking if it is not. This can be used to catch stack mismanagement that
+// might otherwise just cause confusing downstream errors.
+//
+// This function is a no-op if the stack is empty when called.
+//
+// If newlines stack tracing is enabled by setting the global variable
+// tracePeekerNewlinesStack at init time, a full log of all of the push/pop
+// calls will be produced to help identify which caller in the parser is
+// misbehaving.
+func (p *peeker) AssertEmptyIncludeNewlinesStack() {
+ if len(p.IncludeNewlinesStack) != 1 {
+ // Should never happen; indicates mismanagement of the stack inside
+ // the parser.
+ if p.newlineStackChanges != nil { // only if traceNewlinesStack is enabled above
+ panic(fmt.Errorf(
+ "non-empty IncludeNewlinesStack after parse with %d calls unaccounted for:\n%s",
+ len(p.IncludeNewlinesStack)-1,
+ formatPeekerNewlineStackChanges(p.newlineStackChanges),
+ ))
+ } else {
+ panic(fmt.Errorf("non-empty IncludeNewlinesStack after parse: %#v", p.IncludeNewlinesStack))
+ }
+ }
+}
+
+func formatPeekerNewlineStackChanges(changes []peekerNewlineStackChange) string {
+ indent := 0
+ var buf bytes.Buffer
+ for _, change := range changes {
+ funcName := change.Frame.Function
+ if idx := strings.LastIndexByte(funcName, '.'); idx != -1 {
+ funcName = funcName[idx+1:]
+ }
+ filename := change.Frame.File
+ if idx := strings.LastIndexByte(filename, filepath.Separator); idx != -1 {
+ filename = filename[idx+1:]
+ }
+
+ switch change.Pushing {
+
+ case true:
+ buf.WriteString(strings.Repeat(" ", indent))
+ fmt.Fprintf(&buf, "PUSH %#v (%s at %s:%d)\n", change.Include, funcName, filename, change.Frame.Line)
+ indent++
+
+ case false:
+ indent--
+ buf.WriteString(strings.Repeat(" ", indent))
+ fmt.Fprintf(&buf, "POP %#v (%s at %s:%d)\n", change.Include, funcName, filename, change.Frame.Line)
+
+ }
+ }
+ return buf.String()
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/public.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/public.go
new file mode 100644
index 00000000000..17dc1ed419a
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/public.go
@@ -0,0 +1,205 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+// ParseConfig parses the given buffer as a whole HCL config file, returning
+// a *hcl.File representing its contents. If HasErrors called on the returned
+// diagnostics returns true, the returned body is likely to be incomplete
+// and should therefore be used with care.
+//
+// The body in the returned file has dynamic type *hclsyntax.Body, so callers
+// may freely type-assert this to get access to the full hclsyntax API in
+// situations where detailed access is required. However, most common use-cases
+// should be served using the hcl.Body interface to ensure compatibility with
+// other configurationg syntaxes, such as JSON.
+func ParseConfig(src []byte, filename string, start hcl.Pos) (*hcl.File, hcl.Diagnostics) {
+ tokens, diags := LexConfig(src, filename, start)
+ peeker := newPeeker(tokens, false)
+ parser := &parser{peeker: peeker}
+ body, parseDiags := parser.ParseBody(TokenEOF)
+ diags = append(diags, parseDiags...)
+
+ // Panic if the parser uses incorrect stack discipline with the peeker's
+ // newlines stack, since otherwise it will produce confusing downstream
+ // errors.
+ peeker.AssertEmptyIncludeNewlinesStack()
+
+ return &hcl.File{
+ Body: body,
+ Bytes: src,
+
+ Nav: navigation{
+ root: body,
+ },
+ }, diags
+}
+
+// ParseExpression parses the given buffer as a standalone HCL expression,
+// returning it as an instance of Expression.
+func ParseExpression(src []byte, filename string, start hcl.Pos) (Expression, hcl.Diagnostics) {
+ tokens, diags := LexExpression(src, filename, start)
+ peeker := newPeeker(tokens, false)
+ parser := &parser{peeker: peeker}
+
+ // Bare expressions are always parsed in "ignore newlines" mode, as if
+ // they were wrapped in parentheses.
+ parser.PushIncludeNewlines(false)
+
+ expr, parseDiags := parser.ParseExpression()
+ diags = append(diags, parseDiags...)
+
+ next := parser.Peek()
+ if next.Type != TokenEOF && !parser.recovery {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Extra characters after expression",
+ Detail: "An expression was successfully parsed, but extra characters were found after it.",
+ Subject: &next.Range,
+ })
+ }
+
+ parser.PopIncludeNewlines()
+
+ // Panic if the parser uses incorrect stack discipline with the peeker's
+ // newlines stack, since otherwise it will produce confusing downstream
+ // errors.
+ peeker.AssertEmptyIncludeNewlinesStack()
+
+ return expr, diags
+}
+
+// ParseTemplate parses the given buffer as a standalone HCL template,
+// returning it as an instance of Expression.
+func ParseTemplate(src []byte, filename string, start hcl.Pos) (Expression, hcl.Diagnostics) {
+ tokens, diags := LexTemplate(src, filename, start)
+ peeker := newPeeker(tokens, false)
+ parser := &parser{peeker: peeker}
+ expr, parseDiags := parser.ParseTemplate()
+ diags = append(diags, parseDiags...)
+
+ // Panic if the parser uses incorrect stack discipline with the peeker's
+ // newlines stack, since otherwise it will produce confusing downstream
+ // errors.
+ peeker.AssertEmptyIncludeNewlinesStack()
+
+ return expr, diags
+}
+
+// ParseTraversalAbs parses the given buffer as a standalone absolute traversal.
+//
+// Parsing as a traversal is more limited than parsing as an expession since
+// it allows only attribute and indexing operations on variables. Traverals
+// are useful as a syntax for referring to objects without necessarily
+// evaluating them.
+func ParseTraversalAbs(src []byte, filename string, start hcl.Pos) (hcl.Traversal, hcl.Diagnostics) {
+ tokens, diags := LexExpression(src, filename, start)
+ peeker := newPeeker(tokens, false)
+ parser := &parser{peeker: peeker}
+
+ // Bare traverals are always parsed in "ignore newlines" mode, as if
+ // they were wrapped in parentheses.
+ parser.PushIncludeNewlines(false)
+
+ expr, parseDiags := parser.ParseTraversalAbs()
+ diags = append(diags, parseDiags...)
+
+ parser.PopIncludeNewlines()
+
+ // Panic if the parser uses incorrect stack discipline with the peeker's
+ // newlines stack, since otherwise it will produce confusing downstream
+ // errors.
+ peeker.AssertEmptyIncludeNewlinesStack()
+
+ return expr, diags
+}
+
+// ParseTraversalPartial matches the behavior of ParseTraversalAbs except
+// that it allows splat expressions ([*]) to appear in the traversal.
+//
+// The returned traversals are "partial" in that the splat expression indicates
+// an unknown value for the index.
+//
+// Traversals that include splats cannot be automatically traversed by HCL using
+// the TraversalAbs or TraversalRel methods. Instead, the caller must handle
+// the traversals manually.
+func ParseTraversalPartial(src []byte, filename string, start hcl.Pos) (hcl.Traversal, hcl.Diagnostics) {
+ tokens, diags := LexExpression(src, filename, start)
+ peeker := newPeeker(tokens, false)
+ parser := &parser{peeker: peeker}
+
+ // Bare traverals are always parsed in "ignore newlines" mode, as if
+ // they were wrapped in parentheses.
+ parser.PushIncludeNewlines(false)
+
+ expr, parseDiags := parser.ParseTraversalPartial()
+ diags = append(diags, parseDiags...)
+
+ parser.PopIncludeNewlines()
+
+ // Panic if the parser uses incorrect stack discipline with the peeker's
+ // newlines stack, since otherwise it will produce confusing downstream
+ // errors.
+ peeker.AssertEmptyIncludeNewlinesStack()
+
+ return expr, diags
+}
+
+// LexConfig performs lexical analysis on the given buffer, treating it as a
+// whole HCL config file, and returns the resulting tokens.
+//
+// Only minimal validation is done during lexical analysis, so the returned
+// diagnostics may include errors about lexical issues such as bad character
+// encodings or unrecognized characters, but full parsing is required to
+// detect _all_ syntax errors.
+func LexConfig(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {
+ tokens := scanTokens(src, filename, start, scanNormal)
+ diags := checkInvalidTokens(tokens)
+ return tokens, diags
+}
+
+// LexExpression performs lexical analysis on the given buffer, treating it as
+// a standalone HCL expression, and returns the resulting tokens.
+//
+// Only minimal validation is done during lexical analysis, so the returned
+// diagnostics may include errors about lexical issues such as bad character
+// encodings or unrecognized characters, but full parsing is required to
+// detect _all_ syntax errors.
+func LexExpression(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {
+ // This is actually just the same thing as LexConfig, since configs
+ // and expressions lex in the same way.
+ tokens := scanTokens(src, filename, start, scanNormal)
+ diags := checkInvalidTokens(tokens)
+ return tokens, diags
+}
+
+// LexTemplate performs lexical analysis on the given buffer, treating it as a
+// standalone HCL template, and returns the resulting tokens.
+//
+// Only minimal validation is done during lexical analysis, so the returned
+// diagnostics may include errors about lexical issues such as bad character
+// encodings or unrecognized characters, but full parsing is required to
+// detect _all_ syntax errors.
+func LexTemplate(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {
+ tokens := scanTokens(src, filename, start, scanTemplate)
+ diags := checkInvalidTokens(tokens)
+ return tokens, diags
+}
+
+// ValidIdentifier tests if the given string could be a valid identifier in
+// a native syntax expression.
+//
+// This is useful when accepting names from the user that will be used as
+// variable or attribute names in the scope, to ensure that any name chosen
+// will be traversable using the variable or attribute traversal syntax.
+func ValidIdentifier(s string) bool {
+ // This is a kinda-expensive way to do something pretty simple, but it
+ // is easiest to do with our existing scanner-related infrastructure here
+ // and nobody should be validating identifiers in a tight loop.
+ tokens := scanTokens([]byte(s), "", hcl.Pos{}, scanIdentOnly)
+ return len(tokens) == 2 && tokens[0].Type == TokenIdent && tokens[1].Type == TokenEOF
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.go
new file mode 100644
index 00000000000..6b44d9923ba
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.go
@@ -0,0 +1,303 @@
+//line scan_string_lit.rl:1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+// This file is generated from scan_string_lit.rl. DO NOT EDIT.
+
+//line scan_string_lit.go:11
+var _hclstrtok_actions []byte = []byte{
+ 0, 1, 0, 1, 1, 2, 1, 0,
+}
+
+var _hclstrtok_key_offsets []byte = []byte{
+ 0, 0, 2, 4, 6, 10, 14, 18,
+ 22, 27, 31, 36, 41, 46, 51, 57,
+ 62, 74, 85, 96, 107, 118, 129, 140,
+ 151,
+}
+
+var _hclstrtok_trans_keys []byte = []byte{
+ 128, 191, 128, 191, 128, 191, 10, 13,
+ 36, 37, 10, 13, 36, 37, 10, 13,
+ 36, 37, 10, 13, 36, 37, 10, 13,
+ 36, 37, 123, 10, 13, 36, 37, 10,
+ 13, 36, 37, 92, 10, 13, 36, 37,
+ 92, 10, 13, 36, 37, 92, 10, 13,
+ 36, 37, 92, 10, 13, 36, 37, 92,
+ 123, 10, 13, 36, 37, 92, 85, 117,
+ 128, 191, 192, 223, 224, 239, 240, 247,
+ 248, 255, 10, 13, 36, 37, 92, 48,
+ 57, 65, 70, 97, 102, 10, 13, 36,
+ 37, 92, 48, 57, 65, 70, 97, 102,
+ 10, 13, 36, 37, 92, 48, 57, 65,
+ 70, 97, 102, 10, 13, 36, 37, 92,
+ 48, 57, 65, 70, 97, 102, 10, 13,
+ 36, 37, 92, 48, 57, 65, 70, 97,
+ 102, 10, 13, 36, 37, 92, 48, 57,
+ 65, 70, 97, 102, 10, 13, 36, 37,
+ 92, 48, 57, 65, 70, 97, 102, 10,
+ 13, 36, 37, 92, 48, 57, 65, 70,
+ 97, 102,
+}
+
+var _hclstrtok_single_lengths []byte = []byte{
+ 0, 0, 0, 0, 4, 4, 4, 4,
+ 5, 4, 5, 5, 5, 5, 6, 5,
+ 2, 5, 5, 5, 5, 5, 5, 5,
+ 5,
+}
+
+var _hclstrtok_range_lengths []byte = []byte{
+ 0, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 3, 3, 3, 3, 3, 3, 3,
+ 3,
+}
+
+var _hclstrtok_index_offsets []byte = []byte{
+ 0, 0, 2, 4, 6, 11, 16, 21,
+ 26, 32, 37, 43, 49, 55, 61, 68,
+ 74, 82, 91, 100, 109, 118, 127, 136,
+ 145,
+}
+
+var _hclstrtok_indicies []byte = []byte{
+ 0, 1, 2, 1, 3, 1, 5, 6,
+ 7, 8, 4, 10, 11, 12, 13, 9,
+ 14, 11, 12, 13, 9, 10, 11, 15,
+ 13, 9, 10, 11, 12, 13, 14, 9,
+ 10, 11, 12, 15, 9, 17, 18, 19,
+ 20, 21, 16, 23, 24, 25, 26, 27,
+ 22, 0, 24, 25, 26, 27, 22, 23,
+ 24, 28, 26, 27, 22, 23, 24, 25,
+ 26, 27, 0, 22, 23, 24, 25, 28,
+ 27, 22, 29, 30, 22, 2, 3, 31,
+ 22, 0, 23, 24, 25, 26, 27, 32,
+ 32, 32, 22, 23, 24, 25, 26, 27,
+ 33, 33, 33, 22, 23, 24, 25, 26,
+ 27, 34, 34, 34, 22, 23, 24, 25,
+ 26, 27, 30, 30, 30, 22, 23, 24,
+ 25, 26, 27, 35, 35, 35, 22, 23,
+ 24, 25, 26, 27, 36, 36, 36, 22,
+ 23, 24, 25, 26, 27, 37, 37, 37,
+ 22, 23, 24, 25, 26, 27, 0, 0,
+ 0, 22,
+}
+
+var _hclstrtok_trans_targs []byte = []byte{
+ 11, 0, 1, 2, 4, 5, 6, 7,
+ 9, 4, 5, 6, 7, 9, 5, 8,
+ 10, 11, 12, 13, 15, 16, 10, 11,
+ 12, 13, 15, 16, 14, 17, 21, 3,
+ 18, 19, 20, 22, 23, 24,
+}
+
+var _hclstrtok_trans_actions []byte = []byte{
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 3, 5, 5, 5, 5, 0, 0,
+ 0, 1, 1, 1, 1, 1, 3, 5,
+ 5, 5, 5, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+}
+
+var _hclstrtok_eof_actions []byte = []byte{
+ 0, 0, 0, 0, 0, 3, 3, 3,
+ 3, 3, 0, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3,
+}
+
+const hclstrtok_start int = 4
+const hclstrtok_first_final int = 4
+const hclstrtok_error int = 0
+
+const hclstrtok_en_quoted int = 10
+const hclstrtok_en_unquoted int = 4
+
+//line scan_string_lit.rl:12
+
+func scanStringLit(data []byte, quoted bool) [][]byte {
+ var ret [][]byte
+
+//line scan_string_lit.rl:63
+
+ // Ragel state
+ p := 0 // "Pointer" into data
+ pe := len(data) // End-of-data "pointer"
+ ts := 0
+ te := 0
+ eof := pe
+
+ var cs int // current state
+ switch {
+ case quoted:
+ cs = hclstrtok_en_quoted
+ default:
+ cs = hclstrtok_en_unquoted
+ }
+
+ // Make Go compiler happy
+ _ = ts
+ _ = eof
+
+ /*token := func () {
+ ret = append(ret, data[ts:te])
+ }*/
+
+//line scan_string_lit.go:156
+ {
+ }
+
+//line scan_string_lit.go:160
+ {
+ var _klen int
+ var _trans int
+ var _acts int
+ var _nacts uint
+ var _keys int
+ if p == pe {
+ goto _test_eof
+ }
+ if cs == 0 {
+ goto _out
+ }
+ _resume:
+ _keys = int(_hclstrtok_key_offsets[cs])
+ _trans = int(_hclstrtok_index_offsets[cs])
+
+ _klen = int(_hclstrtok_single_lengths[cs])
+ if _klen > 0 {
+ _lower := int(_keys)
+ var _mid int
+ _upper := int(_keys + _klen - 1)
+ for {
+ if _upper < _lower {
+ break
+ }
+
+ _mid = _lower + ((_upper - _lower) >> 1)
+ switch {
+ case data[p] < _hclstrtok_trans_keys[_mid]:
+ _upper = _mid - 1
+ case data[p] > _hclstrtok_trans_keys[_mid]:
+ _lower = _mid + 1
+ default:
+ _trans += int(_mid - int(_keys))
+ goto _match
+ }
+ }
+ _keys += _klen
+ _trans += _klen
+ }
+
+ _klen = int(_hclstrtok_range_lengths[cs])
+ if _klen > 0 {
+ _lower := int(_keys)
+ var _mid int
+ _upper := int(_keys + (_klen << 1) - 2)
+ for {
+ if _upper < _lower {
+ break
+ }
+
+ _mid = _lower + (((_upper - _lower) >> 1) & ^1)
+ switch {
+ case data[p] < _hclstrtok_trans_keys[_mid]:
+ _upper = _mid - 2
+ case data[p] > _hclstrtok_trans_keys[_mid+1]:
+ _lower = _mid + 2
+ default:
+ _trans += int((_mid - int(_keys)) >> 1)
+ goto _match
+ }
+ }
+ _trans += _klen
+ }
+
+ _match:
+ _trans = int(_hclstrtok_indicies[_trans])
+ cs = int(_hclstrtok_trans_targs[_trans])
+
+ if _hclstrtok_trans_actions[_trans] == 0 {
+ goto _again
+ }
+
+ _acts = int(_hclstrtok_trans_actions[_trans])
+ _nacts = uint(_hclstrtok_actions[_acts])
+ _acts++
+ for ; _nacts > 0; _nacts-- {
+ _acts++
+ switch _hclstrtok_actions[_acts-1] {
+ case 0:
+//line scan_string_lit.rl:42
+
+ // If te is behind p then we've skipped over some literal
+ // characters which we must now return.
+ if te < p {
+ ret = append(ret, data[te:p])
+ }
+ ts = p
+
+ case 1:
+//line scan_string_lit.rl:50
+
+ te = p
+ ret = append(ret, data[ts:te])
+
+//line scan_string_lit.go:255
+ }
+ }
+
+ _again:
+ if cs == 0 {
+ goto _out
+ }
+ p++
+ if p != pe {
+ goto _resume
+ }
+ _test_eof:
+ {
+ }
+ if p == eof {
+ __acts := _hclstrtok_eof_actions[cs]
+ __nacts := uint(_hclstrtok_actions[__acts])
+ __acts++
+ for ; __nacts > 0; __nacts-- {
+ __acts++
+ switch _hclstrtok_actions[__acts-1] {
+ case 1:
+//line scan_string_lit.rl:50
+
+ te = p
+ ret = append(ret, data[ts:te])
+
+//line scan_string_lit.go:280
+ }
+ }
+ }
+
+ _out:
+ {
+ }
+ }
+
+//line scan_string_lit.rl:91
+
+ if te < p {
+ // Collect any leftover literal characters at the end of the input
+ ret = append(ret, data[te:p])
+ }
+
+ // If we fall out here without being in a final state then we've
+ // encountered something that the scanner can't match, which should
+ // be impossible (the scanner matches all bytes _somehow_) but we'll
+ // tolerate it and let the caller deal with it.
+ if cs < hclstrtok_first_final {
+ ret = append(ret, data[p:len(data)])
+ }
+
+ return ret
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.rl b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.rl
new file mode 100644
index 00000000000..21d2c8bca38
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_string_lit.rl
@@ -0,0 +1,107 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+// This file is generated from scan_string_lit.rl. DO NOT EDIT.
+%%{
+ # (except you are actually in scan_string_lit.rl here, so edit away!)
+
+ machine hclstrtok;
+ write data;
+}%%
+
+func scanStringLit(data []byte, quoted bool) [][]byte {
+ var ret [][]byte
+
+ %%{
+ include UnicodeDerived "unicode_derived.rl";
+
+ UTF8Cont = 0x80 .. 0xBF;
+ AnyUTF8 = (
+ 0x00..0x7F |
+ 0xC0..0xDF . UTF8Cont |
+ 0xE0..0xEF . UTF8Cont . UTF8Cont |
+ 0xF0..0xF7 . UTF8Cont . UTF8Cont . UTF8Cont
+ );
+ BadUTF8 = any - AnyUTF8;
+
+ Hex = ('0'..'9' | 'a'..'f' | 'A'..'F');
+
+ # Our goal with this patterns is to capture user intent as best as
+ # possible, even if the input is invalid. The caller will then verify
+ # whether each token is valid and generate suitable error messages
+ # if not.
+ UnicodeEscapeShort = "\\u" . Hex{0,4};
+ UnicodeEscapeLong = "\\U" . Hex{0,8};
+ UnicodeEscape = (UnicodeEscapeShort | UnicodeEscapeLong);
+ SimpleEscape = "\\" . (AnyUTF8 - ('U'|'u'))?;
+ TemplateEscape = ("$" . ("$" . ("{"?))?) | ("%" . ("%" . ("{"?))?);
+ Newline = ("\r\n" | "\r" | "\n");
+
+ action Begin {
+ // If te is behind p then we've skipped over some literal
+ // characters which we must now return.
+ if te < p {
+ ret = append(ret, data[te:p])
+ }
+ ts = p;
+ }
+ action End {
+ te = p;
+ ret = append(ret, data[ts:te]);
+ }
+
+ QuotedToken = (UnicodeEscape | SimpleEscape | TemplateEscape | Newline) >Begin %End;
+ UnquotedToken = (TemplateEscape | Newline) >Begin %End;
+ QuotedLiteral = (any - ("\\" | "$" | "%" | "\r" | "\n"));
+ UnquotedLiteral = (any - ("$" | "%" | "\r" | "\n"));
+
+ quoted := (QuotedToken | QuotedLiteral)**;
+ unquoted := (UnquotedToken | UnquotedLiteral)**;
+
+ }%%
+
+ // Ragel state
+ p := 0 // "Pointer" into data
+ pe := len(data) // End-of-data "pointer"
+ ts := 0
+ te := 0
+ eof := pe
+
+ var cs int // current state
+ switch {
+ case quoted:
+ cs = hclstrtok_en_quoted
+ default:
+ cs = hclstrtok_en_unquoted
+ }
+
+ // Make Go compiler happy
+ _ = ts
+ _ = eof
+
+ /*token := func () {
+ ret = append(ret, data[ts:te])
+ }*/
+
+ %%{
+ write init nocs;
+ write exec;
+ }%%
+
+ if te < p {
+ // Collect any leftover literal characters at the end of the input
+ ret = append(ret, data[te:p])
+ }
+
+ // If we fall out here without being in a final state then we've
+ // encountered something that the scanner can't match, which should
+ // be impossible (the scanner matches all bytes _somehow_) but we'll
+ // tolerate it and let the caller deal with it.
+ if cs < hclstrtok_first_final {
+ ret = append(ret, data[p:len(data)])
+ }
+
+ return ret
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.go
new file mode 100644
index 00000000000..3ed8455ff87
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.go
@@ -0,0 +1,5273 @@
+//line scan_tokens.rl:1
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// This file is generated from scan_tokens.rl. DO NOT EDIT.
+
+//line scan_tokens.go:17
+var _hcltok_actions []byte = []byte{
+ 0, 1, 0, 1, 1, 1, 3, 1, 4,
+ 1, 7, 1, 8, 1, 9, 1, 10,
+ 1, 11, 1, 12, 1, 13, 1, 14,
+ 1, 15, 1, 16, 1, 17, 1, 18,
+ 1, 19, 1, 20, 1, 23, 1, 24,
+ 1, 25, 1, 26, 1, 27, 1, 28,
+ 1, 29, 1, 30, 1, 31, 1, 32,
+ 1, 35, 1, 36, 1, 37, 1, 38,
+ 1, 39, 1, 40, 1, 41, 1, 42,
+ 1, 43, 1, 44, 1, 47, 1, 48,
+ 1, 49, 1, 50, 1, 51, 1, 52,
+ 1, 53, 1, 56, 1, 57, 1, 58,
+ 1, 59, 1, 60, 1, 61, 1, 62,
+ 1, 63, 1, 64, 1, 65, 1, 66,
+ 1, 67, 1, 68, 1, 69, 1, 70,
+ 1, 71, 1, 72, 1, 73, 1, 74,
+ 1, 75, 1, 76, 1, 77, 1, 78,
+ 1, 79, 1, 80, 1, 81, 1, 82,
+ 1, 83, 1, 84, 1, 85, 1, 86,
+ 2, 0, 14, 2, 0, 25, 2, 0,
+ 29, 2, 0, 37, 2, 0, 41, 2,
+ 1, 2, 2, 4, 5, 2, 4, 6,
+ 2, 4, 21, 2, 4, 22, 2, 4,
+ 33, 2, 4, 34, 2, 4, 45, 2,
+ 4, 46, 2, 4, 54, 2, 4, 55,
+}
+
+var _hcltok_key_offsets []int16 = []int16{
+ 0, 0, 1, 2, 4, 9, 13, 15,
+ 57, 98, 144, 145, 149, 155, 155, 157,
+ 159, 168, 174, 181, 182, 185, 186, 190,
+ 195, 204, 208, 212, 220, 222, 224, 226,
+ 229, 261, 263, 265, 269, 273, 276, 287,
+ 300, 319, 332, 348, 360, 376, 391, 412,
+ 422, 434, 445, 459, 474, 484, 496, 505,
+ 517, 519, 523, 544, 553, 563, 569, 575,
+ 576, 625, 627, 631, 633, 639, 646, 654,
+ 661, 664, 670, 674, 678, 680, 684, 688,
+ 692, 698, 706, 714, 720, 722, 726, 728,
+ 734, 738, 742, 746, 750, 755, 762, 768,
+ 770, 772, 776, 778, 784, 788, 792, 802,
+ 807, 821, 836, 838, 846, 848, 853, 867,
+ 872, 874, 878, 879, 883, 889, 895, 905,
+ 915, 926, 934, 937, 940, 944, 948, 950,
+ 953, 953, 956, 958, 988, 990, 992, 996,
+ 1001, 1005, 1010, 1012, 1014, 1016, 1025, 1029,
+ 1033, 1039, 1041, 1049, 1057, 1069, 1072, 1078,
+ 1082, 1084, 1088, 1108, 1110, 1112, 1123, 1129,
+ 1131, 1133, 1135, 1139, 1145, 1151, 1153, 1158,
+ 1162, 1164, 1172, 1190, 1230, 1240, 1244, 1246,
+ 1248, 1249, 1253, 1257, 1261, 1265, 1269, 1274,
+ 1278, 1282, 1286, 1288, 1290, 1294, 1304, 1308,
+ 1310, 1314, 1318, 1322, 1335, 1337, 1339, 1343,
+ 1345, 1349, 1351, 1353, 1383, 1387, 1391, 1395,
+ 1398, 1405, 1410, 1421, 1425, 1441, 1455, 1459,
+ 1464, 1468, 1472, 1478, 1480, 1486, 1488, 1492,
+ 1494, 1500, 1505, 1510, 1520, 1522, 1524, 1528,
+ 1532, 1534, 1547, 1549, 1553, 1557, 1565, 1567,
+ 1571, 1573, 1574, 1577, 1582, 1584, 1586, 1590,
+ 1592, 1596, 1602, 1622, 1628, 1634, 1636, 1637,
+ 1647, 1648, 1656, 1663, 1665, 1668, 1670, 1672,
+ 1674, 1679, 1683, 1687, 1692, 1702, 1712, 1716,
+ 1720, 1734, 1760, 1770, 1772, 1774, 1777, 1779,
+ 1782, 1784, 1788, 1790, 1791, 1795, 1797, 1800,
+ 1807, 1815, 1817, 1819, 1823, 1825, 1831, 1842,
+ 1845, 1847, 1851, 1856, 1886, 1891, 1893, 1896,
+ 1901, 1915, 1922, 1936, 1941, 1954, 1958, 1971,
+ 1976, 1994, 1995, 2004, 2008, 2020, 2025, 2032,
+ 2039, 2046, 2048, 2052, 2074, 2079, 2080, 2084,
+ 2086, 2136, 2139, 2150, 2154, 2156, 2162, 2168,
+ 2170, 2175, 2177, 2181, 2183, 2184, 2186, 2188,
+ 2194, 2196, 2198, 2202, 2208, 2221, 2223, 2229,
+ 2233, 2241, 2252, 2260, 2263, 2293, 2299, 2302,
+ 2307, 2309, 2313, 2317, 2321, 2323, 2330, 2332,
+ 2341, 2348, 2356, 2358, 2378, 2390, 2394, 2396,
+ 2414, 2453, 2455, 2459, 2461, 2468, 2472, 2500,
+ 2502, 2504, 2506, 2508, 2511, 2513, 2517, 2521,
+ 2523, 2526, 2528, 2530, 2533, 2535, 2537, 2538,
+ 2540, 2542, 2546, 2550, 2553, 2566, 2568, 2574,
+ 2578, 2580, 2584, 2588, 2602, 2605, 2614, 2616,
+ 2620, 2626, 2626, 2628, 2630, 2639, 2645, 2652,
+ 2653, 2656, 2657, 2661, 2666, 2675, 2679, 2683,
+ 2691, 2693, 2695, 2697, 2700, 2732, 2734, 2736,
+ 2740, 2744, 2747, 2758, 2771, 2790, 2803, 2819,
+ 2831, 2847, 2862, 2883, 2893, 2905, 2916, 2930,
+ 2945, 2955, 2967, 2976, 2988, 2990, 2994, 3015,
+ 3024, 3034, 3040, 3046, 3047, 3096, 3098, 3102,
+ 3104, 3110, 3117, 3125, 3132, 3135, 3141, 3145,
+ 3149, 3151, 3155, 3159, 3163, 3169, 3177, 3185,
+ 3191, 3193, 3197, 3199, 3205, 3209, 3213, 3217,
+ 3221, 3226, 3233, 3239, 3241, 3243, 3247, 3249,
+ 3255, 3259, 3263, 3273, 3278, 3292, 3307, 3309,
+ 3317, 3319, 3324, 3338, 3343, 3345, 3349, 3350,
+ 3354, 3360, 3366, 3376, 3386, 3397, 3405, 3408,
+ 3411, 3415, 3419, 3421, 3424, 3424, 3427, 3429,
+ 3459, 3461, 3463, 3467, 3472, 3476, 3481, 3483,
+ 3485, 3487, 3496, 3500, 3504, 3510, 3512, 3520,
+ 3528, 3540, 3543, 3549, 3553, 3555, 3559, 3579,
+ 3581, 3583, 3594, 3600, 3602, 3604, 3606, 3610,
+ 3616, 3622, 3624, 3629, 3633, 3635, 3643, 3661,
+ 3701, 3711, 3715, 3717, 3719, 3720, 3724, 3728,
+ 3732, 3736, 3740, 3745, 3749, 3753, 3757, 3759,
+ 3761, 3765, 3775, 3779, 3781, 3785, 3789, 3793,
+ 3806, 3808, 3810, 3814, 3816, 3820, 3822, 3824,
+ 3854, 3858, 3862, 3866, 3869, 3876, 3881, 3892,
+ 3896, 3912, 3926, 3930, 3935, 3939, 3943, 3949,
+ 3951, 3957, 3959, 3963, 3965, 3971, 3976, 3981,
+ 3991, 3993, 3995, 3999, 4003, 4005, 4018, 4020,
+ 4024, 4028, 4036, 4038, 4042, 4044, 4045, 4048,
+ 4053, 4055, 4057, 4061, 4063, 4067, 4073, 4093,
+ 4099, 4105, 4107, 4108, 4118, 4119, 4127, 4134,
+ 4136, 4139, 4141, 4143, 4145, 4150, 4154, 4158,
+ 4163, 4173, 4183, 4187, 4191, 4205, 4231, 4241,
+ 4243, 4245, 4248, 4250, 4253, 4255, 4259, 4261,
+ 4262, 4266, 4268, 4270, 4277, 4281, 4288, 4295,
+ 4304, 4320, 4332, 4350, 4361, 4373, 4381, 4399,
+ 4407, 4437, 4440, 4450, 4460, 4472, 4483, 4492,
+ 4505, 4517, 4521, 4527, 4554, 4563, 4566, 4571,
+ 4577, 4582, 4603, 4607, 4613, 4613, 4620, 4629,
+ 4637, 4640, 4644, 4650, 4656, 4659, 4663, 4670,
+ 4676, 4685, 4694, 4698, 4702, 4706, 4710, 4717,
+ 4721, 4725, 4735, 4741, 4745, 4751, 4755, 4758,
+ 4764, 4770, 4782, 4786, 4790, 4800, 4804, 4815,
+ 4817, 4819, 4823, 4835, 4840, 4864, 4868, 4874,
+ 4896, 4905, 4909, 4912, 4913, 4921, 4929, 4935,
+ 4945, 4952, 4970, 4973, 4976, 4984, 4990, 4994,
+ 4998, 5002, 5008, 5016, 5021, 5027, 5031, 5039,
+ 5046, 5050, 5057, 5063, 5071, 5079, 5085, 5091,
+ 5102, 5106, 5118, 5127, 5144, 5161, 5164, 5168,
+ 5170, 5176, 5178, 5182, 5197, 5201, 5205, 5209,
+ 5213, 5217, 5219, 5225, 5230, 5234, 5240, 5247,
+ 5250, 5268, 5270, 5315, 5321, 5327, 5331, 5335,
+ 5341, 5345, 5351, 5357, 5364, 5366, 5372, 5378,
+ 5382, 5386, 5394, 5407, 5413, 5420, 5428, 5434,
+ 5443, 5449, 5453, 5458, 5462, 5470, 5474, 5478,
+ 5508, 5514, 5520, 5526, 5532, 5539, 5545, 5552,
+ 5557, 5567, 5571, 5578, 5584, 5588, 5595, 5599,
+ 5605, 5608, 5612, 5616, 5620, 5624, 5629, 5634,
+ 5638, 5649, 5653, 5657, 5663, 5671, 5675, 5692,
+ 5696, 5702, 5712, 5718, 5724, 5727, 5732, 5741,
+ 5745, 5749, 5755, 5759, 5765, 5773, 5791, 5792,
+ 5802, 5803, 5812, 5820, 5822, 5825, 5827, 5829,
+ 5831, 5836, 5849, 5853, 5868, 5897, 5908, 5910,
+ 5914, 5918, 5923, 5927, 5929, 5936, 5940, 5948,
+ 5952, 5964, 5966, 5968, 5970, 5972, 5974, 5975,
+ 5977, 5979, 5981, 5983, 5985, 5986, 5988, 5990,
+ 5992, 5994, 5996, 6000, 6006, 6006, 6008, 6010,
+ 6019, 6025, 6032, 6033, 6036, 6037, 6041, 6046,
+ 6055, 6059, 6063, 6071, 6073, 6075, 6077, 6080,
+ 6112, 6114, 6116, 6120, 6124, 6127, 6138, 6151,
+ 6170, 6183, 6199, 6211, 6227, 6242, 6263, 6273,
+ 6285, 6296, 6310, 6325, 6335, 6347, 6356, 6368,
+ 6370, 6374, 6395, 6404, 6414, 6420, 6426, 6427,
+ 6476, 6478, 6482, 6484, 6490, 6497, 6505, 6512,
+ 6515, 6521, 6525, 6529, 6531, 6535, 6539, 6543,
+ 6549, 6557, 6565, 6571, 6573, 6577, 6579, 6585,
+ 6589, 6593, 6597, 6601, 6606, 6613, 6619, 6621,
+ 6623, 6627, 6629, 6635, 6639, 6643, 6653, 6658,
+ 6672, 6687, 6689, 6697, 6699, 6704, 6718, 6723,
+ 6725, 6729, 6730, 6734, 6740, 6746, 6756, 6766,
+ 6777, 6785, 6788, 6791, 6795, 6799, 6801, 6804,
+ 6804, 6807, 6809, 6839, 6841, 6843, 6847, 6852,
+ 6856, 6861, 6863, 6865, 6867, 6876, 6880, 6884,
+ 6890, 6892, 6900, 6908, 6920, 6923, 6929, 6933,
+ 6935, 6939, 6959, 6961, 6963, 6974, 6980, 6982,
+ 6984, 6986, 6990, 6996, 7002, 7004, 7009, 7013,
+ 7015, 7023, 7041, 7081, 7091, 7095, 7097, 7099,
+ 7100, 7104, 7108, 7112, 7116, 7120, 7125, 7129,
+ 7133, 7137, 7139, 7141, 7145, 7155, 7159, 7161,
+ 7165, 7169, 7173, 7186, 7188, 7190, 7194, 7196,
+ 7200, 7202, 7204, 7234, 7238, 7242, 7246, 7249,
+ 7256, 7261, 7272, 7276, 7292, 7306, 7310, 7315,
+ 7319, 7323, 7329, 7331, 7337, 7339, 7343, 7345,
+ 7351, 7356, 7361, 7371, 7373, 7375, 7379, 7383,
+ 7385, 7398, 7400, 7404, 7408, 7416, 7418, 7422,
+ 7424, 7425, 7428, 7433, 7435, 7437, 7441, 7443,
+ 7447, 7453, 7473, 7479, 7485, 7487, 7488, 7498,
+ 7499, 7507, 7514, 7516, 7519, 7521, 7523, 7525,
+ 7530, 7534, 7538, 7543, 7553, 7563, 7567, 7571,
+ 7585, 7611, 7621, 7623, 7625, 7628, 7630, 7633,
+ 7635, 7639, 7641, 7642, 7646, 7648, 7650, 7657,
+ 7661, 7668, 7675, 7684, 7700, 7712, 7730, 7741,
+ 7753, 7761, 7779, 7787, 7817, 7820, 7830, 7840,
+ 7852, 7863, 7872, 7885, 7897, 7901, 7907, 7934,
+ 7943, 7946, 7951, 7957, 7962, 7983, 7987, 7993,
+ 7993, 8000, 8009, 8017, 8020, 8024, 8030, 8036,
+ 8039, 8043, 8050, 8056, 8065, 8074, 8078, 8082,
+ 8086, 8090, 8097, 8101, 8105, 8115, 8121, 8125,
+ 8131, 8135, 8138, 8144, 8150, 8162, 8166, 8170,
+ 8180, 8184, 8195, 8197, 8199, 8203, 8215, 8220,
+ 8244, 8248, 8254, 8276, 8285, 8289, 8292, 8293,
+ 8301, 8309, 8315, 8325, 8332, 8350, 8353, 8356,
+ 8364, 8370, 8374, 8378, 8382, 8388, 8396, 8401,
+ 8407, 8411, 8419, 8426, 8430, 8437, 8443, 8451,
+ 8459, 8465, 8471, 8482, 8486, 8498, 8507, 8524,
+ 8541, 8544, 8548, 8550, 8556, 8558, 8562, 8577,
+ 8581, 8585, 8589, 8593, 8597, 8599, 8605, 8610,
+ 8614, 8620, 8627, 8630, 8648, 8650, 8695, 8701,
+ 8707, 8711, 8715, 8721, 8725, 8731, 8737, 8744,
+ 8746, 8752, 8758, 8762, 8766, 8774, 8787, 8793,
+ 8800, 8808, 8814, 8823, 8829, 8833, 8838, 8842,
+ 8850, 8854, 8858, 8888, 8894, 8900, 8906, 8912,
+ 8919, 8925, 8932, 8937, 8947, 8951, 8958, 8964,
+ 8968, 8975, 8979, 8985, 8988, 8992, 8996, 9000,
+ 9004, 9009, 9014, 9018, 9029, 9033, 9037, 9043,
+ 9051, 9055, 9072, 9076, 9082, 9092, 9098, 9104,
+ 9107, 9112, 9121, 9125, 9129, 9135, 9139, 9145,
+ 9153, 9171, 9172, 9182, 9183, 9192, 9200, 9202,
+ 9205, 9207, 9209, 9211, 9216, 9229, 9233, 9248,
+ 9277, 9288, 9290, 9294, 9298, 9303, 9307, 9309,
+ 9316, 9320, 9328, 9332, 9408, 9410, 9411, 9412,
+ 9413, 9414, 9415, 9417, 9422, 9423, 9425, 9427,
+ 9428, 9472, 9473, 9474, 9476, 9481, 9485, 9485,
+ 9487, 9489, 9500, 9510, 9518, 9519, 9521, 9522,
+ 9526, 9530, 9540, 9544, 9551, 9562, 9569, 9573,
+ 9579, 9590, 9622, 9671, 9686, 9701, 9706, 9708,
+ 9713, 9745, 9753, 9755, 9777, 9799, 9801, 9817,
+ 9833, 9835, 9837, 9837, 9838, 9839, 9840, 9842,
+ 9843, 9855, 9857, 9859, 9861, 9875, 9889, 9891,
+ 9894, 9897, 9899, 9900, 9901, 9903, 9905, 9907,
+ 9921, 9935, 9937, 9940, 9943, 9945, 9946, 9947,
+ 9949, 9951, 9953, 10002, 10046, 10048, 10053, 10057,
+ 10057, 10059, 10061, 10072, 10082, 10090, 10091, 10093,
+ 10094, 10098, 10102, 10112, 10116, 10123, 10134, 10141,
+ 10145, 10151, 10162, 10194, 10243, 10258, 10273, 10278,
+ 10280, 10285, 10317, 10325, 10327, 10349, 10371,
+}
+
+var _hcltok_trans_keys []byte = []byte{
+ 46, 42, 42, 47, 46, 69, 101, 48,
+ 57, 43, 45, 48, 57, 48, 57, 45,
+ 95, 194, 195, 198, 199, 203, 205, 206,
+ 207, 210, 212, 213, 214, 215, 216, 217,
+ 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 233, 234, 237, 239, 240, 65,
+ 90, 97, 122, 196, 202, 208, 218, 229,
+ 236, 95, 194, 195, 198, 199, 203, 205,
+ 206, 207, 210, 212, 213, 214, 215, 216,
+ 217, 219, 220, 221, 222, 223, 224, 225,
+ 226, 227, 228, 233, 234, 237, 239, 240,
+ 65, 90, 97, 122, 196, 202, 208, 218,
+ 229, 236, 10, 13, 45, 95, 194, 195,
+ 198, 199, 203, 204, 205, 206, 207, 210,
+ 212, 213, 214, 215, 216, 217, 219, 220,
+ 221, 222, 223, 224, 225, 226, 227, 228,
+ 233, 234, 237, 239, 240, 243, 48, 57,
+ 65, 90, 97, 122, 196, 218, 229, 236,
+ 10, 170, 181, 183, 186, 128, 150, 152,
+ 182, 184, 255, 192, 255, 0, 127, 173,
+ 130, 133, 146, 159, 165, 171, 175, 255,
+ 181, 190, 184, 185, 192, 255, 140, 134,
+ 138, 142, 161, 163, 255, 182, 130, 136,
+ 137, 176, 151, 152, 154, 160, 190, 136,
+ 144, 192, 255, 135, 129, 130, 132, 133,
+ 144, 170, 176, 178, 144, 154, 160, 191,
+ 128, 169, 174, 255, 148, 169, 157, 158,
+ 189, 190, 192, 255, 144, 255, 139, 140,
+ 178, 255, 186, 128, 181, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 128, 173, 128,
+ 155, 160, 180, 182, 189, 148, 161, 163,
+ 255, 176, 164, 165, 132, 169, 177, 141,
+ 142, 145, 146, 179, 181, 186, 187, 158,
+ 133, 134, 137, 138, 143, 150, 152, 155,
+ 164, 165, 178, 255, 188, 129, 131, 133,
+ 138, 143, 144, 147, 168, 170, 176, 178,
+ 179, 181, 182, 184, 185, 190, 255, 157,
+ 131, 134, 137, 138, 142, 144, 146, 152,
+ 159, 165, 182, 255, 129, 131, 133, 141,
+ 143, 145, 147, 168, 170, 176, 178, 179,
+ 181, 185, 188, 255, 134, 138, 142, 143,
+ 145, 159, 164, 165, 176, 184, 186, 255,
+ 129, 131, 133, 140, 143, 144, 147, 168,
+ 170, 176, 178, 179, 181, 185, 188, 191,
+ 177, 128, 132, 135, 136, 139, 141, 150,
+ 151, 156, 157, 159, 163, 166, 175, 156,
+ 130, 131, 133, 138, 142, 144, 146, 149,
+ 153, 154, 158, 159, 163, 164, 168, 170,
+ 174, 185, 190, 191, 144, 151, 128, 130,
+ 134, 136, 138, 141, 166, 175, 128, 131,
+ 133, 140, 142, 144, 146, 168, 170, 185,
+ 189, 255, 133, 137, 151, 142, 148, 155,
+ 159, 164, 165, 176, 255, 128, 131, 133,
+ 140, 142, 144, 146, 168, 170, 179, 181,
+ 185, 188, 191, 158, 128, 132, 134, 136,
+ 138, 141, 149, 150, 160, 163, 166, 175,
+ 177, 178, 129, 131, 133, 140, 142, 144,
+ 146, 186, 189, 255, 133, 137, 143, 147,
+ 152, 158, 164, 165, 176, 185, 192, 255,
+ 189, 130, 131, 133, 150, 154, 177, 179,
+ 187, 138, 150, 128, 134, 143, 148, 152,
+ 159, 166, 175, 178, 179, 129, 186, 128,
+ 142, 144, 153, 132, 138, 141, 165, 167,
+ 129, 130, 135, 136, 148, 151, 153, 159,
+ 161, 163, 170, 171, 173, 185, 187, 189,
+ 134, 128, 132, 136, 141, 144, 153, 156,
+ 159, 128, 181, 183, 185, 152, 153, 160,
+ 169, 190, 191, 128, 135, 137, 172, 177,
+ 191, 128, 132, 134, 151, 153, 188, 134,
+ 128, 129, 130, 131, 137, 138, 139, 140,
+ 141, 142, 143, 144, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 173, 175,
+ 176, 177, 178, 179, 181, 182, 183, 188,
+ 189, 190, 191, 132, 152, 172, 184, 185,
+ 187, 128, 191, 128, 137, 144, 255, 158,
+ 159, 134, 187, 136, 140, 142, 143, 137,
+ 151, 153, 142, 143, 158, 159, 137, 177,
+ 142, 143, 182, 183, 191, 255, 128, 130,
+ 133, 136, 150, 152, 255, 145, 150, 151,
+ 155, 156, 160, 168, 178, 255, 128, 143,
+ 160, 255, 182, 183, 190, 255, 129, 255,
+ 173, 174, 192, 255, 129, 154, 160, 255,
+ 171, 173, 185, 255, 128, 140, 142, 148,
+ 160, 180, 128, 147, 160, 172, 174, 176,
+ 178, 179, 148, 150, 152, 155, 158, 159,
+ 170, 255, 139, 141, 144, 153, 160, 255,
+ 184, 255, 128, 170, 176, 255, 182, 255,
+ 128, 158, 160, 171, 176, 187, 134, 173,
+ 176, 180, 128, 171, 176, 255, 138, 143,
+ 155, 255, 128, 155, 160, 255, 159, 189,
+ 190, 192, 255, 167, 128, 137, 144, 153,
+ 176, 189, 140, 143, 154, 170, 180, 255,
+ 180, 255, 128, 183, 128, 137, 141, 189,
+ 128, 136, 144, 146, 148, 182, 184, 185,
+ 128, 181, 187, 191, 150, 151, 158, 159,
+ 152, 154, 156, 158, 134, 135, 142, 143,
+ 190, 255, 190, 128, 180, 182, 188, 130,
+ 132, 134, 140, 144, 147, 150, 155, 160,
+ 172, 178, 180, 182, 188, 128, 129, 130,
+ 131, 132, 133, 134, 176, 177, 178, 179,
+ 180, 181, 182, 183, 191, 255, 129, 147,
+ 149, 176, 178, 190, 192, 255, 144, 156,
+ 161, 144, 156, 165, 176, 130, 135, 149,
+ 164, 166, 168, 138, 147, 152, 157, 170,
+ 185, 188, 191, 142, 133, 137, 160, 255,
+ 137, 255, 128, 174, 176, 255, 159, 165,
+ 170, 180, 255, 167, 173, 128, 165, 176,
+ 255, 168, 174, 176, 190, 192, 255, 128,
+ 150, 160, 166, 168, 174, 176, 182, 184,
+ 190, 128, 134, 136, 142, 144, 150, 152,
+ 158, 160, 191, 128, 129, 130, 131, 132,
+ 133, 134, 135, 144, 145, 255, 133, 135,
+ 161, 175, 177, 181, 184, 188, 160, 151,
+ 152, 187, 192, 255, 133, 173, 177, 255,
+ 143, 159, 187, 255, 176, 191, 182, 183,
+ 184, 191, 192, 255, 150, 255, 128, 146,
+ 147, 148, 152, 153, 154, 155, 156, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 129, 255, 141, 255, 144, 189,
+ 141, 143, 172, 255, 191, 128, 175, 180,
+ 189, 151, 159, 162, 255, 175, 137, 138,
+ 184, 255, 183, 255, 168, 255, 128, 179,
+ 188, 134, 143, 154, 159, 184, 186, 190,
+ 255, 128, 173, 176, 255, 148, 159, 189,
+ 255, 129, 142, 154, 159, 191, 255, 128,
+ 182, 128, 141, 144, 153, 160, 182, 186,
+ 255, 128, 130, 155, 157, 160, 175, 178,
+ 182, 129, 134, 137, 142, 145, 150, 160,
+ 166, 168, 174, 176, 255, 155, 166, 175,
+ 128, 170, 172, 173, 176, 185, 158, 159,
+ 160, 255, 164, 175, 135, 138, 188, 255,
+ 164, 169, 171, 172, 173, 174, 175, 180,
+ 181, 182, 183, 184, 185, 187, 188, 189,
+ 190, 191, 165, 186, 174, 175, 154, 255,
+ 190, 128, 134, 147, 151, 157, 168, 170,
+ 182, 184, 188, 128, 129, 131, 132, 134,
+ 255, 147, 255, 190, 255, 144, 145, 136,
+ 175, 188, 255, 128, 143, 160, 175, 179,
+ 180, 141, 143, 176, 180, 182, 255, 189,
+ 255, 191, 144, 153, 161, 186, 129, 154,
+ 166, 255, 191, 255, 130, 135, 138, 143,
+ 146, 151, 154, 156, 144, 145, 146, 147,
+ 148, 150, 151, 152, 155, 157, 158, 160,
+ 170, 171, 172, 175, 161, 169, 128, 129,
+ 130, 131, 133, 135, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149,
+ 152, 156, 157, 160, 161, 162, 163, 164,
+ 166, 168, 169, 170, 171, 172, 173, 174,
+ 176, 177, 153, 155, 178, 179, 128, 139,
+ 141, 166, 168, 186, 188, 189, 191, 255,
+ 142, 143, 158, 255, 187, 255, 128, 180,
+ 189, 128, 156, 160, 255, 145, 159, 161,
+ 255, 128, 159, 176, 255, 139, 143, 187,
+ 255, 128, 157, 160, 255, 144, 132, 135,
+ 150, 255, 158, 159, 170, 175, 148, 151,
+ 188, 255, 128, 167, 176, 255, 164, 255,
+ 183, 255, 128, 149, 160, 167, 136, 188,
+ 128, 133, 138, 181, 183, 184, 191, 255,
+ 150, 159, 183, 255, 128, 158, 160, 178,
+ 180, 181, 128, 149, 160, 185, 128, 183,
+ 190, 191, 191, 128, 131, 133, 134, 140,
+ 147, 149, 151, 153, 179, 184, 186, 160,
+ 188, 128, 156, 128, 135, 137, 166, 128,
+ 181, 128, 149, 160, 178, 128, 145, 128,
+ 178, 129, 130, 131, 132, 133, 135, 136,
+ 138, 139, 140, 141, 144, 145, 146, 147,
+ 150, 151, 152, 153, 154, 155, 156, 162,
+ 163, 171, 176, 177, 178, 128, 134, 135,
+ 165, 176, 190, 144, 168, 176, 185, 128,
+ 180, 182, 191, 182, 144, 179, 155, 133,
+ 137, 141, 143, 157, 255, 190, 128, 145,
+ 147, 183, 136, 128, 134, 138, 141, 143,
+ 157, 159, 168, 176, 255, 171, 175, 186,
+ 255, 128, 131, 133, 140, 143, 144, 147,
+ 168, 170, 176, 178, 179, 181, 185, 188,
+ 191, 144, 151, 128, 132, 135, 136, 139,
+ 141, 157, 163, 166, 172, 176, 180, 128,
+ 138, 144, 153, 134, 136, 143, 154, 255,
+ 128, 181, 184, 255, 129, 151, 158, 255,
+ 129, 131, 133, 143, 154, 255, 128, 137,
+ 128, 153, 157, 171, 176, 185, 160, 255,
+ 170, 190, 192, 255, 128, 184, 128, 136,
+ 138, 182, 184, 191, 128, 144, 153, 178,
+ 255, 168, 144, 145, 183, 255, 128, 142,
+ 145, 149, 129, 141, 144, 146, 147, 148,
+ 175, 255, 132, 255, 128, 144, 129, 143,
+ 144, 153, 145, 152, 135, 255, 160, 168,
+ 169, 171, 172, 173, 174, 188, 189, 190,
+ 191, 161, 167, 185, 255, 128, 158, 160,
+ 169, 144, 173, 176, 180, 128, 131, 144,
+ 153, 163, 183, 189, 255, 144, 255, 133,
+ 143, 191, 255, 143, 159, 160, 128, 129,
+ 255, 159, 160, 171, 172, 255, 173, 255,
+ 179, 255, 128, 176, 177, 178, 128, 129,
+ 171, 175, 189, 255, 128, 136, 144, 153,
+ 157, 158, 133, 134, 137, 144, 145, 146,
+ 147, 148, 149, 154, 155, 156, 157, 158,
+ 159, 168, 169, 170, 150, 153, 165, 169,
+ 173, 178, 187, 255, 131, 132, 140, 169,
+ 174, 255, 130, 132, 149, 157, 173, 186,
+ 188, 160, 161, 163, 164, 167, 168, 132,
+ 134, 149, 157, 186, 139, 140, 191, 255,
+ 134, 128, 132, 138, 144, 146, 255, 166,
+ 167, 129, 155, 187, 149, 181, 143, 175,
+ 137, 169, 131, 140, 141, 192, 255, 128,
+ 182, 187, 255, 173, 180, 182, 255, 132,
+ 155, 159, 161, 175, 128, 160, 163, 164,
+ 165, 184, 185, 186, 161, 162, 128, 134,
+ 136, 152, 155, 161, 163, 164, 166, 170,
+ 133, 143, 151, 255, 139, 143, 154, 255,
+ 164, 167, 185, 187, 128, 131, 133, 159,
+ 161, 162, 169, 178, 180, 183, 130, 135,
+ 137, 139, 148, 151, 153, 155, 157, 159,
+ 164, 190, 141, 143, 145, 146, 161, 162,
+ 167, 170, 172, 178, 180, 183, 185, 188,
+ 128, 137, 139, 155, 161, 163, 165, 169,
+ 171, 187, 155, 156, 151, 255, 156, 157,
+ 160, 181, 255, 186, 187, 255, 162, 255,
+ 160, 168, 161, 167, 158, 255, 160, 132,
+ 135, 133, 134, 176, 255, 170, 181, 186,
+ 191, 176, 180, 182, 183, 186, 189, 134,
+ 140, 136, 138, 142, 161, 163, 255, 130,
+ 137, 136, 255, 144, 170, 176, 178, 160,
+ 191, 128, 138, 174, 175, 177, 255, 148,
+ 150, 164, 167, 173, 176, 185, 189, 190,
+ 192, 255, 144, 146, 175, 141, 255, 166,
+ 176, 178, 255, 186, 138, 170, 180, 181,
+ 160, 161, 162, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 184, 186,
+ 187, 188, 189, 190, 183, 185, 154, 164,
+ 168, 128, 149, 128, 152, 189, 132, 185,
+ 144, 152, 161, 177, 255, 169, 177, 129,
+ 132, 141, 142, 145, 146, 179, 181, 186,
+ 188, 190, 255, 142, 156, 157, 159, 161,
+ 176, 177, 133, 138, 143, 144, 147, 168,
+ 170, 176, 178, 179, 181, 182, 184, 185,
+ 158, 153, 156, 178, 180, 189, 133, 141,
+ 143, 145, 147, 168, 170, 176, 178, 179,
+ 181, 185, 144, 185, 160, 161, 189, 133,
+ 140, 143, 144, 147, 168, 170, 176, 178,
+ 179, 181, 185, 177, 156, 157, 159, 161,
+ 131, 156, 133, 138, 142, 144, 146, 149,
+ 153, 154, 158, 159, 163, 164, 168, 170,
+ 174, 185, 144, 189, 133, 140, 142, 144,
+ 146, 168, 170, 185, 152, 154, 160, 161,
+ 128, 189, 133, 140, 142, 144, 146, 168,
+ 170, 179, 181, 185, 158, 160, 161, 177,
+ 178, 189, 133, 140, 142, 144, 146, 186,
+ 142, 148, 150, 159, 161, 186, 191, 189,
+ 133, 150, 154, 177, 179, 187, 128, 134,
+ 129, 176, 178, 179, 132, 138, 141, 165,
+ 167, 189, 129, 130, 135, 136, 148, 151,
+ 153, 159, 161, 163, 170, 171, 173, 176,
+ 178, 179, 134, 128, 132, 156, 159, 128,
+ 128, 135, 137, 172, 136, 140, 128, 129,
+ 130, 131, 137, 138, 139, 140, 141, 142,
+ 143, 144, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 184,
+ 188, 189, 190, 191, 132, 152, 185, 187,
+ 191, 128, 170, 161, 144, 149, 154, 157,
+ 165, 166, 174, 176, 181, 255, 130, 141,
+ 143, 159, 155, 255, 128, 140, 142, 145,
+ 160, 177, 128, 145, 160, 172, 174, 176,
+ 151, 156, 170, 128, 168, 176, 255, 138,
+ 255, 128, 150, 160, 255, 149, 255, 167,
+ 133, 179, 133, 139, 131, 160, 174, 175,
+ 186, 255, 166, 255, 128, 163, 141, 143,
+ 154, 189, 169, 172, 174, 177, 181, 182,
+ 129, 130, 132, 133, 134, 176, 177, 178,
+ 179, 180, 181, 182, 183, 177, 191, 165,
+ 170, 175, 177, 180, 255, 168, 174, 176,
+ 255, 128, 134, 136, 142, 144, 150, 152,
+ 158, 128, 129, 130, 131, 132, 133, 134,
+ 135, 144, 145, 255, 133, 135, 161, 169,
+ 177, 181, 184, 188, 160, 151, 154, 128,
+ 146, 147, 148, 152, 153, 154, 155, 156,
+ 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 129, 255, 141, 143, 160,
+ 169, 172, 255, 191, 128, 174, 130, 134,
+ 139, 163, 255, 130, 179, 187, 189, 178,
+ 183, 138, 165, 176, 255, 135, 159, 189,
+ 255, 132, 178, 143, 160, 164, 166, 175,
+ 186, 190, 128, 168, 186, 128, 130, 132,
+ 139, 160, 182, 190, 255, 176, 178, 180,
+ 183, 184, 190, 255, 128, 130, 155, 157,
+ 160, 170, 178, 180, 128, 162, 164, 169,
+ 171, 172, 173, 174, 175, 180, 181, 182,
+ 183, 185, 186, 187, 188, 189, 190, 191,
+ 165, 179, 157, 190, 128, 134, 147, 151,
+ 159, 168, 170, 182, 184, 188, 176, 180,
+ 182, 255, 161, 186, 144, 145, 146, 147,
+ 148, 150, 151, 152, 155, 157, 158, 160,
+ 170, 171, 172, 175, 161, 169, 128, 129,
+ 130, 131, 133, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 152,
+ 156, 157, 160, 161, 162, 163, 164, 166,
+ 168, 169, 170, 171, 172, 173, 174, 176,
+ 177, 153, 155, 178, 179, 145, 255, 139,
+ 143, 182, 255, 158, 175, 128, 144, 147,
+ 149, 151, 153, 179, 128, 135, 137, 164,
+ 128, 130, 131, 132, 133, 134, 135, 136,
+ 138, 139, 140, 141, 144, 145, 146, 147,
+ 150, 151, 152, 153, 154, 156, 162, 163,
+ 171, 176, 177, 178, 131, 183, 131, 175,
+ 144, 168, 131, 166, 182, 144, 178, 131,
+ 178, 154, 156, 129, 132, 128, 145, 147,
+ 171, 159, 255, 144, 157, 161, 135, 138,
+ 128, 175, 135, 132, 133, 128, 174, 152,
+ 155, 132, 128, 170, 128, 153, 160, 190,
+ 192, 255, 128, 136, 138, 174, 128, 178,
+ 255, 160, 168, 169, 171, 172, 173, 174,
+ 188, 189, 190, 191, 161, 167, 144, 173,
+ 128, 131, 163, 183, 189, 255, 133, 143,
+ 145, 255, 147, 159, 128, 176, 177, 178,
+ 128, 136, 144, 153, 144, 145, 146, 147,
+ 148, 149, 154, 155, 156, 157, 158, 159,
+ 150, 153, 131, 140, 255, 160, 163, 164,
+ 165, 184, 185, 186, 161, 162, 133, 255,
+ 170, 181, 183, 186, 128, 150, 152, 182,
+ 184, 255, 192, 255, 0, 127, 173, 130,
+ 133, 146, 159, 165, 171, 175, 255, 181,
+ 190, 184, 185, 192, 255, 140, 134, 138,
+ 142, 161, 163, 255, 182, 130, 136, 137,
+ 176, 151, 152, 154, 160, 190, 136, 144,
+ 192, 255, 135, 129, 130, 132, 133, 144,
+ 170, 176, 178, 144, 154, 160, 191, 128,
+ 169, 174, 255, 148, 169, 157, 158, 189,
+ 190, 192, 255, 144, 255, 139, 140, 178,
+ 255, 186, 128, 181, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 128, 173, 128, 155,
+ 160, 180, 182, 189, 148, 161, 163, 255,
+ 176, 164, 165, 132, 169, 177, 141, 142,
+ 145, 146, 179, 181, 186, 187, 158, 133,
+ 134, 137, 138, 143, 150, 152, 155, 164,
+ 165, 178, 255, 188, 129, 131, 133, 138,
+ 143, 144, 147, 168, 170, 176, 178, 179,
+ 181, 182, 184, 185, 190, 255, 157, 131,
+ 134, 137, 138, 142, 144, 146, 152, 159,
+ 165, 182, 255, 129, 131, 133, 141, 143,
+ 145, 147, 168, 170, 176, 178, 179, 181,
+ 185, 188, 255, 134, 138, 142, 143, 145,
+ 159, 164, 165, 176, 184, 186, 255, 129,
+ 131, 133, 140, 143, 144, 147, 168, 170,
+ 176, 178, 179, 181, 185, 188, 191, 177,
+ 128, 132, 135, 136, 139, 141, 150, 151,
+ 156, 157, 159, 163, 166, 175, 156, 130,
+ 131, 133, 138, 142, 144, 146, 149, 153,
+ 154, 158, 159, 163, 164, 168, 170, 174,
+ 185, 190, 191, 144, 151, 128, 130, 134,
+ 136, 138, 141, 166, 175, 128, 131, 133,
+ 140, 142, 144, 146, 168, 170, 185, 189,
+ 255, 133, 137, 151, 142, 148, 155, 159,
+ 164, 165, 176, 255, 128, 131, 133, 140,
+ 142, 144, 146, 168, 170, 179, 181, 185,
+ 188, 191, 158, 128, 132, 134, 136, 138,
+ 141, 149, 150, 160, 163, 166, 175, 177,
+ 178, 129, 131, 133, 140, 142, 144, 146,
+ 186, 189, 255, 133, 137, 143, 147, 152,
+ 158, 164, 165, 176, 185, 192, 255, 189,
+ 130, 131, 133, 150, 154, 177, 179, 187,
+ 138, 150, 128, 134, 143, 148, 152, 159,
+ 166, 175, 178, 179, 129, 186, 128, 142,
+ 144, 153, 132, 138, 141, 165, 167, 129,
+ 130, 135, 136, 148, 151, 153, 159, 161,
+ 163, 170, 171, 173, 185, 187, 189, 134,
+ 128, 132, 136, 141, 144, 153, 156, 159,
+ 128, 181, 183, 185, 152, 153, 160, 169,
+ 190, 191, 128, 135, 137, 172, 177, 191,
+ 128, 132, 134, 151, 153, 188, 134, 128,
+ 129, 130, 131, 137, 138, 139, 140, 141,
+ 142, 143, 144, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 173, 175, 176,
+ 177, 178, 179, 181, 182, 183, 188, 189,
+ 190, 191, 132, 152, 172, 184, 185, 187,
+ 128, 191, 128, 137, 144, 255, 158, 159,
+ 134, 187, 136, 140, 142, 143, 137, 151,
+ 153, 142, 143, 158, 159, 137, 177, 142,
+ 143, 182, 183, 191, 255, 128, 130, 133,
+ 136, 150, 152, 255, 145, 150, 151, 155,
+ 156, 160, 168, 178, 255, 128, 143, 160,
+ 255, 182, 183, 190, 255, 129, 255, 173,
+ 174, 192, 255, 129, 154, 160, 255, 171,
+ 173, 185, 255, 128, 140, 142, 148, 160,
+ 180, 128, 147, 160, 172, 174, 176, 178,
+ 179, 148, 150, 152, 155, 158, 159, 170,
+ 255, 139, 141, 144, 153, 160, 255, 184,
+ 255, 128, 170, 176, 255, 182, 255, 128,
+ 158, 160, 171, 176, 187, 134, 173, 176,
+ 180, 128, 171, 176, 255, 138, 143, 155,
+ 255, 128, 155, 160, 255, 159, 189, 190,
+ 192, 255, 167, 128, 137, 144, 153, 176,
+ 189, 140, 143, 154, 170, 180, 255, 180,
+ 255, 128, 183, 128, 137, 141, 189, 128,
+ 136, 144, 146, 148, 182, 184, 185, 128,
+ 181, 187, 191, 150, 151, 158, 159, 152,
+ 154, 156, 158, 134, 135, 142, 143, 190,
+ 255, 190, 128, 180, 182, 188, 130, 132,
+ 134, 140, 144, 147, 150, 155, 160, 172,
+ 178, 180, 182, 188, 128, 129, 130, 131,
+ 132, 133, 134, 176, 177, 178, 179, 180,
+ 181, 182, 183, 191, 255, 129, 147, 149,
+ 176, 178, 190, 192, 255, 144, 156, 161,
+ 144, 156, 165, 176, 130, 135, 149, 164,
+ 166, 168, 138, 147, 152, 157, 170, 185,
+ 188, 191, 142, 133, 137, 160, 255, 137,
+ 255, 128, 174, 176, 255, 159, 165, 170,
+ 180, 255, 167, 173, 128, 165, 176, 255,
+ 168, 174, 176, 190, 192, 255, 128, 150,
+ 160, 166, 168, 174, 176, 182, 184, 190,
+ 128, 134, 136, 142, 144, 150, 152, 158,
+ 160, 191, 128, 129, 130, 131, 132, 133,
+ 134, 135, 144, 145, 255, 133, 135, 161,
+ 175, 177, 181, 184, 188, 160, 151, 152,
+ 187, 192, 255, 133, 173, 177, 255, 143,
+ 159, 187, 255, 176, 191, 182, 183, 184,
+ 191, 192, 255, 150, 255, 128, 146, 147,
+ 148, 152, 153, 154, 155, 156, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 129, 255, 141, 255, 144, 189, 141,
+ 143, 172, 255, 191, 128, 175, 180, 189,
+ 151, 159, 162, 255, 175, 137, 138, 184,
+ 255, 183, 255, 168, 255, 128, 179, 188,
+ 134, 143, 154, 159, 184, 186, 190, 255,
+ 128, 173, 176, 255, 148, 159, 189, 255,
+ 129, 142, 154, 159, 191, 255, 128, 182,
+ 128, 141, 144, 153, 160, 182, 186, 255,
+ 128, 130, 155, 157, 160, 175, 178, 182,
+ 129, 134, 137, 142, 145, 150, 160, 166,
+ 168, 174, 176, 255, 155, 166, 175, 128,
+ 170, 172, 173, 176, 185, 158, 159, 160,
+ 255, 164, 175, 135, 138, 188, 255, 164,
+ 169, 171, 172, 173, 174, 175, 180, 181,
+ 182, 183, 184, 185, 187, 188, 189, 190,
+ 191, 165, 186, 174, 175, 154, 255, 190,
+ 128, 134, 147, 151, 157, 168, 170, 182,
+ 184, 188, 128, 129, 131, 132, 134, 255,
+ 147, 255, 190, 255, 144, 145, 136, 175,
+ 188, 255, 128, 143, 160, 175, 179, 180,
+ 141, 143, 176, 180, 182, 255, 189, 255,
+ 191, 144, 153, 161, 186, 129, 154, 166,
+ 255, 191, 255, 130, 135, 138, 143, 146,
+ 151, 154, 156, 144, 145, 146, 147, 148,
+ 150, 151, 152, 155, 157, 158, 160, 170,
+ 171, 172, 175, 161, 169, 128, 129, 130,
+ 131, 133, 135, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 152,
+ 156, 157, 160, 161, 162, 163, 164, 166,
+ 168, 169, 170, 171, 172, 173, 174, 176,
+ 177, 153, 155, 178, 179, 128, 139, 141,
+ 166, 168, 186, 188, 189, 191, 255, 142,
+ 143, 158, 255, 187, 255, 128, 180, 189,
+ 128, 156, 160, 255, 145, 159, 161, 255,
+ 128, 159, 176, 255, 139, 143, 187, 255,
+ 128, 157, 160, 255, 144, 132, 135, 150,
+ 255, 158, 159, 170, 175, 148, 151, 188,
+ 255, 128, 167, 176, 255, 164, 255, 183,
+ 255, 128, 149, 160, 167, 136, 188, 128,
+ 133, 138, 181, 183, 184, 191, 255, 150,
+ 159, 183, 255, 128, 158, 160, 178, 180,
+ 181, 128, 149, 160, 185, 128, 183, 190,
+ 191, 191, 128, 131, 133, 134, 140, 147,
+ 149, 151, 153, 179, 184, 186, 160, 188,
+ 128, 156, 128, 135, 137, 166, 128, 181,
+ 128, 149, 160, 178, 128, 145, 128, 178,
+ 129, 130, 131, 132, 133, 135, 136, 138,
+ 139, 140, 141, 144, 145, 146, 147, 150,
+ 151, 152, 153, 154, 155, 156, 162, 163,
+ 171, 176, 177, 178, 128, 134, 135, 165,
+ 176, 190, 144, 168, 176, 185, 128, 180,
+ 182, 191, 182, 144, 179, 155, 133, 137,
+ 141, 143, 157, 255, 190, 128, 145, 147,
+ 183, 136, 128, 134, 138, 141, 143, 157,
+ 159, 168, 176, 255, 171, 175, 186, 255,
+ 128, 131, 133, 140, 143, 144, 147, 168,
+ 170, 176, 178, 179, 181, 185, 188, 191,
+ 144, 151, 128, 132, 135, 136, 139, 141,
+ 157, 163, 166, 172, 176, 180, 128, 138,
+ 144, 153, 134, 136, 143, 154, 255, 128,
+ 181, 184, 255, 129, 151, 158, 255, 129,
+ 131, 133, 143, 154, 255, 128, 137, 128,
+ 153, 157, 171, 176, 185, 160, 255, 170,
+ 190, 192, 255, 128, 184, 128, 136, 138,
+ 182, 184, 191, 128, 144, 153, 178, 255,
+ 168, 144, 145, 183, 255, 128, 142, 145,
+ 149, 129, 141, 144, 146, 147, 148, 175,
+ 255, 132, 255, 128, 144, 129, 143, 144,
+ 153, 145, 152, 135, 255, 160, 168, 169,
+ 171, 172, 173, 174, 188, 189, 190, 191,
+ 161, 167, 185, 255, 128, 158, 160, 169,
+ 144, 173, 176, 180, 128, 131, 144, 153,
+ 163, 183, 189, 255, 144, 255, 133, 143,
+ 191, 255, 143, 159, 160, 128, 129, 255,
+ 159, 160, 171, 172, 255, 173, 255, 179,
+ 255, 128, 176, 177, 178, 128, 129, 171,
+ 175, 189, 255, 128, 136, 144, 153, 157,
+ 158, 133, 134, 137, 144, 145, 146, 147,
+ 148, 149, 154, 155, 156, 157, 158, 159,
+ 168, 169, 170, 150, 153, 165, 169, 173,
+ 178, 187, 255, 131, 132, 140, 169, 174,
+ 255, 130, 132, 149, 157, 173, 186, 188,
+ 160, 161, 163, 164, 167, 168, 132, 134,
+ 149, 157, 186, 139, 140, 191, 255, 134,
+ 128, 132, 138, 144, 146, 255, 166, 167,
+ 129, 155, 187, 149, 181, 143, 175, 137,
+ 169, 131, 140, 141, 192, 255, 128, 182,
+ 187, 255, 173, 180, 182, 255, 132, 155,
+ 159, 161, 175, 128, 160, 163, 164, 165,
+ 184, 185, 186, 161, 162, 128, 134, 136,
+ 152, 155, 161, 163, 164, 166, 170, 133,
+ 143, 151, 255, 139, 143, 154, 255, 164,
+ 167, 185, 187, 128, 131, 133, 159, 161,
+ 162, 169, 178, 180, 183, 130, 135, 137,
+ 139, 148, 151, 153, 155, 157, 159, 164,
+ 190, 141, 143, 145, 146, 161, 162, 167,
+ 170, 172, 178, 180, 183, 185, 188, 128,
+ 137, 139, 155, 161, 163, 165, 169, 171,
+ 187, 155, 156, 151, 255, 156, 157, 160,
+ 181, 255, 186, 187, 255, 162, 255, 160,
+ 168, 161, 167, 158, 255, 160, 132, 135,
+ 133, 134, 176, 255, 128, 191, 154, 164,
+ 168, 128, 149, 150, 191, 128, 152, 153,
+ 191, 181, 128, 159, 160, 189, 190, 191,
+ 189, 128, 131, 132, 185, 186, 191, 144,
+ 128, 151, 152, 161, 162, 176, 177, 255,
+ 169, 177, 129, 132, 141, 142, 145, 146,
+ 179, 181, 186, 188, 190, 191, 192, 255,
+ 142, 158, 128, 155, 156, 161, 162, 175,
+ 176, 177, 178, 191, 169, 177, 180, 183,
+ 128, 132, 133, 138, 139, 142, 143, 144,
+ 145, 146, 147, 185, 186, 191, 157, 128,
+ 152, 153, 158, 159, 177, 178, 180, 181,
+ 191, 142, 146, 169, 177, 180, 189, 128,
+ 132, 133, 185, 186, 191, 144, 185, 128,
+ 159, 160, 161, 162, 191, 169, 177, 180,
+ 189, 128, 132, 133, 140, 141, 142, 143,
+ 144, 145, 146, 147, 185, 186, 191, 158,
+ 177, 128, 155, 156, 161, 162, 191, 131,
+ 145, 155, 157, 128, 132, 133, 138, 139,
+ 141, 142, 149, 150, 152, 153, 159, 160,
+ 162, 163, 164, 165, 167, 168, 170, 171,
+ 173, 174, 185, 186, 191, 144, 128, 191,
+ 141, 145, 169, 189, 128, 132, 133, 185,
+ 186, 191, 128, 151, 152, 154, 155, 159,
+ 160, 161, 162, 191, 128, 141, 145, 169,
+ 180, 189, 129, 132, 133, 185, 186, 191,
+ 158, 128, 159, 160, 161, 162, 176, 177,
+ 178, 179, 191, 141, 145, 189, 128, 132,
+ 133, 186, 187, 191, 142, 128, 147, 148,
+ 150, 151, 158, 159, 161, 162, 185, 186,
+ 191, 178, 188, 128, 132, 133, 150, 151,
+ 153, 154, 189, 190, 191, 128, 134, 135,
+ 191, 128, 177, 129, 179, 180, 191, 128,
+ 131, 137, 141, 152, 160, 164, 166, 172,
+ 177, 189, 129, 132, 133, 134, 135, 138,
+ 139, 147, 148, 167, 168, 169, 170, 179,
+ 180, 191, 133, 128, 134, 135, 155, 156,
+ 159, 160, 191, 128, 129, 191, 136, 128,
+ 172, 173, 191, 128, 135, 136, 140, 141,
+ 191, 191, 128, 170, 171, 190, 161, 128,
+ 143, 144, 149, 150, 153, 154, 157, 158,
+ 164, 165, 166, 167, 173, 174, 176, 177,
+ 180, 181, 255, 130, 141, 143, 159, 134,
+ 187, 136, 140, 142, 143, 137, 151, 153,
+ 142, 143, 158, 159, 137, 177, 191, 142,
+ 143, 182, 183, 192, 255, 129, 151, 128,
+ 133, 134, 135, 136, 255, 145, 150, 151,
+ 155, 191, 192, 255, 128, 143, 144, 159,
+ 160, 255, 182, 183, 190, 191, 192, 255,
+ 128, 129, 255, 173, 174, 192, 255, 128,
+ 129, 154, 155, 159, 160, 255, 171, 173,
+ 185, 191, 192, 255, 141, 128, 145, 146,
+ 159, 160, 177, 178, 191, 173, 128, 145,
+ 146, 159, 160, 176, 177, 191, 128, 179,
+ 180, 191, 151, 156, 128, 191, 128, 159,
+ 160, 255, 184, 191, 192, 255, 169, 128,
+ 170, 171, 175, 176, 255, 182, 191, 192,
+ 255, 128, 158, 159, 191, 128, 143, 144,
+ 173, 174, 175, 176, 180, 181, 191, 128,
+ 171, 172, 175, 176, 255, 138, 191, 192,
+ 255, 128, 150, 151, 159, 160, 255, 149,
+ 191, 192, 255, 167, 128, 191, 128, 132,
+ 133, 179, 180, 191, 128, 132, 133, 139,
+ 140, 191, 128, 130, 131, 160, 161, 173,
+ 174, 175, 176, 185, 186, 255, 166, 191,
+ 192, 255, 128, 163, 164, 191, 128, 140,
+ 141, 143, 144, 153, 154, 189, 190, 191,
+ 128, 136, 137, 191, 173, 128, 168, 169,
+ 177, 178, 180, 181, 182, 183, 191, 0,
+ 127, 192, 255, 150, 151, 158, 159, 152,
+ 154, 156, 158, 134, 135, 142, 143, 190,
+ 191, 192, 255, 181, 189, 191, 128, 190,
+ 133, 181, 128, 129, 130, 140, 141, 143,
+ 144, 147, 148, 149, 150, 155, 156, 159,
+ 160, 172, 173, 177, 178, 188, 189, 191,
+ 177, 191, 128, 190, 128, 143, 144, 156,
+ 157, 191, 130, 135, 148, 164, 166, 168,
+ 128, 137, 138, 149, 150, 151, 152, 157,
+ 158, 169, 170, 185, 186, 187, 188, 191,
+ 142, 128, 132, 133, 137, 138, 159, 160,
+ 255, 137, 191, 192, 255, 175, 128, 255,
+ 159, 165, 170, 175, 177, 180, 191, 192,
+ 255, 166, 173, 128, 167, 168, 175, 176,
+ 255, 168, 174, 176, 191, 192, 255, 167,
+ 175, 183, 191, 128, 150, 151, 159, 160,
+ 190, 135, 143, 151, 128, 158, 159, 191,
+ 128, 132, 133, 135, 136, 160, 161, 169,
+ 170, 176, 177, 181, 182, 183, 184, 188,
+ 189, 191, 160, 151, 154, 187, 192, 255,
+ 128, 132, 133, 173, 174, 176, 177, 255,
+ 143, 159, 187, 191, 192, 255, 128, 175,
+ 176, 191, 150, 191, 192, 255, 141, 191,
+ 192, 255, 128, 143, 144, 189, 190, 191,
+ 141, 143, 160, 169, 172, 191, 192, 255,
+ 191, 128, 174, 175, 190, 128, 157, 158,
+ 159, 160, 255, 176, 191, 192, 255, 128,
+ 150, 151, 159, 160, 161, 162, 255, 175,
+ 137, 138, 184, 191, 192, 255, 128, 182,
+ 183, 255, 130, 134, 139, 163, 191, 192,
+ 255, 128, 129, 130, 179, 180, 191, 187,
+ 189, 128, 177, 178, 183, 184, 191, 128,
+ 137, 138, 165, 166, 175, 176, 255, 135,
+ 159, 189, 191, 192, 255, 128, 131, 132,
+ 178, 179, 191, 143, 165, 191, 128, 159,
+ 160, 175, 176, 185, 186, 190, 128, 168,
+ 169, 191, 131, 186, 128, 139, 140, 159,
+ 160, 182, 183, 189, 190, 255, 176, 178,
+ 180, 183, 184, 190, 191, 192, 255, 129,
+ 128, 130, 131, 154, 155, 157, 158, 159,
+ 160, 170, 171, 177, 178, 180, 181, 191,
+ 128, 167, 175, 129, 134, 135, 136, 137,
+ 142, 143, 144, 145, 150, 151, 159, 160,
+ 255, 155, 166, 175, 128, 162, 163, 191,
+ 164, 175, 135, 138, 188, 191, 192, 255,
+ 174, 175, 154, 191, 192, 255, 157, 169,
+ 183, 189, 191, 128, 134, 135, 146, 147,
+ 151, 152, 158, 159, 190, 130, 133, 128,
+ 255, 178, 191, 192, 255, 128, 146, 147,
+ 255, 190, 191, 192, 255, 128, 143, 144,
+ 255, 144, 145, 136, 175, 188, 191, 192,
+ 255, 181, 128, 175, 176, 255, 189, 191,
+ 192, 255, 128, 160, 161, 186, 187, 191,
+ 128, 129, 154, 155, 165, 166, 255, 191,
+ 192, 255, 128, 129, 130, 135, 136, 137,
+ 138, 143, 144, 145, 146, 151, 152, 153,
+ 154, 156, 157, 191, 128, 191, 128, 129,
+ 130, 131, 133, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 152,
+ 156, 157, 160, 161, 162, 163, 164, 166,
+ 168, 169, 170, 171, 172, 173, 174, 176,
+ 177, 132, 151, 153, 155, 158, 175, 178,
+ 179, 180, 191, 140, 167, 187, 190, 128,
+ 255, 142, 143, 158, 191, 192, 255, 187,
+ 191, 192, 255, 128, 180, 181, 191, 128,
+ 156, 157, 159, 160, 255, 145, 191, 192,
+ 255, 128, 159, 160, 175, 176, 255, 139,
+ 143, 182, 191, 192, 255, 144, 132, 135,
+ 150, 191, 192, 255, 158, 175, 148, 151,
+ 188, 191, 192, 255, 128, 167, 168, 175,
+ 176, 255, 164, 191, 192, 255, 183, 191,
+ 192, 255, 128, 149, 150, 159, 160, 167,
+ 168, 191, 136, 182, 188, 128, 133, 134,
+ 137, 138, 184, 185, 190, 191, 255, 150,
+ 159, 183, 191, 192, 255, 179, 128, 159,
+ 160, 181, 182, 191, 128, 149, 150, 159,
+ 160, 185, 186, 191, 128, 183, 184, 189,
+ 190, 191, 128, 148, 152, 129, 143, 144,
+ 179, 180, 191, 128, 159, 160, 188, 189,
+ 191, 128, 156, 157, 191, 136, 128, 164,
+ 165, 191, 128, 181, 182, 191, 128, 149,
+ 150, 159, 160, 178, 179, 191, 128, 145,
+ 146, 191, 128, 178, 179, 191, 128, 130,
+ 131, 132, 133, 134, 135, 136, 138, 139,
+ 140, 141, 144, 145, 146, 147, 150, 151,
+ 152, 153, 154, 156, 162, 163, 171, 176,
+ 177, 178, 129, 191, 128, 130, 131, 183,
+ 184, 191, 128, 130, 131, 175, 176, 191,
+ 128, 143, 144, 168, 169, 191, 128, 130,
+ 131, 166, 167, 191, 182, 128, 143, 144,
+ 178, 179, 191, 128, 130, 131, 178, 179,
+ 191, 128, 154, 156, 129, 132, 133, 191,
+ 146, 128, 171, 172, 191, 135, 137, 142,
+ 158, 128, 168, 169, 175, 176, 255, 159,
+ 191, 192, 255, 144, 128, 156, 157, 161,
+ 162, 191, 128, 134, 135, 138, 139, 191,
+ 128, 175, 176, 191, 134, 128, 131, 132,
+ 135, 136, 191, 128, 174, 175, 191, 128,
+ 151, 152, 155, 156, 191, 132, 128, 191,
+ 128, 170, 171, 191, 128, 153, 154, 191,
+ 160, 190, 192, 255, 128, 184, 185, 191,
+ 137, 128, 174, 175, 191, 128, 129, 177,
+ 178, 255, 144, 191, 192, 255, 128, 142,
+ 143, 144, 145, 146, 149, 129, 148, 150,
+ 191, 175, 191, 192, 255, 132, 191, 192,
+ 255, 128, 144, 129, 143, 145, 191, 144,
+ 153, 128, 143, 145, 152, 154, 191, 135,
+ 191, 192, 255, 160, 168, 169, 171, 172,
+ 173, 174, 188, 189, 190, 191, 128, 159,
+ 161, 167, 170, 187, 185, 191, 192, 255,
+ 128, 143, 144, 173, 174, 191, 128, 131,
+ 132, 162, 163, 183, 184, 188, 189, 255,
+ 133, 143, 145, 191, 192, 255, 128, 146,
+ 147, 159, 160, 191, 160, 128, 191, 128,
+ 129, 191, 192, 255, 159, 160, 171, 128,
+ 170, 172, 191, 192, 255, 173, 191, 192,
+ 255, 179, 191, 192, 255, 128, 176, 177,
+ 178, 129, 191, 128, 129, 130, 191, 171,
+ 175, 189, 191, 192, 255, 128, 136, 137,
+ 143, 144, 153, 154, 191, 144, 145, 146,
+ 147, 148, 149, 154, 155, 156, 157, 158,
+ 159, 128, 143, 150, 153, 160, 191, 149,
+ 157, 173, 186, 188, 160, 161, 163, 164,
+ 167, 168, 132, 134, 149, 157, 186, 191,
+ 139, 140, 192, 255, 133, 145, 128, 134,
+ 135, 137, 138, 255, 166, 167, 129, 155,
+ 187, 149, 181, 143, 175, 137, 169, 131,
+ 140, 191, 192, 255, 160, 163, 164, 165,
+ 184, 185, 186, 128, 159, 161, 162, 166,
+ 191, 133, 191, 192, 255, 132, 160, 163,
+ 167, 179, 184, 186, 128, 164, 165, 168,
+ 169, 187, 188, 191, 130, 135, 137, 139,
+ 144, 147, 151, 153, 155, 157, 159, 163,
+ 171, 179, 184, 189, 191, 128, 140, 141,
+ 148, 149, 160, 161, 164, 165, 166, 167,
+ 190, 138, 164, 170, 128, 155, 156, 160,
+ 161, 187, 188, 191, 128, 191, 155, 156,
+ 128, 191, 151, 191, 192, 255, 156, 157,
+ 160, 128, 191, 181, 191, 192, 255, 158,
+ 159, 186, 128, 185, 187, 191, 192, 255,
+ 162, 191, 192, 255, 160, 168, 128, 159,
+ 161, 167, 169, 191, 158, 191, 192, 255,
+ 10, 13, 128, 191, 192, 223, 224, 239,
+ 240, 247, 248, 255, 128, 191, 128, 191,
+ 128, 191, 128, 191, 128, 191, 10, 128,
+ 191, 128, 191, 128, 191, 36, 123, 37,
+ 123, 10, 128, 191, 128, 191, 128, 191,
+ 36, 123, 37, 123, 170, 181, 183, 186,
+ 128, 150, 152, 182, 184, 255, 192, 255,
+ 128, 255, 173, 130, 133, 146, 159, 165,
+ 171, 175, 255, 181, 190, 184, 185, 192,
+ 255, 140, 134, 138, 142, 161, 163, 255,
+ 182, 130, 136, 137, 176, 151, 152, 154,
+ 160, 190, 136, 144, 192, 255, 135, 129,
+ 130, 132, 133, 144, 170, 176, 178, 144,
+ 154, 160, 191, 128, 169, 174, 255, 148,
+ 169, 157, 158, 189, 190, 192, 255, 144,
+ 255, 139, 140, 178, 255, 186, 128, 181,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 128, 173, 128, 155, 160, 180, 182, 189,
+ 148, 161, 163, 255, 176, 164, 165, 132,
+ 169, 177, 141, 142, 145, 146, 179, 181,
+ 186, 187, 158, 133, 134, 137, 138, 143,
+ 150, 152, 155, 164, 165, 178, 255, 188,
+ 129, 131, 133, 138, 143, 144, 147, 168,
+ 170, 176, 178, 179, 181, 182, 184, 185,
+ 190, 255, 157, 131, 134, 137, 138, 142,
+ 144, 146, 152, 159, 165, 182, 255, 129,
+ 131, 133, 141, 143, 145, 147, 168, 170,
+ 176, 178, 179, 181, 185, 188, 255, 134,
+ 138, 142, 143, 145, 159, 164, 165, 176,
+ 184, 186, 255, 129, 131, 133, 140, 143,
+ 144, 147, 168, 170, 176, 178, 179, 181,
+ 185, 188, 191, 177, 128, 132, 135, 136,
+ 139, 141, 150, 151, 156, 157, 159, 163,
+ 166, 175, 156, 130, 131, 133, 138, 142,
+ 144, 146, 149, 153, 154, 158, 159, 163,
+ 164, 168, 170, 174, 185, 190, 191, 144,
+ 151, 128, 130, 134, 136, 138, 141, 166,
+ 175, 128, 131, 133, 140, 142, 144, 146,
+ 168, 170, 185, 189, 255, 133, 137, 151,
+ 142, 148, 155, 159, 164, 165, 176, 255,
+ 128, 131, 133, 140, 142, 144, 146, 168,
+ 170, 179, 181, 185, 188, 191, 158, 128,
+ 132, 134, 136, 138, 141, 149, 150, 160,
+ 163, 166, 175, 177, 178, 129, 131, 133,
+ 140, 142, 144, 146, 186, 189, 255, 133,
+ 137, 143, 147, 152, 158, 164, 165, 176,
+ 185, 192, 255, 189, 130, 131, 133, 150,
+ 154, 177, 179, 187, 138, 150, 128, 134,
+ 143, 148, 152, 159, 166, 175, 178, 179,
+ 129, 186, 128, 142, 144, 153, 132, 138,
+ 141, 165, 167, 129, 130, 135, 136, 148,
+ 151, 153, 159, 161, 163, 170, 171, 173,
+ 185, 187, 189, 134, 128, 132, 136, 141,
+ 144, 153, 156, 159, 128, 181, 183, 185,
+ 152, 153, 160, 169, 190, 191, 128, 135,
+ 137, 172, 177, 191, 128, 132, 134, 151,
+ 153, 188, 134, 128, 129, 130, 131, 137,
+ 138, 139, 140, 141, 142, 143, 144, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 173, 175, 176, 177, 178, 179, 181,
+ 182, 183, 188, 189, 190, 191, 132, 152,
+ 172, 184, 185, 187, 128, 191, 128, 137,
+ 144, 255, 158, 159, 134, 187, 136, 140,
+ 142, 143, 137, 151, 153, 142, 143, 158,
+ 159, 137, 177, 142, 143, 182, 183, 191,
+ 255, 128, 130, 133, 136, 150, 152, 255,
+ 145, 150, 151, 155, 156, 160, 168, 178,
+ 255, 128, 143, 160, 255, 182, 183, 190,
+ 255, 129, 255, 173, 174, 192, 255, 129,
+ 154, 160, 255, 171, 173, 185, 255, 128,
+ 140, 142, 148, 160, 180, 128, 147, 160,
+ 172, 174, 176, 178, 179, 148, 150, 152,
+ 155, 158, 159, 170, 255, 139, 141, 144,
+ 153, 160, 255, 184, 255, 128, 170, 176,
+ 255, 182, 255, 128, 158, 160, 171, 176,
+ 187, 134, 173, 176, 180, 128, 171, 176,
+ 255, 138, 143, 155, 255, 128, 155, 160,
+ 255, 159, 189, 190, 192, 255, 167, 128,
+ 137, 144, 153, 176, 189, 140, 143, 154,
+ 170, 180, 255, 180, 255, 128, 183, 128,
+ 137, 141, 189, 128, 136, 144, 146, 148,
+ 182, 184, 185, 128, 181, 187, 191, 150,
+ 151, 158, 159, 152, 154, 156, 158, 134,
+ 135, 142, 143, 190, 255, 190, 128, 180,
+ 182, 188, 130, 132, 134, 140, 144, 147,
+ 150, 155, 160, 172, 178, 180, 182, 188,
+ 128, 129, 130, 131, 132, 133, 134, 176,
+ 177, 178, 179, 180, 181, 182, 183, 191,
+ 255, 129, 147, 149, 176, 178, 190, 192,
+ 255, 144, 156, 161, 144, 156, 165, 176,
+ 130, 135, 149, 164, 166, 168, 138, 147,
+ 152, 157, 170, 185, 188, 191, 142, 133,
+ 137, 160, 255, 137, 255, 128, 174, 176,
+ 255, 159, 165, 170, 180, 255, 167, 173,
+ 128, 165, 176, 255, 168, 174, 176, 190,
+ 192, 255, 128, 150, 160, 166, 168, 174,
+ 176, 182, 184, 190, 128, 134, 136, 142,
+ 144, 150, 152, 158, 160, 191, 128, 129,
+ 130, 131, 132, 133, 134, 135, 144, 145,
+ 255, 133, 135, 161, 175, 177, 181, 184,
+ 188, 160, 151, 152, 187, 192, 255, 133,
+ 173, 177, 255, 143, 159, 187, 255, 176,
+ 191, 182, 183, 184, 191, 192, 255, 150,
+ 255, 128, 146, 147, 148, 152, 153, 154,
+ 155, 156, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 129, 255, 141,
+ 255, 144, 189, 141, 143, 172, 255, 191,
+ 128, 175, 180, 189, 151, 159, 162, 255,
+ 175, 137, 138, 184, 255, 183, 255, 168,
+ 255, 128, 179, 188, 134, 143, 154, 159,
+ 184, 186, 190, 255, 128, 173, 176, 255,
+ 148, 159, 189, 255, 129, 142, 154, 159,
+ 191, 255, 128, 182, 128, 141, 144, 153,
+ 160, 182, 186, 255, 128, 130, 155, 157,
+ 160, 175, 178, 182, 129, 134, 137, 142,
+ 145, 150, 160, 166, 168, 174, 176, 255,
+ 155, 166, 175, 128, 170, 172, 173, 176,
+ 185, 158, 159, 160, 255, 164, 175, 135,
+ 138, 188, 255, 164, 169, 171, 172, 173,
+ 174, 175, 180, 181, 182, 183, 184, 185,
+ 187, 188, 189, 190, 191, 165, 186, 174,
+ 175, 154, 255, 190, 128, 134, 147, 151,
+ 157, 168, 170, 182, 184, 188, 128, 129,
+ 131, 132, 134, 255, 147, 255, 190, 255,
+ 144, 145, 136, 175, 188, 255, 128, 143,
+ 160, 175, 179, 180, 141, 143, 176, 180,
+ 182, 255, 189, 255, 191, 144, 153, 161,
+ 186, 129, 154, 166, 255, 191, 255, 130,
+ 135, 138, 143, 146, 151, 154, 156, 144,
+ 145, 146, 147, 148, 150, 151, 152, 155,
+ 157, 158, 160, 170, 171, 172, 175, 161,
+ 169, 128, 129, 130, 131, 133, 135, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 152, 156, 157, 160, 161,
+ 162, 163, 164, 166, 168, 169, 170, 171,
+ 172, 173, 174, 176, 177, 153, 155, 178,
+ 179, 128, 139, 141, 166, 168, 186, 188,
+ 189, 191, 255, 142, 143, 158, 255, 187,
+ 255, 128, 180, 189, 128, 156, 160, 255,
+ 145, 159, 161, 255, 128, 159, 176, 255,
+ 139, 143, 187, 255, 128, 157, 160, 255,
+ 144, 132, 135, 150, 255, 158, 159, 170,
+ 175, 148, 151, 188, 255, 128, 167, 176,
+ 255, 164, 255, 183, 255, 128, 149, 160,
+ 167, 136, 188, 128, 133, 138, 181, 183,
+ 184, 191, 255, 150, 159, 183, 255, 128,
+ 158, 160, 178, 180, 181, 128, 149, 160,
+ 185, 128, 183, 190, 191, 191, 128, 131,
+ 133, 134, 140, 147, 149, 151, 153, 179,
+ 184, 186, 160, 188, 128, 156, 128, 135,
+ 137, 166, 128, 181, 128, 149, 160, 178,
+ 128, 145, 128, 178, 129, 130, 131, 132,
+ 133, 135, 136, 138, 139, 140, 141, 144,
+ 145, 146, 147, 150, 151, 152, 153, 154,
+ 155, 156, 162, 163, 171, 176, 177, 178,
+ 128, 134, 135, 165, 176, 190, 144, 168,
+ 176, 185, 128, 180, 182, 191, 182, 144,
+ 179, 155, 133, 137, 141, 143, 157, 255,
+ 190, 128, 145, 147, 183, 136, 128, 134,
+ 138, 141, 143, 157, 159, 168, 176, 255,
+ 171, 175, 186, 255, 128, 131, 133, 140,
+ 143, 144, 147, 168, 170, 176, 178, 179,
+ 181, 185, 188, 191, 144, 151, 128, 132,
+ 135, 136, 139, 141, 157, 163, 166, 172,
+ 176, 180, 128, 138, 144, 153, 134, 136,
+ 143, 154, 255, 128, 181, 184, 255, 129,
+ 151, 158, 255, 129, 131, 133, 143, 154,
+ 255, 128, 137, 128, 153, 157, 171, 176,
+ 185, 160, 255, 170, 190, 192, 255, 128,
+ 184, 128, 136, 138, 182, 184, 191, 128,
+ 144, 153, 178, 255, 168, 144, 145, 183,
+ 255, 128, 142, 145, 149, 129, 141, 144,
+ 146, 147, 148, 175, 255, 132, 255, 128,
+ 144, 129, 143, 144, 153, 145, 152, 135,
+ 255, 160, 168, 169, 171, 172, 173, 174,
+ 188, 189, 190, 191, 161, 167, 185, 255,
+ 128, 158, 160, 169, 144, 173, 176, 180,
+ 128, 131, 144, 153, 163, 183, 189, 255,
+ 144, 255, 133, 143, 191, 255, 143, 159,
+ 160, 128, 129, 255, 159, 160, 171, 172,
+ 255, 173, 255, 179, 255, 128, 176, 177,
+ 178, 128, 129, 171, 175, 189, 255, 128,
+ 136, 144, 153, 157, 158, 133, 134, 137,
+ 144, 145, 146, 147, 148, 149, 154, 155,
+ 156, 157, 158, 159, 168, 169, 170, 150,
+ 153, 165, 169, 173, 178, 187, 255, 131,
+ 132, 140, 169, 174, 255, 130, 132, 149,
+ 157, 173, 186, 188, 160, 161, 163, 164,
+ 167, 168, 132, 134, 149, 157, 186, 139,
+ 140, 191, 255, 134, 128, 132, 138, 144,
+ 146, 255, 166, 167, 129, 155, 187, 149,
+ 181, 143, 175, 137, 169, 131, 140, 141,
+ 192, 255, 128, 182, 187, 255, 173, 180,
+ 182, 255, 132, 155, 159, 161, 175, 128,
+ 160, 163, 164, 165, 184, 185, 186, 161,
+ 162, 128, 134, 136, 152, 155, 161, 163,
+ 164, 166, 170, 133, 143, 151, 255, 139,
+ 143, 154, 255, 164, 167, 185, 187, 128,
+ 131, 133, 159, 161, 162, 169, 178, 180,
+ 183, 130, 135, 137, 139, 148, 151, 153,
+ 155, 157, 159, 164, 190, 141, 143, 145,
+ 146, 161, 162, 167, 170, 172, 178, 180,
+ 183, 185, 188, 128, 137, 139, 155, 161,
+ 163, 165, 169, 171, 187, 155, 156, 151,
+ 255, 156, 157, 160, 181, 255, 186, 187,
+ 255, 162, 255, 160, 168, 161, 167, 158,
+ 255, 160, 132, 135, 133, 134, 176, 255,
+ 128, 191, 154, 164, 168, 128, 149, 150,
+ 191, 128, 152, 153, 191, 181, 128, 159,
+ 160, 189, 190, 191, 189, 128, 131, 132,
+ 185, 186, 191, 144, 128, 151, 152, 161,
+ 162, 176, 177, 255, 169, 177, 129, 132,
+ 141, 142, 145, 146, 179, 181, 186, 188,
+ 190, 191, 192, 255, 142, 158, 128, 155,
+ 156, 161, 162, 175, 176, 177, 178, 191,
+ 169, 177, 180, 183, 128, 132, 133, 138,
+ 139, 142, 143, 144, 145, 146, 147, 185,
+ 186, 191, 157, 128, 152, 153, 158, 159,
+ 177, 178, 180, 181, 191, 142, 146, 169,
+ 177, 180, 189, 128, 132, 133, 185, 186,
+ 191, 144, 185, 128, 159, 160, 161, 162,
+ 191, 169, 177, 180, 189, 128, 132, 133,
+ 140, 141, 142, 143, 144, 145, 146, 147,
+ 185, 186, 191, 158, 177, 128, 155, 156,
+ 161, 162, 191, 131, 145, 155, 157, 128,
+ 132, 133, 138, 139, 141, 142, 149, 150,
+ 152, 153, 159, 160, 162, 163, 164, 165,
+ 167, 168, 170, 171, 173, 174, 185, 186,
+ 191, 144, 128, 191, 141, 145, 169, 189,
+ 128, 132, 133, 185, 186, 191, 128, 151,
+ 152, 154, 155, 159, 160, 161, 162, 191,
+ 128, 141, 145, 169, 180, 189, 129, 132,
+ 133, 185, 186, 191, 158, 128, 159, 160,
+ 161, 162, 176, 177, 178, 179, 191, 141,
+ 145, 189, 128, 132, 133, 186, 187, 191,
+ 142, 128, 147, 148, 150, 151, 158, 159,
+ 161, 162, 185, 186, 191, 178, 188, 128,
+ 132, 133, 150, 151, 153, 154, 189, 190,
+ 191, 128, 134, 135, 191, 128, 177, 129,
+ 179, 180, 191, 128, 131, 137, 141, 152,
+ 160, 164, 166, 172, 177, 189, 129, 132,
+ 133, 134, 135, 138, 139, 147, 148, 167,
+ 168, 169, 170, 179, 180, 191, 133, 128,
+ 134, 135, 155, 156, 159, 160, 191, 128,
+ 129, 191, 136, 128, 172, 173, 191, 128,
+ 135, 136, 140, 141, 191, 191, 128, 170,
+ 171, 190, 161, 128, 143, 144, 149, 150,
+ 153, 154, 157, 158, 164, 165, 166, 167,
+ 173, 174, 176, 177, 180, 181, 255, 130,
+ 141, 143, 159, 134, 187, 136, 140, 142,
+ 143, 137, 151, 153, 142, 143, 158, 159,
+ 137, 177, 191, 142, 143, 182, 183, 192,
+ 255, 129, 151, 128, 133, 134, 135, 136,
+ 255, 145, 150, 151, 155, 191, 192, 255,
+ 128, 143, 144, 159, 160, 255, 182, 183,
+ 190, 191, 192, 255, 128, 129, 255, 173,
+ 174, 192, 255, 128, 129, 154, 155, 159,
+ 160, 255, 171, 173, 185, 191, 192, 255,
+ 141, 128, 145, 146, 159, 160, 177, 178,
+ 191, 173, 128, 145, 146, 159, 160, 176,
+ 177, 191, 128, 179, 180, 191, 151, 156,
+ 128, 191, 128, 159, 160, 255, 184, 191,
+ 192, 255, 169, 128, 170, 171, 175, 176,
+ 255, 182, 191, 192, 255, 128, 158, 159,
+ 191, 128, 143, 144, 173, 174, 175, 176,
+ 180, 181, 191, 128, 171, 172, 175, 176,
+ 255, 138, 191, 192, 255, 128, 150, 151,
+ 159, 160, 255, 149, 191, 192, 255, 167,
+ 128, 191, 128, 132, 133, 179, 180, 191,
+ 128, 132, 133, 139, 140, 191, 128, 130,
+ 131, 160, 161, 173, 174, 175, 176, 185,
+ 186, 255, 166, 191, 192, 255, 128, 163,
+ 164, 191, 128, 140, 141, 143, 144, 153,
+ 154, 189, 190, 191, 128, 136, 137, 191,
+ 173, 128, 168, 169, 177, 178, 180, 181,
+ 182, 183, 191, 0, 127, 192, 255, 150,
+ 151, 158, 159, 152, 154, 156, 158, 134,
+ 135, 142, 143, 190, 191, 192, 255, 181,
+ 189, 191, 128, 190, 133, 181, 128, 129,
+ 130, 140, 141, 143, 144, 147, 148, 149,
+ 150, 155, 156, 159, 160, 172, 173, 177,
+ 178, 188, 189, 191, 177, 191, 128, 190,
+ 128, 143, 144, 156, 157, 191, 130, 135,
+ 148, 164, 166, 168, 128, 137, 138, 149,
+ 150, 151, 152, 157, 158, 169, 170, 185,
+ 186, 187, 188, 191, 142, 128, 132, 133,
+ 137, 138, 159, 160, 255, 137, 191, 192,
+ 255, 175, 128, 255, 159, 165, 170, 175,
+ 177, 180, 191, 192, 255, 166, 173, 128,
+ 167, 168, 175, 176, 255, 168, 174, 176,
+ 191, 192, 255, 167, 175, 183, 191, 128,
+ 150, 151, 159, 160, 190, 135, 143, 151,
+ 128, 158, 159, 191, 128, 132, 133, 135,
+ 136, 160, 161, 169, 170, 176, 177, 181,
+ 182, 183, 184, 188, 189, 191, 160, 151,
+ 154, 187, 192, 255, 128, 132, 133, 173,
+ 174, 176, 177, 255, 143, 159, 187, 191,
+ 192, 255, 128, 175, 176, 191, 150, 191,
+ 192, 255, 141, 191, 192, 255, 128, 143,
+ 144, 189, 190, 191, 141, 143, 160, 169,
+ 172, 191, 192, 255, 191, 128, 174, 175,
+ 190, 128, 157, 158, 159, 160, 255, 176,
+ 191, 192, 255, 128, 150, 151, 159, 160,
+ 161, 162, 255, 175, 137, 138, 184, 191,
+ 192, 255, 128, 182, 183, 255, 130, 134,
+ 139, 163, 191, 192, 255, 128, 129, 130,
+ 179, 180, 191, 187, 189, 128, 177, 178,
+ 183, 184, 191, 128, 137, 138, 165, 166,
+ 175, 176, 255, 135, 159, 189, 191, 192,
+ 255, 128, 131, 132, 178, 179, 191, 143,
+ 165, 191, 128, 159, 160, 175, 176, 185,
+ 186, 190, 128, 168, 169, 191, 131, 186,
+ 128, 139, 140, 159, 160, 182, 183, 189,
+ 190, 255, 176, 178, 180, 183, 184, 190,
+ 191, 192, 255, 129, 128, 130, 131, 154,
+ 155, 157, 158, 159, 160, 170, 171, 177,
+ 178, 180, 181, 191, 128, 167, 175, 129,
+ 134, 135, 136, 137, 142, 143, 144, 145,
+ 150, 151, 159, 160, 255, 155, 166, 175,
+ 128, 162, 163, 191, 164, 175, 135, 138,
+ 188, 191, 192, 255, 174, 175, 154, 191,
+ 192, 255, 157, 169, 183, 189, 191, 128,
+ 134, 135, 146, 147, 151, 152, 158, 159,
+ 190, 130, 133, 128, 255, 178, 191, 192,
+ 255, 128, 146, 147, 255, 190, 191, 192,
+ 255, 128, 143, 144, 255, 144, 145, 136,
+ 175, 188, 191, 192, 255, 181, 128, 175,
+ 176, 255, 189, 191, 192, 255, 128, 160,
+ 161, 186, 187, 191, 128, 129, 154, 155,
+ 165, 166, 255, 191, 192, 255, 128, 129,
+ 130, 135, 136, 137, 138, 143, 144, 145,
+ 146, 151, 152, 153, 154, 156, 157, 191,
+ 128, 191, 128, 129, 130, 131, 133, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 152, 156, 157, 160, 161,
+ 162, 163, 164, 166, 168, 169, 170, 171,
+ 172, 173, 174, 176, 177, 132, 151, 153,
+ 155, 158, 175, 178, 179, 180, 191, 140,
+ 167, 187, 190, 128, 255, 142, 143, 158,
+ 191, 192, 255, 187, 191, 192, 255, 128,
+ 180, 181, 191, 128, 156, 157, 159, 160,
+ 255, 145, 191, 192, 255, 128, 159, 160,
+ 175, 176, 255, 139, 143, 182, 191, 192,
+ 255, 144, 132, 135, 150, 191, 192, 255,
+ 158, 175, 148, 151, 188, 191, 192, 255,
+ 128, 167, 168, 175, 176, 255, 164, 191,
+ 192, 255, 183, 191, 192, 255, 128, 149,
+ 150, 159, 160, 167, 168, 191, 136, 182,
+ 188, 128, 133, 134, 137, 138, 184, 185,
+ 190, 191, 255, 150, 159, 183, 191, 192,
+ 255, 179, 128, 159, 160, 181, 182, 191,
+ 128, 149, 150, 159, 160, 185, 186, 191,
+ 128, 183, 184, 189, 190, 191, 128, 148,
+ 152, 129, 143, 144, 179, 180, 191, 128,
+ 159, 160, 188, 189, 191, 128, 156, 157,
+ 191, 136, 128, 164, 165, 191, 128, 181,
+ 182, 191, 128, 149, 150, 159, 160, 178,
+ 179, 191, 128, 145, 146, 191, 128, 178,
+ 179, 191, 128, 130, 131, 132, 133, 134,
+ 135, 136, 138, 139, 140, 141, 144, 145,
+ 146, 147, 150, 151, 152, 153, 154, 156,
+ 162, 163, 171, 176, 177, 178, 129, 191,
+ 128, 130, 131, 183, 184, 191, 128, 130,
+ 131, 175, 176, 191, 128, 143, 144, 168,
+ 169, 191, 128, 130, 131, 166, 167, 191,
+ 182, 128, 143, 144, 178, 179, 191, 128,
+ 130, 131, 178, 179, 191, 128, 154, 156,
+ 129, 132, 133, 191, 146, 128, 171, 172,
+ 191, 135, 137, 142, 158, 128, 168, 169,
+ 175, 176, 255, 159, 191, 192, 255, 144,
+ 128, 156, 157, 161, 162, 191, 128, 134,
+ 135, 138, 139, 191, 128, 175, 176, 191,
+ 134, 128, 131, 132, 135, 136, 191, 128,
+ 174, 175, 191, 128, 151, 152, 155, 156,
+ 191, 132, 128, 191, 128, 170, 171, 191,
+ 128, 153, 154, 191, 160, 190, 192, 255,
+ 128, 184, 185, 191, 137, 128, 174, 175,
+ 191, 128, 129, 177, 178, 255, 144, 191,
+ 192, 255, 128, 142, 143, 144, 145, 146,
+ 149, 129, 148, 150, 191, 175, 191, 192,
+ 255, 132, 191, 192, 255, 128, 144, 129,
+ 143, 145, 191, 144, 153, 128, 143, 145,
+ 152, 154, 191, 135, 191, 192, 255, 160,
+ 168, 169, 171, 172, 173, 174, 188, 189,
+ 190, 191, 128, 159, 161, 167, 170, 187,
+ 185, 191, 192, 255, 128, 143, 144, 173,
+ 174, 191, 128, 131, 132, 162, 163, 183,
+ 184, 188, 189, 255, 133, 143, 145, 191,
+ 192, 255, 128, 146, 147, 159, 160, 191,
+ 160, 128, 191, 128, 129, 191, 192, 255,
+ 159, 160, 171, 128, 170, 172, 191, 192,
+ 255, 173, 191, 192, 255, 179, 191, 192,
+ 255, 128, 176, 177, 178, 129, 191, 128,
+ 129, 130, 191, 171, 175, 189, 191, 192,
+ 255, 128, 136, 137, 143, 144, 153, 154,
+ 191, 144, 145, 146, 147, 148, 149, 154,
+ 155, 156, 157, 158, 159, 128, 143, 150,
+ 153, 160, 191, 149, 157, 173, 186, 188,
+ 160, 161, 163, 164, 167, 168, 132, 134,
+ 149, 157, 186, 191, 139, 140, 192, 255,
+ 133, 145, 128, 134, 135, 137, 138, 255,
+ 166, 167, 129, 155, 187, 149, 181, 143,
+ 175, 137, 169, 131, 140, 191, 192, 255,
+ 160, 163, 164, 165, 184, 185, 186, 128,
+ 159, 161, 162, 166, 191, 133, 191, 192,
+ 255, 132, 160, 163, 167, 179, 184, 186,
+ 128, 164, 165, 168, 169, 187, 188, 191,
+ 130, 135, 137, 139, 144, 147, 151, 153,
+ 155, 157, 159, 163, 171, 179, 184, 189,
+ 191, 128, 140, 141, 148, 149, 160, 161,
+ 164, 165, 166, 167, 190, 138, 164, 170,
+ 128, 155, 156, 160, 161, 187, 188, 191,
+ 128, 191, 155, 156, 128, 191, 151, 191,
+ 192, 255, 156, 157, 160, 128, 191, 181,
+ 191, 192, 255, 158, 159, 186, 128, 185,
+ 187, 191, 192, 255, 162, 191, 192, 255,
+ 160, 168, 128, 159, 161, 167, 169, 191,
+ 158, 191, 192, 255, 9, 10, 13, 32,
+ 33, 34, 35, 38, 46, 47, 58, 60,
+ 61, 62, 64, 92, 95, 123, 124, 125,
+ 126, 127, 194, 195, 198, 199, 203, 204,
+ 205, 206, 207, 210, 212, 213, 214, 215,
+ 216, 217, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 233, 234, 237, 238,
+ 239, 240, 0, 36, 37, 45, 48, 57,
+ 59, 63, 65, 90, 91, 96, 97, 122,
+ 192, 193, 196, 218, 229, 236, 241, 247,
+ 9, 32, 10, 61, 10, 38, 46, 42,
+ 47, 46, 69, 101, 48, 57, 58, 60,
+ 61, 61, 62, 61, 45, 95, 194, 195,
+ 198, 199, 203, 204, 205, 206, 207, 210,
+ 212, 213, 214, 215, 216, 217, 219, 220,
+ 221, 222, 223, 224, 225, 226, 227, 228,
+ 233, 234, 237, 239, 240, 243, 48, 57,
+ 65, 90, 97, 122, 196, 218, 229, 236,
+ 124, 125, 128, 191, 170, 181, 186, 128,
+ 191, 151, 183, 128, 255, 192, 255, 0,
+ 127, 173, 130, 133, 146, 159, 165, 171,
+ 175, 191, 192, 255, 181, 190, 128, 175,
+ 176, 183, 184, 185, 186, 191, 134, 139,
+ 141, 162, 128, 135, 136, 255, 182, 130,
+ 137, 176, 151, 152, 154, 160, 136, 191,
+ 192, 255, 128, 143, 144, 170, 171, 175,
+ 176, 178, 179, 191, 128, 159, 160, 191,
+ 176, 128, 138, 139, 173, 174, 255, 148,
+ 150, 164, 167, 173, 176, 185, 189, 190,
+ 192, 255, 144, 128, 145, 146, 175, 176,
+ 191, 128, 140, 141, 255, 166, 176, 178,
+ 191, 192, 255, 186, 128, 137, 138, 170,
+ 171, 179, 180, 181, 182, 191, 160, 161,
+ 162, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 128, 191, 128, 129,
+ 130, 131, 137, 138, 139, 140, 141, 142,
+ 143, 144, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 182, 183,
+ 184, 188, 189, 190, 191, 132, 187, 129,
+ 130, 132, 133, 134, 176, 177, 178, 179,
+ 180, 181, 182, 183, 128, 191, 128, 129,
+ 130, 131, 132, 133, 134, 135, 144, 136,
+ 143, 145, 191, 192, 255, 182, 183, 184,
+ 128, 191, 128, 191, 191, 128, 190, 192,
+ 255, 128, 146, 147, 148, 152, 153, 154,
+ 155, 156, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 129, 191, 192,
+ 255, 158, 159, 128, 157, 160, 191, 192,
+ 255, 128, 191, 164, 169, 171, 172, 173,
+ 174, 175, 180, 181, 182, 183, 184, 185,
+ 187, 188, 189, 190, 191, 128, 163, 165,
+ 186, 144, 145, 146, 147, 148, 150, 151,
+ 152, 155, 157, 158, 160, 170, 171, 172,
+ 175, 128, 159, 161, 169, 173, 191, 128,
+ 191, 10, 13, 34, 36, 37, 92, 128,
+ 191, 192, 223, 224, 239, 240, 247, 248,
+ 255, 10, 13, 34, 92, 36, 37, 128,
+ 191, 192, 223, 224, 239, 240, 247, 248,
+ 255, 10, 13, 36, 123, 123, 126, 126,
+ 37, 123, 126, 10, 13, 128, 191, 192,
+ 223, 224, 239, 240, 247, 248, 255, 128,
+ 191, 128, 191, 128, 191, 10, 13, 36,
+ 37, 128, 191, 192, 223, 224, 239, 240,
+ 247, 248, 255, 10, 13, 36, 37, 128,
+ 191, 192, 223, 224, 239, 240, 247, 248,
+ 255, 10, 13, 10, 13, 123, 10, 13,
+ 126, 10, 13, 126, 126, 128, 191, 128,
+ 191, 128, 191, 10, 13, 36, 37, 128,
+ 191, 192, 223, 224, 239, 240, 247, 248,
+ 255, 10, 13, 36, 37, 128, 191, 192,
+ 223, 224, 239, 240, 247, 248, 255, 10,
+ 13, 10, 13, 123, 10, 13, 126, 10,
+ 13, 126, 126, 128, 191, 128, 191, 128,
+ 191, 95, 194, 195, 198, 199, 203, 204,
+ 205, 206, 207, 210, 212, 213, 214, 215,
+ 216, 217, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 233, 234, 237, 238,
+ 239, 240, 65, 90, 97, 122, 128, 191,
+ 192, 193, 196, 218, 229, 236, 241, 247,
+ 248, 255, 45, 95, 194, 195, 198, 199,
+ 203, 204, 205, 206, 207, 210, 212, 213,
+ 214, 215, 216, 217, 219, 220, 221, 222,
+ 223, 224, 225, 226, 227, 228, 233, 234,
+ 237, 239, 240, 243, 48, 57, 65, 90,
+ 97, 122, 196, 218, 229, 236, 128, 191,
+ 170, 181, 186, 128, 191, 151, 183, 128,
+ 255, 192, 255, 0, 127, 173, 130, 133,
+ 146, 159, 165, 171, 175, 191, 192, 255,
+ 181, 190, 128, 175, 176, 183, 184, 185,
+ 186, 191, 134, 139, 141, 162, 128, 135,
+ 136, 255, 182, 130, 137, 176, 151, 152,
+ 154, 160, 136, 191, 192, 255, 128, 143,
+ 144, 170, 171, 175, 176, 178, 179, 191,
+ 128, 159, 160, 191, 176, 128, 138, 139,
+ 173, 174, 255, 148, 150, 164, 167, 173,
+ 176, 185, 189, 190, 192, 255, 144, 128,
+ 145, 146, 175, 176, 191, 128, 140, 141,
+ 255, 166, 176, 178, 191, 192, 255, 186,
+ 128, 137, 138, 170, 171, 179, 180, 181,
+ 182, 191, 160, 161, 162, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190,
+ 128, 191, 128, 129, 130, 131, 137, 138,
+ 139, 140, 141, 142, 143, 144, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 182, 183, 184, 188, 189, 190,
+ 191, 132, 187, 129, 130, 132, 133, 134,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 128, 191, 128, 129, 130, 131, 132, 133,
+ 134, 135, 144, 136, 143, 145, 191, 192,
+ 255, 182, 183, 184, 128, 191, 128, 191,
+ 191, 128, 190, 192, 255, 128, 146, 147,
+ 148, 152, 153, 154, 155, 156, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 129, 191, 192, 255, 158, 159, 128,
+ 157, 160, 191, 192, 255, 128, 191, 164,
+ 169, 171, 172, 173, 174, 175, 180, 181,
+ 182, 183, 184, 185, 187, 188, 189, 190,
+ 191, 128, 163, 165, 186, 144, 145, 146,
+ 147, 148, 150, 151, 152, 155, 157, 158,
+ 160, 170, 171, 172, 175, 128, 159, 161,
+ 169, 173, 191, 128, 191,
+}
+
+var _hcltok_single_lengths []byte = []byte{
+ 0, 1, 1, 2, 3, 2, 0, 32,
+ 31, 36, 1, 4, 0, 0, 0, 0,
+ 1, 2, 1, 1, 1, 1, 0, 1,
+ 1, 0, 0, 2, 0, 0, 0, 1,
+ 32, 0, 0, 0, 0, 1, 3, 1,
+ 1, 1, 0, 2, 0, 1, 1, 2,
+ 0, 3, 0, 1, 0, 2, 1, 2,
+ 0, 0, 5, 1, 4, 0, 0, 1,
+ 43, 0, 0, 0, 2, 3, 2, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 4, 1,
+ 0, 15, 0, 0, 0, 1, 6, 1,
+ 0, 0, 1, 0, 2, 0, 0, 0,
+ 9, 0, 1, 1, 0, 0, 0, 3,
+ 0, 1, 0, 28, 0, 0, 0, 1,
+ 0, 1, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 2,
+ 0, 0, 18, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 16, 36, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 28, 0, 0, 0, 1,
+ 1, 1, 1, 0, 0, 2, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 4, 0, 0, 2, 2,
+ 0, 11, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 3, 0, 0, 4, 0,
+ 0, 0, 18, 0, 0, 0, 1, 4,
+ 1, 4, 1, 0, 3, 2, 2, 2,
+ 1, 0, 0, 1, 8, 0, 0, 0,
+ 4, 12, 0, 2, 0, 3, 0, 1,
+ 0, 2, 0, 1, 2, 0, 3, 1,
+ 2, 0, 0, 0, 0, 0, 1, 1,
+ 0, 0, 1, 28, 3, 0, 1, 1,
+ 2, 1, 0, 1, 1, 2, 1, 1,
+ 2, 1, 1, 0, 2, 1, 1, 1,
+ 1, 0, 0, 6, 1, 1, 0, 0,
+ 46, 1, 1, 0, 0, 0, 0, 2,
+ 1, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 13, 2, 0, 0,
+ 0, 9, 0, 1, 28, 0, 1, 3,
+ 0, 2, 0, 0, 0, 1, 0, 1,
+ 1, 2, 0, 18, 2, 0, 0, 16,
+ 35, 0, 0, 0, 1, 0, 28, 0,
+ 0, 0, 0, 1, 0, 2, 0, 0,
+ 1, 0, 0, 1, 0, 0, 1, 0,
+ 0, 0, 0, 1, 11, 0, 0, 0,
+ 0, 4, 0, 12, 1, 7, 0, 4,
+ 0, 0, 0, 0, 1, 2, 1, 1,
+ 1, 1, 0, 1, 1, 0, 0, 2,
+ 0, 0, 0, 1, 32, 0, 0, 0,
+ 0, 1, 3, 1, 1, 1, 0, 2,
+ 0, 1, 1, 2, 0, 3, 0, 1,
+ 0, 2, 1, 2, 0, 0, 5, 1,
+ 4, 0, 0, 1, 43, 0, 0, 0,
+ 2, 3, 2, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 4, 1, 0, 15, 0, 0,
+ 0, 1, 6, 1, 0, 0, 1, 0,
+ 2, 0, 0, 0, 9, 0, 1, 1,
+ 0, 0, 0, 3, 0, 1, 0, 28,
+ 0, 0, 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 2, 0, 0, 18, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 16, 36,
+ 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 28,
+ 0, 0, 0, 1, 1, 1, 1, 0,
+ 0, 2, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 4,
+ 0, 0, 2, 2, 0, 11, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 3,
+ 0, 0, 4, 0, 0, 0, 18, 0,
+ 0, 0, 1, 4, 1, 4, 1, 0,
+ 3, 2, 2, 2, 1, 0, 0, 1,
+ 8, 0, 0, 0, 4, 12, 0, 2,
+ 0, 3, 0, 1, 0, 2, 0, 1,
+ 2, 0, 0, 3, 0, 1, 1, 1,
+ 2, 2, 4, 1, 6, 2, 4, 2,
+ 4, 1, 4, 0, 6, 1, 3, 1,
+ 2, 0, 2, 11, 1, 1, 1, 0,
+ 1, 1, 0, 2, 0, 3, 3, 2,
+ 1, 0, 0, 0, 1, 0, 1, 0,
+ 1, 1, 0, 2, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 4, 3, 2, 2, 0, 6,
+ 1, 0, 1, 1, 0, 2, 0, 4,
+ 3, 0, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 1,
+ 0, 3, 0, 2, 0, 0, 0, 3,
+ 0, 2, 1, 1, 3, 1, 0, 0,
+ 0, 0, 0, 5, 2, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 1, 1,
+ 0, 0, 35, 4, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 3, 0, 1, 0, 0, 3,
+ 0, 0, 1, 0, 0, 0, 0, 28,
+ 0, 0, 0, 0, 1, 0, 3, 1,
+ 4, 0, 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 0, 1, 1, 0,
+ 7, 0, 0, 2, 2, 0, 11, 0,
+ 0, 0, 0, 0, 1, 1, 3, 0,
+ 0, 4, 0, 0, 0, 12, 1, 4,
+ 1, 5, 2, 0, 3, 2, 2, 2,
+ 1, 7, 0, 7, 17, 3, 0, 2,
+ 0, 3, 0, 0, 1, 0, 2, 0,
+ 2, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 2, 2, 1, 0, 0, 0,
+ 2, 2, 4, 0, 0, 0, 0, 1,
+ 2, 1, 1, 1, 1, 0, 1, 1,
+ 0, 0, 2, 0, 0, 0, 1, 32,
+ 0, 0, 0, 0, 1, 3, 1, 1,
+ 1, 0, 2, 0, 1, 1, 2, 0,
+ 3, 0, 1, 0, 2, 1, 2, 0,
+ 0, 5, 1, 4, 0, 0, 1, 43,
+ 0, 0, 0, 2, 3, 2, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 1, 0,
+ 15, 0, 0, 0, 1, 6, 1, 0,
+ 0, 1, 0, 2, 0, 0, 0, 9,
+ 0, 1, 1, 0, 0, 0, 3, 0,
+ 1, 0, 28, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 2, 0,
+ 0, 18, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 16, 36, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 28, 0, 0, 0, 1, 1,
+ 1, 1, 0, 0, 2, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 4, 0, 0, 2, 2, 0,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 3, 0, 0, 4, 0, 0,
+ 0, 18, 0, 0, 0, 1, 4, 1,
+ 4, 1, 0, 3, 2, 2, 2, 1,
+ 0, 0, 1, 8, 0, 0, 0, 4,
+ 12, 0, 2, 0, 3, 0, 1, 0,
+ 2, 0, 1, 2, 0, 0, 3, 0,
+ 1, 1, 1, 2, 2, 4, 1, 6,
+ 2, 4, 2, 4, 1, 4, 0, 6,
+ 1, 3, 1, 2, 0, 2, 11, 1,
+ 1, 1, 0, 1, 1, 0, 2, 0,
+ 3, 3, 2, 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 1, 0, 2, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 4, 3, 2,
+ 2, 0, 6, 1, 0, 1, 1, 0,
+ 2, 0, 4, 3, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 3, 0, 2, 0,
+ 0, 0, 3, 0, 2, 1, 1, 3,
+ 1, 0, 0, 0, 0, 0, 5, 2,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0, 35, 4, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 3, 0, 1,
+ 0, 0, 3, 0, 0, 1, 0, 0,
+ 0, 0, 28, 0, 0, 0, 0, 1,
+ 0, 3, 1, 4, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 0, 7, 0, 0, 2, 2,
+ 0, 11, 0, 0, 0, 0, 0, 1,
+ 1, 3, 0, 0, 4, 0, 0, 0,
+ 12, 1, 4, 1, 5, 2, 0, 3,
+ 2, 2, 2, 1, 7, 0, 7, 17,
+ 3, 0, 2, 0, 3, 0, 0, 1,
+ 0, 2, 0, 54, 2, 1, 1, 1,
+ 1, 1, 2, 3, 1, 2, 2, 1,
+ 34, 1, 1, 0, 3, 2, 0, 0,
+ 0, 1, 2, 4, 1, 0, 1, 0,
+ 0, 0, 0, 1, 1, 1, 0, 0,
+ 1, 30, 47, 13, 9, 3, 0, 1,
+ 28, 2, 0, 18, 16, 0, 6, 4,
+ 2, 2, 0, 1, 1, 1, 2, 1,
+ 2, 0, 0, 0, 4, 2, 2, 3,
+ 3, 2, 1, 1, 0, 0, 0, 4,
+ 2, 2, 3, 3, 2, 1, 1, 0,
+ 0, 0, 33, 34, 0, 3, 2, 0,
+ 0, 0, 1, 2, 4, 1, 0, 1,
+ 0, 0, 0, 0, 1, 1, 1, 0,
+ 0, 1, 30, 47, 13, 9, 3, 0,
+ 1, 28, 2, 0, 18, 16, 0,
+}
+
+var _hcltok_range_lengths []byte = []byte{
+ 0, 0, 0, 0, 1, 1, 1, 5,
+ 5, 5, 0, 0, 3, 0, 1, 1,
+ 4, 2, 3, 0, 1, 0, 2, 2,
+ 4, 2, 2, 3, 1, 1, 1, 1,
+ 0, 1, 1, 2, 2, 1, 4, 6,
+ 9, 6, 8, 5, 8, 7, 10, 4,
+ 6, 4, 7, 7, 5, 5, 4, 5,
+ 1, 2, 8, 4, 3, 3, 3, 0,
+ 3, 1, 2, 1, 2, 2, 3, 3,
+ 1, 3, 2, 2, 1, 2, 2, 2,
+ 3, 4, 4, 3, 1, 2, 1, 3,
+ 2, 2, 2, 2, 2, 3, 3, 1,
+ 1, 2, 1, 3, 2, 2, 3, 2,
+ 7, 0, 1, 4, 1, 2, 4, 2,
+ 1, 2, 0, 2, 2, 3, 5, 5,
+ 1, 4, 1, 1, 2, 2, 1, 0,
+ 0, 1, 1, 1, 1, 1, 2, 2,
+ 2, 2, 1, 1, 1, 4, 2, 2,
+ 3, 1, 4, 4, 6, 1, 3, 1,
+ 1, 2, 1, 1, 1, 5, 3, 1,
+ 1, 1, 2, 3, 3, 1, 2, 2,
+ 1, 4, 1, 2, 5, 2, 1, 1,
+ 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 1, 1, 2, 4, 2, 1,
+ 2, 2, 2, 6, 1, 1, 2, 1,
+ 2, 1, 1, 1, 2, 2, 2, 1,
+ 3, 2, 5, 2, 8, 6, 2, 2,
+ 2, 2, 3, 1, 3, 1, 2, 1,
+ 3, 2, 2, 3, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 4, 1, 2,
+ 1, 0, 1, 1, 1, 1, 0, 1,
+ 2, 3, 1, 3, 3, 1, 0, 3,
+ 0, 2, 3, 1, 0, 0, 0, 0,
+ 2, 2, 2, 2, 1, 5, 2, 2,
+ 5, 7, 5, 0, 1, 0, 1, 1,
+ 1, 1, 1, 0, 1, 1, 0, 3,
+ 3, 1, 1, 2, 1, 3, 5, 1,
+ 1, 2, 2, 1, 1, 1, 1, 2,
+ 6, 3, 7, 2, 6, 1, 6, 2,
+ 8, 0, 4, 2, 5, 2, 3, 3,
+ 3, 1, 2, 8, 2, 0, 2, 1,
+ 2, 1, 5, 2, 1, 3, 3, 0,
+ 2, 1, 2, 1, 0, 1, 1, 3,
+ 1, 1, 2, 3, 0, 0, 3, 2,
+ 4, 1, 4, 1, 1, 3, 1, 1,
+ 1, 1, 2, 2, 1, 3, 1, 4,
+ 3, 3, 1, 1, 5, 2, 1, 1,
+ 2, 1, 2, 1, 3, 2, 0, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1,
+ 1, 2, 2, 1, 1, 1, 3, 2,
+ 1, 0, 2, 1, 1, 1, 1, 0,
+ 3, 0, 1, 1, 4, 2, 3, 0,
+ 1, 0, 2, 2, 4, 2, 2, 3,
+ 1, 1, 1, 1, 0, 1, 1, 2,
+ 2, 1, 4, 6, 9, 6, 8, 5,
+ 8, 7, 10, 4, 6, 4, 7, 7,
+ 5, 5, 4, 5, 1, 2, 8, 4,
+ 3, 3, 3, 0, 3, 1, 2, 1,
+ 2, 2, 3, 3, 1, 3, 2, 2,
+ 1, 2, 2, 2, 3, 4, 4, 3,
+ 1, 2, 1, 3, 2, 2, 2, 2,
+ 2, 3, 3, 1, 1, 2, 1, 3,
+ 2, 2, 3, 2, 7, 0, 1, 4,
+ 1, 2, 4, 2, 1, 2, 0, 2,
+ 2, 3, 5, 5, 1, 4, 1, 1,
+ 2, 2, 1, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 1, 1,
+ 1, 4, 2, 2, 3, 1, 4, 4,
+ 6, 1, 3, 1, 1, 2, 1, 1,
+ 1, 5, 3, 1, 1, 1, 2, 3,
+ 3, 1, 2, 2, 1, 4, 1, 2,
+ 5, 2, 1, 1, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 1,
+ 2, 4, 2, 1, 2, 2, 2, 6,
+ 1, 1, 2, 1, 2, 1, 1, 1,
+ 2, 2, 2, 1, 3, 2, 5, 2,
+ 8, 6, 2, 2, 2, 2, 3, 1,
+ 3, 1, 2, 1, 3, 2, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 4, 1, 2, 1, 0, 1, 1,
+ 1, 1, 0, 1, 2, 3, 1, 3,
+ 3, 1, 0, 3, 0, 2, 3, 1,
+ 0, 0, 0, 0, 2, 2, 2, 2,
+ 1, 5, 2, 2, 5, 7, 5, 0,
+ 1, 0, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 2, 2, 3, 3, 4,
+ 7, 5, 7, 5, 3, 3, 7, 3,
+ 13, 1, 3, 5, 3, 5, 3, 6,
+ 5, 2, 2, 8, 4, 1, 2, 3,
+ 2, 10, 2, 2, 0, 2, 3, 3,
+ 1, 2, 3, 3, 1, 2, 3, 3,
+ 4, 4, 2, 1, 2, 2, 3, 2,
+ 2, 5, 3, 2, 3, 2, 1, 3,
+ 3, 6, 2, 2, 5, 2, 5, 1,
+ 1, 2, 4, 1, 11, 1, 3, 8,
+ 4, 2, 1, 0, 4, 3, 3, 3,
+ 2, 9, 1, 1, 4, 3, 2, 2,
+ 2, 3, 4, 2, 3, 2, 4, 3,
+ 2, 2, 3, 3, 4, 3, 3, 4,
+ 2, 5, 4, 8, 7, 1, 2, 1,
+ 3, 1, 2, 5, 1, 2, 2, 2,
+ 2, 1, 3, 2, 2, 3, 3, 1,
+ 9, 1, 5, 1, 3, 2, 2, 3,
+ 2, 3, 3, 3, 1, 3, 3, 2,
+ 2, 4, 5, 3, 3, 4, 3, 3,
+ 3, 2, 2, 2, 4, 2, 2, 1,
+ 3, 3, 3, 3, 3, 3, 2, 2,
+ 3, 2, 3, 3, 2, 3, 2, 3,
+ 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 3, 2, 3, 2,
+ 3, 5, 3, 3, 1, 2, 3, 2,
+ 2, 1, 2, 3, 4, 3, 0, 3,
+ 0, 2, 3, 1, 0, 0, 0, 0,
+ 2, 3, 2, 4, 6, 4, 1, 1,
+ 2, 1, 2, 1, 3, 2, 3, 2,
+ 5, 1, 1, 1, 1, 1, 0, 1,
+ 1, 1, 0, 0, 0, 1, 1, 1,
+ 0, 0, 0, 3, 0, 1, 1, 4,
+ 2, 3, 0, 1, 0, 2, 2, 4,
+ 2, 2, 3, 1, 1, 1, 1, 0,
+ 1, 1, 2, 2, 1, 4, 6, 9,
+ 6, 8, 5, 8, 7, 10, 4, 6,
+ 4, 7, 7, 5, 5, 4, 5, 1,
+ 2, 8, 4, 3, 3, 3, 0, 3,
+ 1, 2, 1, 2, 2, 3, 3, 1,
+ 3, 2, 2, 1, 2, 2, 2, 3,
+ 4, 4, 3, 1, 2, 1, 3, 2,
+ 2, 2, 2, 2, 3, 3, 1, 1,
+ 2, 1, 3, 2, 2, 3, 2, 7,
+ 0, 1, 4, 1, 2, 4, 2, 1,
+ 2, 0, 2, 2, 3, 5, 5, 1,
+ 4, 1, 1, 2, 2, 1, 0, 0,
+ 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 1, 1, 1, 4, 2, 2, 3,
+ 1, 4, 4, 6, 1, 3, 1, 1,
+ 2, 1, 1, 1, 5, 3, 1, 1,
+ 1, 2, 3, 3, 1, 2, 2, 1,
+ 4, 1, 2, 5, 2, 1, 1, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 1, 2, 4, 2, 1, 2,
+ 2, 2, 6, 1, 1, 2, 1, 2,
+ 1, 1, 1, 2, 2, 2, 1, 3,
+ 2, 5, 2, 8, 6, 2, 2, 2,
+ 2, 3, 1, 3, 1, 2, 1, 3,
+ 2, 2, 3, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 4, 1, 2, 1,
+ 0, 1, 1, 1, 1, 0, 1, 2,
+ 3, 1, 3, 3, 1, 0, 3, 0,
+ 2, 3, 1, 0, 0, 0, 0, 2,
+ 2, 2, 2, 1, 5, 2, 2, 5,
+ 7, 5, 0, 1, 0, 1, 1, 1,
+ 1, 1, 0, 1, 1, 1, 2, 2,
+ 3, 3, 4, 7, 5, 7, 5, 3,
+ 3, 7, 3, 13, 1, 3, 5, 3,
+ 5, 3, 6, 5, 2, 2, 8, 4,
+ 1, 2, 3, 2, 10, 2, 2, 0,
+ 2, 3, 3, 1, 2, 3, 3, 1,
+ 2, 3, 3, 4, 4, 2, 1, 2,
+ 2, 3, 2, 2, 5, 3, 2, 3,
+ 2, 1, 3, 3, 6, 2, 2, 5,
+ 2, 5, 1, 1, 2, 4, 1, 11,
+ 1, 3, 8, 4, 2, 1, 0, 4,
+ 3, 3, 3, 2, 9, 1, 1, 4,
+ 3, 2, 2, 2, 3, 4, 2, 3,
+ 2, 4, 3, 2, 2, 3, 3, 4,
+ 3, 3, 4, 2, 5, 4, 8, 7,
+ 1, 2, 1, 3, 1, 2, 5, 1,
+ 2, 2, 2, 2, 1, 3, 2, 2,
+ 3, 3, 1, 9, 1, 5, 1, 3,
+ 2, 2, 3, 2, 3, 3, 3, 1,
+ 3, 3, 2, 2, 4, 5, 3, 3,
+ 4, 3, 3, 3, 2, 2, 2, 4,
+ 2, 2, 1, 3, 3, 3, 3, 3,
+ 3, 2, 2, 3, 2, 3, 3, 2,
+ 3, 2, 3, 1, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 3,
+ 2, 3, 2, 3, 5, 3, 3, 1,
+ 2, 3, 2, 2, 1, 2, 3, 4,
+ 3, 0, 3, 0, 2, 3, 1, 0,
+ 0, 0, 0, 2, 3, 2, 4, 6,
+ 4, 1, 1, 2, 1, 2, 1, 3,
+ 2, 3, 2, 11, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0,
+ 5, 0, 0, 1, 1, 1, 0, 1,
+ 1, 5, 4, 2, 0, 1, 0, 2,
+ 2, 5, 2, 3, 5, 3, 2, 3,
+ 5, 1, 1, 1, 3, 1, 1, 2,
+ 2, 3, 1, 2, 3, 1, 5, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 1, 1, 1, 5, 6, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 5,
+ 6, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 8, 5, 1, 1, 1, 0,
+ 1, 1, 5, 4, 2, 0, 1, 0,
+ 2, 2, 5, 2, 3, 5, 3, 2,
+ 3, 5, 1, 1, 1, 3, 1, 1,
+ 2, 2, 3, 1, 2, 3, 1,
+}
+
+var _hcltok_index_offsets []int16 = []int16{
+ 0, 0, 2, 4, 7, 12, 16, 18,
+ 56, 93, 135, 137, 142, 146, 147, 149,
+ 151, 157, 162, 167, 169, 172, 174, 177,
+ 181, 187, 190, 193, 199, 201, 203, 205,
+ 208, 241, 243, 245, 248, 251, 254, 262,
+ 270, 281, 289, 298, 306, 315, 324, 336,
+ 343, 350, 358, 366, 375, 381, 389, 395,
+ 403, 405, 408, 422, 428, 436, 440, 444,
+ 446, 493, 495, 498, 500, 505, 511, 517,
+ 522, 525, 529, 532, 535, 537, 540, 543,
+ 546, 550, 555, 560, 564, 566, 569, 571,
+ 575, 578, 581, 584, 587, 591, 596, 600,
+ 602, 604, 607, 609, 613, 616, 619, 627,
+ 631, 639, 655, 657, 662, 664, 668, 679,
+ 683, 685, 688, 690, 693, 698, 702, 708,
+ 714, 725, 730, 733, 736, 739, 742, 744,
+ 748, 749, 752, 754, 784, 786, 788, 791,
+ 795, 798, 802, 804, 806, 808, 814, 817,
+ 820, 824, 826, 831, 836, 843, 846, 850,
+ 854, 856, 859, 879, 881, 883, 890, 894,
+ 896, 898, 900, 903, 907, 911, 913, 917,
+ 920, 922, 927, 945, 984, 990, 993, 995,
+ 997, 999, 1002, 1005, 1008, 1011, 1014, 1018,
+ 1021, 1024, 1027, 1029, 1031, 1034, 1041, 1044,
+ 1046, 1049, 1052, 1055, 1063, 1065, 1067, 1070,
+ 1072, 1075, 1077, 1079, 1109, 1112, 1115, 1118,
+ 1121, 1126, 1130, 1137, 1140, 1149, 1158, 1161,
+ 1165, 1168, 1171, 1175, 1177, 1181, 1183, 1186,
+ 1188, 1192, 1196, 1200, 1208, 1210, 1212, 1216,
+ 1220, 1222, 1235, 1237, 1240, 1243, 1248, 1250,
+ 1253, 1255, 1257, 1260, 1265, 1267, 1269, 1274,
+ 1276, 1279, 1283, 1303, 1307, 1311, 1313, 1315,
+ 1323, 1325, 1332, 1337, 1339, 1343, 1346, 1349,
+ 1352, 1356, 1359, 1362, 1366, 1376, 1382, 1385,
+ 1388, 1398, 1418, 1424, 1427, 1429, 1433, 1435,
+ 1438, 1440, 1444, 1446, 1448, 1452, 1454, 1458,
+ 1463, 1469, 1471, 1473, 1476, 1478, 1482, 1489,
+ 1492, 1494, 1497, 1501, 1531, 1536, 1538, 1541,
+ 1545, 1554, 1559, 1567, 1571, 1579, 1583, 1591,
+ 1595, 1606, 1608, 1614, 1617, 1625, 1629, 1634,
+ 1639, 1644, 1646, 1649, 1664, 1668, 1670, 1673,
+ 1675, 1724, 1727, 1734, 1737, 1739, 1743, 1747,
+ 1750, 1754, 1756, 1759, 1761, 1763, 1765, 1767,
+ 1771, 1773, 1775, 1778, 1782, 1796, 1799, 1803,
+ 1806, 1811, 1822, 1827, 1830, 1860, 1864, 1867,
+ 1872, 1874, 1878, 1881, 1884, 1886, 1891, 1893,
+ 1899, 1904, 1910, 1912, 1932, 1940, 1943, 1945,
+ 1963, 2001, 2003, 2006, 2008, 2013, 2016, 2045,
+ 2047, 2049, 2051, 2053, 2056, 2058, 2062, 2065,
+ 2067, 2070, 2072, 2074, 2077, 2079, 2081, 2083,
+ 2085, 2087, 2090, 2093, 2096, 2109, 2111, 2115,
+ 2118, 2120, 2125, 2128, 2142, 2145, 2154, 2156,
+ 2161, 2165, 2166, 2168, 2170, 2176, 2181, 2186,
+ 2188, 2191, 2193, 2196, 2200, 2206, 2209, 2212,
+ 2218, 2220, 2222, 2224, 2227, 2260, 2262, 2264,
+ 2267, 2270, 2273, 2281, 2289, 2300, 2308, 2317,
+ 2325, 2334, 2343, 2355, 2362, 2369, 2377, 2385,
+ 2394, 2400, 2408, 2414, 2422, 2424, 2427, 2441,
+ 2447, 2455, 2459, 2463, 2465, 2512, 2514, 2517,
+ 2519, 2524, 2530, 2536, 2541, 2544, 2548, 2551,
+ 2554, 2556, 2559, 2562, 2565, 2569, 2574, 2579,
+ 2583, 2585, 2588, 2590, 2594, 2597, 2600, 2603,
+ 2606, 2610, 2615, 2619, 2621, 2623, 2626, 2628,
+ 2632, 2635, 2638, 2646, 2650, 2658, 2674, 2676,
+ 2681, 2683, 2687, 2698, 2702, 2704, 2707, 2709,
+ 2712, 2717, 2721, 2727, 2733, 2744, 2749, 2752,
+ 2755, 2758, 2761, 2763, 2767, 2768, 2771, 2773,
+ 2803, 2805, 2807, 2810, 2814, 2817, 2821, 2823,
+ 2825, 2827, 2833, 2836, 2839, 2843, 2845, 2850,
+ 2855, 2862, 2865, 2869, 2873, 2875, 2878, 2898,
+ 2900, 2902, 2909, 2913, 2915, 2917, 2919, 2922,
+ 2926, 2930, 2932, 2936, 2939, 2941, 2946, 2964,
+ 3003, 3009, 3012, 3014, 3016, 3018, 3021, 3024,
+ 3027, 3030, 3033, 3037, 3040, 3043, 3046, 3048,
+ 3050, 3053, 3060, 3063, 3065, 3068, 3071, 3074,
+ 3082, 3084, 3086, 3089, 3091, 3094, 3096, 3098,
+ 3128, 3131, 3134, 3137, 3140, 3145, 3149, 3156,
+ 3159, 3168, 3177, 3180, 3184, 3187, 3190, 3194,
+ 3196, 3200, 3202, 3205, 3207, 3211, 3215, 3219,
+ 3227, 3229, 3231, 3235, 3239, 3241, 3254, 3256,
+ 3259, 3262, 3267, 3269, 3272, 3274, 3276, 3279,
+ 3284, 3286, 3288, 3293, 3295, 3298, 3302, 3322,
+ 3326, 3330, 3332, 3334, 3342, 3344, 3351, 3356,
+ 3358, 3362, 3365, 3368, 3371, 3375, 3378, 3381,
+ 3385, 3395, 3401, 3404, 3407, 3417, 3437, 3443,
+ 3446, 3448, 3452, 3454, 3457, 3459, 3463, 3465,
+ 3467, 3471, 3473, 3475, 3481, 3484, 3489, 3494,
+ 3500, 3510, 3518, 3530, 3537, 3547, 3553, 3565,
+ 3571, 3589, 3592, 3600, 3606, 3616, 3623, 3630,
+ 3638, 3646, 3649, 3654, 3674, 3680, 3683, 3687,
+ 3691, 3695, 3707, 3710, 3715, 3716, 3722, 3729,
+ 3735, 3738, 3741, 3745, 3749, 3752, 3755, 3760,
+ 3764, 3770, 3776, 3779, 3783, 3786, 3789, 3794,
+ 3797, 3800, 3806, 3810, 3813, 3817, 3820, 3823,
+ 3827, 3831, 3838, 3841, 3844, 3850, 3853, 3860,
+ 3862, 3864, 3867, 3876, 3881, 3895, 3899, 3903,
+ 3918, 3924, 3927, 3930, 3932, 3937, 3943, 3947,
+ 3955, 3961, 3971, 3974, 3977, 3982, 3986, 3989,
+ 3992, 3995, 3999, 4004, 4008, 4012, 4015, 4020,
+ 4025, 4028, 4034, 4038, 4044, 4049, 4053, 4057,
+ 4065, 4068, 4076, 4082, 4092, 4103, 4106, 4109,
+ 4111, 4115, 4117, 4120, 4131, 4135, 4138, 4141,
+ 4144, 4147, 4149, 4153, 4157, 4160, 4164, 4169,
+ 4172, 4182, 4184, 4225, 4231, 4235, 4238, 4241,
+ 4245, 4248, 4252, 4256, 4261, 4263, 4267, 4271,
+ 4274, 4277, 4282, 4291, 4295, 4300, 4305, 4309,
+ 4316, 4320, 4323, 4327, 4330, 4335, 4338, 4341,
+ 4371, 4375, 4379, 4383, 4387, 4392, 4396, 4402,
+ 4406, 4414, 4417, 4422, 4426, 4429, 4434, 4437,
+ 4441, 4444, 4447, 4450, 4453, 4456, 4460, 4464,
+ 4467, 4477, 4480, 4483, 4488, 4494, 4497, 4512,
+ 4515, 4519, 4525, 4529, 4533, 4536, 4540, 4547,
+ 4550, 4553, 4559, 4562, 4566, 4571, 4587, 4589,
+ 4597, 4599, 4607, 4613, 4615, 4619, 4622, 4625,
+ 4628, 4632, 4643, 4646, 4658, 4682, 4690, 4692,
+ 4696, 4699, 4704, 4707, 4709, 4714, 4717, 4723,
+ 4726, 4734, 4736, 4738, 4740, 4742, 4744, 4746,
+ 4748, 4750, 4752, 4755, 4758, 4760, 4762, 4764,
+ 4766, 4769, 4772, 4777, 4781, 4782, 4784, 4786,
+ 4792, 4797, 4802, 4804, 4807, 4809, 4812, 4816,
+ 4822, 4825, 4828, 4834, 4836, 4838, 4840, 4843,
+ 4876, 4878, 4880, 4883, 4886, 4889, 4897, 4905,
+ 4916, 4924, 4933, 4941, 4950, 4959, 4971, 4978,
+ 4985, 4993, 5001, 5010, 5016, 5024, 5030, 5038,
+ 5040, 5043, 5057, 5063, 5071, 5075, 5079, 5081,
+ 5128, 5130, 5133, 5135, 5140, 5146, 5152, 5157,
+ 5160, 5164, 5167, 5170, 5172, 5175, 5178, 5181,
+ 5185, 5190, 5195, 5199, 5201, 5204, 5206, 5210,
+ 5213, 5216, 5219, 5222, 5226, 5231, 5235, 5237,
+ 5239, 5242, 5244, 5248, 5251, 5254, 5262, 5266,
+ 5274, 5290, 5292, 5297, 5299, 5303, 5314, 5318,
+ 5320, 5323, 5325, 5328, 5333, 5337, 5343, 5349,
+ 5360, 5365, 5368, 5371, 5374, 5377, 5379, 5383,
+ 5384, 5387, 5389, 5419, 5421, 5423, 5426, 5430,
+ 5433, 5437, 5439, 5441, 5443, 5449, 5452, 5455,
+ 5459, 5461, 5466, 5471, 5478, 5481, 5485, 5489,
+ 5491, 5494, 5514, 5516, 5518, 5525, 5529, 5531,
+ 5533, 5535, 5538, 5542, 5546, 5548, 5552, 5555,
+ 5557, 5562, 5580, 5619, 5625, 5628, 5630, 5632,
+ 5634, 5637, 5640, 5643, 5646, 5649, 5653, 5656,
+ 5659, 5662, 5664, 5666, 5669, 5676, 5679, 5681,
+ 5684, 5687, 5690, 5698, 5700, 5702, 5705, 5707,
+ 5710, 5712, 5714, 5744, 5747, 5750, 5753, 5756,
+ 5761, 5765, 5772, 5775, 5784, 5793, 5796, 5800,
+ 5803, 5806, 5810, 5812, 5816, 5818, 5821, 5823,
+ 5827, 5831, 5835, 5843, 5845, 5847, 5851, 5855,
+ 5857, 5870, 5872, 5875, 5878, 5883, 5885, 5888,
+ 5890, 5892, 5895, 5900, 5902, 5904, 5909, 5911,
+ 5914, 5918, 5938, 5942, 5946, 5948, 5950, 5958,
+ 5960, 5967, 5972, 5974, 5978, 5981, 5984, 5987,
+ 5991, 5994, 5997, 6001, 6011, 6017, 6020, 6023,
+ 6033, 6053, 6059, 6062, 6064, 6068, 6070, 6073,
+ 6075, 6079, 6081, 6083, 6087, 6089, 6091, 6097,
+ 6100, 6105, 6110, 6116, 6126, 6134, 6146, 6153,
+ 6163, 6169, 6181, 6187, 6205, 6208, 6216, 6222,
+ 6232, 6239, 6246, 6254, 6262, 6265, 6270, 6290,
+ 6296, 6299, 6303, 6307, 6311, 6323, 6326, 6331,
+ 6332, 6338, 6345, 6351, 6354, 6357, 6361, 6365,
+ 6368, 6371, 6376, 6380, 6386, 6392, 6395, 6399,
+ 6402, 6405, 6410, 6413, 6416, 6422, 6426, 6429,
+ 6433, 6436, 6439, 6443, 6447, 6454, 6457, 6460,
+ 6466, 6469, 6476, 6478, 6480, 6483, 6492, 6497,
+ 6511, 6515, 6519, 6534, 6540, 6543, 6546, 6548,
+ 6553, 6559, 6563, 6571, 6577, 6587, 6590, 6593,
+ 6598, 6602, 6605, 6608, 6611, 6615, 6620, 6624,
+ 6628, 6631, 6636, 6641, 6644, 6650, 6654, 6660,
+ 6665, 6669, 6673, 6681, 6684, 6692, 6698, 6708,
+ 6719, 6722, 6725, 6727, 6731, 6733, 6736, 6747,
+ 6751, 6754, 6757, 6760, 6763, 6765, 6769, 6773,
+ 6776, 6780, 6785, 6788, 6798, 6800, 6841, 6847,
+ 6851, 6854, 6857, 6861, 6864, 6868, 6872, 6877,
+ 6879, 6883, 6887, 6890, 6893, 6898, 6907, 6911,
+ 6916, 6921, 6925, 6932, 6936, 6939, 6943, 6946,
+ 6951, 6954, 6957, 6987, 6991, 6995, 6999, 7003,
+ 7008, 7012, 7018, 7022, 7030, 7033, 7038, 7042,
+ 7045, 7050, 7053, 7057, 7060, 7063, 7066, 7069,
+ 7072, 7076, 7080, 7083, 7093, 7096, 7099, 7104,
+ 7110, 7113, 7128, 7131, 7135, 7141, 7145, 7149,
+ 7152, 7156, 7163, 7166, 7169, 7175, 7178, 7182,
+ 7187, 7203, 7205, 7213, 7215, 7223, 7229, 7231,
+ 7235, 7238, 7241, 7244, 7248, 7259, 7262, 7274,
+ 7298, 7306, 7308, 7312, 7315, 7320, 7323, 7325,
+ 7330, 7333, 7339, 7342, 7408, 7411, 7413, 7415,
+ 7417, 7419, 7421, 7424, 7429, 7431, 7434, 7437,
+ 7439, 7479, 7481, 7483, 7485, 7490, 7494, 7495,
+ 7497, 7499, 7506, 7513, 7520, 7522, 7524, 7526,
+ 7529, 7532, 7538, 7541, 7546, 7553, 7558, 7561,
+ 7565, 7572, 7604, 7653, 7668, 7681, 7686, 7688,
+ 7692, 7723, 7729, 7731, 7752, 7772, 7774, 7786,
+ 7797, 7800, 7803, 7804, 7806, 7808, 7810, 7813,
+ 7815, 7823, 7825, 7827, 7829, 7839, 7848, 7851,
+ 7855, 7859, 7862, 7864, 7866, 7868, 7870, 7872,
+ 7882, 7891, 7894, 7898, 7902, 7905, 7907, 7909,
+ 7911, 7913, 7915, 7957, 7997, 7999, 8004, 8008,
+ 8009, 8011, 8013, 8020, 8027, 8034, 8036, 8038,
+ 8040, 8043, 8046, 8052, 8055, 8060, 8067, 8072,
+ 8075, 8079, 8086, 8118, 8167, 8182, 8195, 8200,
+ 8202, 8206, 8237, 8243, 8245, 8266, 8286,
+}
+
+var _hcltok_indicies []int16 = []int16{
+ 1, 0, 3, 2, 3, 4, 2, 6,
+ 8, 8, 7, 5, 9, 9, 7, 5,
+ 7, 5, 10, 11, 12, 13, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 39, 40, 41,
+ 42, 43, 11, 11, 14, 14, 38, 0,
+ 11, 12, 13, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 39, 40, 41, 42, 43, 11,
+ 11, 14, 14, 38, 0, 44, 45, 11,
+ 11, 46, 13, 15, 16, 17, 16, 47,
+ 48, 20, 49, 22, 23, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 37, 39, 63, 41, 64, 65,
+ 66, 11, 11, 11, 14, 38, 0, 44,
+ 0, 11, 11, 11, 11, 0, 11, 11,
+ 11, 0, 11, 0, 11, 0, 11, 0,
+ 0, 0, 0, 0, 11, 0, 0, 0,
+ 0, 11, 11, 11, 11, 11, 0, 0,
+ 11, 0, 0, 11, 0, 11, 0, 0,
+ 11, 0, 0, 0, 11, 11, 11, 11,
+ 11, 11, 0, 11, 11, 0, 11, 11,
+ 0, 0, 0, 0, 0, 0, 11, 11,
+ 0, 0, 11, 0, 11, 11, 11, 0,
+ 67, 68, 69, 70, 14, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97,
+ 0, 11, 0, 11, 0, 11, 11, 0,
+ 11, 11, 0, 0, 0, 11, 0, 0,
+ 0, 0, 0, 0, 0, 11, 0, 0,
+ 0, 0, 0, 0, 0, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 0, 11, 11, 11, 11, 11,
+ 11, 11, 11, 0, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 0,
+ 11, 11, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 11, 11, 0, 0, 0,
+ 0, 0, 0, 0, 0, 11, 11, 11,
+ 11, 11, 11, 11, 11, 0, 11, 11,
+ 11, 11, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 11, 11, 11, 11,
+ 11, 11, 0, 11, 11, 11, 11, 11,
+ 11, 11, 0, 11, 0, 11, 11, 0,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 0, 11, 11,
+ 11, 11, 11, 0, 11, 11, 11, 11,
+ 11, 11, 11, 0, 11, 11, 11, 0,
+ 11, 11, 11, 0, 11, 0, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 16,
+ 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 14, 15, 133, 134, 135, 136,
+ 137, 14, 16, 14, 0, 11, 0, 11,
+ 11, 0, 0, 11, 0, 0, 0, 0,
+ 11, 0, 0, 0, 0, 0, 11, 0,
+ 0, 0, 0, 0, 11, 11, 11, 11,
+ 11, 0, 0, 0, 11, 0, 0, 0,
+ 11, 11, 11, 0, 0, 0, 11, 11,
+ 0, 0, 0, 11, 11, 11, 0, 0,
+ 0, 11, 11, 11, 11, 0, 11, 11,
+ 11, 11, 0, 0, 0, 0, 0, 11,
+ 11, 11, 11, 0, 0, 11, 11, 11,
+ 0, 0, 11, 11, 11, 11, 0, 11,
+ 11, 0, 11, 11, 0, 0, 0, 11,
+ 11, 11, 0, 0, 0, 0, 11, 11,
+ 11, 11, 11, 0, 0, 0, 0, 11,
+ 0, 11, 11, 0, 11, 11, 0, 11,
+ 0, 11, 11, 11, 0, 11, 11, 0,
+ 0, 0, 11, 0, 0, 0, 0, 0,
+ 0, 0, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 11, 11, 11, 0, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146,
+ 14, 147, 148, 149, 150, 151, 0, 11,
+ 0, 0, 0, 0, 0, 11, 11, 0,
+ 11, 11, 11, 0, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 0, 11,
+ 11, 11, 0, 0, 11, 11, 11, 0,
+ 0, 11, 0, 0, 11, 11, 11, 11,
+ 11, 0, 0, 0, 0, 11, 11, 11,
+ 11, 11, 11, 0, 11, 11, 11, 11,
+ 11, 0, 152, 109, 153, 154, 155, 14,
+ 156, 157, 16, 14, 0, 11, 11, 11,
+ 11, 0, 0, 0, 11, 0, 0, 11,
+ 11, 11, 0, 0, 0, 11, 11, 0,
+ 119, 0, 16, 14, 14, 158, 0, 14,
+ 0, 11, 16, 159, 160, 16, 161, 162,
+ 16, 57, 163, 164, 165, 166, 167, 16,
+ 168, 169, 170, 16, 171, 172, 173, 15,
+ 174, 175, 176, 15, 177, 16, 14, 0,
+ 0, 11, 11, 0, 0, 0, 11, 11,
+ 11, 11, 0, 11, 11, 0, 0, 0,
+ 0, 11, 11, 0, 0, 11, 11, 0,
+ 0, 0, 0, 0, 0, 11, 11, 11,
+ 0, 0, 0, 11, 0, 0, 0, 11,
+ 11, 0, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 0, 11, 11, 11, 11,
+ 11, 11, 0, 0, 0, 11, 11, 11,
+ 11, 0, 178, 179, 0, 14, 0, 11,
+ 0, 0, 11, 16, 180, 181, 182, 183,
+ 57, 184, 185, 55, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 14, 0, 0,
+ 11, 0, 11, 11, 11, 11, 11, 11,
+ 11, 0, 11, 11, 11, 0, 11, 0,
+ 0, 11, 0, 11, 0, 0, 11, 11,
+ 11, 11, 0, 11, 11, 11, 0, 0,
+ 11, 11, 11, 11, 0, 11, 11, 0,
+ 0, 11, 11, 11, 11, 11, 0, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 201, 206, 207, 208, 209, 38,
+ 0, 210, 211, 16, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 16, 14, 221,
+ 222, 223, 224, 16, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 16, 144, 14, 240, 0,
+ 11, 11, 11, 11, 11, 0, 0, 0,
+ 11, 0, 11, 11, 0, 11, 0, 11,
+ 11, 0, 0, 0, 11, 11, 11, 0,
+ 0, 0, 11, 11, 11, 0, 0, 0,
+ 0, 11, 0, 0, 11, 0, 0, 11,
+ 11, 11, 0, 0, 11, 0, 11, 11,
+ 11, 0, 11, 11, 11, 11, 11, 11,
+ 0, 0, 0, 11, 11, 0, 11, 11,
+ 0, 11, 11, 0, 11, 11, 0, 11,
+ 11, 11, 11, 11, 11, 11, 0, 11,
+ 0, 11, 0, 11, 11, 0, 11, 0,
+ 11, 11, 0, 11, 0, 11, 0, 241,
+ 212, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 98, 251, 16, 252, 253, 254,
+ 16, 255, 129, 256, 257, 258, 259, 260,
+ 261, 262, 263, 16, 0, 0, 0, 11,
+ 11, 11, 0, 11, 11, 0, 11, 11,
+ 0, 0, 0, 0, 0, 11, 11, 11,
+ 11, 0, 11, 11, 11, 11, 11, 11,
+ 0, 0, 0, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 0, 11, 11, 11,
+ 11, 11, 11, 11, 11, 0, 11, 11,
+ 0, 0, 0, 0, 11, 11, 11, 0,
+ 0, 0, 11, 0, 0, 0, 11, 11,
+ 0, 11, 11, 11, 0, 11, 0, 0,
+ 0, 11, 11, 0, 11, 11, 11, 0,
+ 11, 11, 11, 0, 0, 0, 0, 11,
+ 16, 181, 264, 265, 14, 16, 14, 0,
+ 0, 11, 0, 11, 16, 264, 14, 0,
+ 16, 266, 14, 0, 0, 11, 16, 267,
+ 268, 269, 172, 270, 271, 16, 272, 273,
+ 274, 14, 0, 0, 11, 11, 11, 0,
+ 11, 11, 0, 11, 11, 11, 11, 0,
+ 0, 11, 0, 0, 11, 11, 0, 11,
+ 0, 16, 14, 0, 275, 16, 276, 0,
+ 14, 0, 11, 0, 11, 277, 16, 278,
+ 279, 0, 11, 0, 0, 0, 11, 11,
+ 11, 11, 0, 280, 281, 282, 16, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 14, 0, 11,
+ 11, 11, 0, 0, 0, 0, 11, 11,
+ 0, 0, 11, 0, 0, 0, 0, 0,
+ 0, 0, 11, 0, 11, 0, 0, 0,
+ 0, 0, 0, 11, 11, 11, 11, 11,
+ 0, 0, 11, 0, 0, 0, 11, 0,
+ 0, 11, 0, 0, 11, 0, 0, 11,
+ 0, 0, 0, 11, 11, 11, 0, 0,
+ 0, 11, 11, 11, 11, 0, 297, 16,
+ 298, 16, 299, 300, 301, 302, 14, 0,
+ 11, 11, 11, 11, 11, 0, 0, 0,
+ 11, 0, 0, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 0, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 0, 11, 11, 11, 11, 11, 0,
+ 303, 16, 14, 0, 11, 304, 16, 100,
+ 14, 0, 11, 305, 0, 14, 0, 11,
+ 16, 306, 14, 0, 0, 11, 307, 0,
+ 16, 308, 14, 0, 0, 11, 11, 11,
+ 11, 0, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 11, 0, 0, 11, 0,
+ 11, 11, 11, 0, 11, 0, 11, 11,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 11, 11, 11, 0, 11, 0, 0, 0,
+ 11, 11, 11, 11, 0, 309, 310, 69,
+ 311, 312, 313, 314, 315, 316, 317, 318,
+ 319, 320, 321, 322, 323, 324, 325, 326,
+ 327, 328, 329, 331, 332, 333, 334, 335,
+ 336, 330, 0, 11, 11, 11, 11, 0,
+ 11, 0, 11, 11, 0, 11, 11, 11,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 11, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 11, 11, 11, 0, 11,
+ 11, 11, 0, 11, 11, 11, 11, 11,
+ 11, 11, 0, 11, 11, 11, 0, 11,
+ 11, 11, 11, 11, 11, 11, 0, 11,
+ 11, 11, 0, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 0, 11, 0,
+ 11, 11, 11, 11, 11, 0, 11, 11,
+ 0, 11, 11, 11, 11, 11, 11, 11,
+ 0, 11, 11, 11, 0, 11, 11, 11,
+ 11, 0, 11, 11, 11, 11, 0, 11,
+ 11, 11, 11, 0, 11, 0, 11, 11,
+ 0, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 0,
+ 11, 11, 11, 0, 11, 0, 11, 11,
+ 0, 11, 0, 337, 338, 339, 101, 102,
+ 103, 104, 105, 340, 107, 108, 109, 110,
+ 111, 112, 341, 342, 167, 343, 258, 117,
+ 344, 119, 229, 269, 122, 345, 346, 347,
+ 348, 349, 350, 351, 352, 353, 354, 131,
+ 355, 16, 14, 15, 16, 134, 135, 136,
+ 137, 14, 14, 0, 11, 11, 0, 11,
+ 11, 11, 11, 11, 11, 0, 0, 0,
+ 11, 0, 11, 11, 11, 11, 0, 11,
+ 11, 11, 0, 11, 11, 0, 11, 11,
+ 11, 0, 0, 11, 11, 11, 0, 0,
+ 11, 11, 0, 11, 0, 11, 0, 11,
+ 11, 11, 0, 0, 11, 11, 0, 11,
+ 11, 0, 11, 11, 11, 0, 356, 140,
+ 142, 143, 144, 145, 146, 14, 357, 148,
+ 358, 150, 359, 0, 11, 11, 0, 0,
+ 0, 0, 11, 0, 0, 11, 11, 11,
+ 11, 11, 0, 360, 109, 361, 154, 155,
+ 14, 156, 157, 16, 14, 0, 11, 11,
+ 11, 11, 0, 0, 0, 11, 16, 159,
+ 160, 16, 362, 363, 219, 308, 163, 164,
+ 165, 364, 167, 365, 366, 367, 368, 369,
+ 370, 371, 372, 373, 374, 175, 176, 15,
+ 375, 16, 14, 0, 0, 0, 0, 11,
+ 11, 11, 0, 0, 0, 0, 0, 11,
+ 11, 0, 11, 11, 11, 0, 11, 11,
+ 0, 0, 0, 11, 11, 0, 11, 11,
+ 11, 11, 0, 11, 0, 11, 11, 11,
+ 11, 11, 0, 0, 0, 0, 0, 11,
+ 11, 11, 11, 11, 11, 0, 11, 0,
+ 16, 180, 181, 376, 183, 57, 184, 185,
+ 55, 186, 187, 377, 14, 190, 378, 192,
+ 193, 194, 14, 0, 11, 11, 11, 11,
+ 11, 11, 11, 0, 11, 11, 0, 11,
+ 0, 379, 380, 197, 198, 199, 381, 201,
+ 202, 382, 383, 384, 201, 206, 207, 208,
+ 209, 38, 0, 210, 211, 16, 212, 213,
+ 215, 385, 217, 386, 219, 220, 16, 14,
+ 387, 222, 223, 224, 16, 225, 226, 227,
+ 228, 229, 230, 231, 232, 388, 234, 235,
+ 389, 237, 238, 239, 16, 144, 14, 240,
+ 0, 0, 11, 0, 0, 11, 0, 11,
+ 11, 11, 11, 11, 0, 11, 11, 0,
+ 390, 391, 392, 393, 394, 395, 396, 397,
+ 247, 398, 319, 399, 213, 400, 401, 402,
+ 403, 404, 401, 405, 406, 407, 258, 408,
+ 260, 409, 410, 271, 0, 11, 0, 11,
+ 0, 11, 0, 11, 0, 11, 11, 0,
+ 11, 0, 11, 11, 11, 0, 11, 11,
+ 0, 0, 11, 11, 11, 0, 11, 0,
+ 11, 0, 11, 11, 0, 11, 0, 11,
+ 0, 11, 0, 11, 0, 11, 0, 0,
+ 0, 11, 11, 11, 0, 11, 11, 0,
+ 16, 267, 229, 411, 401, 412, 271, 16,
+ 413, 414, 274, 14, 0, 11, 0, 11,
+ 11, 11, 0, 0, 0, 11, 11, 0,
+ 277, 16, 278, 415, 0, 11, 11, 0,
+ 16, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 416, 14, 0, 0, 0,
+ 11, 16, 417, 16, 265, 300, 301, 302,
+ 14, 0, 0, 11, 419, 419, 419, 419,
+ 418, 419, 419, 419, 418, 419, 418, 419,
+ 418, 419, 418, 418, 418, 418, 418, 419,
+ 418, 418, 418, 418, 419, 419, 419, 419,
+ 419, 418, 418, 419, 418, 418, 419, 418,
+ 419, 418, 418, 419, 418, 418, 418, 419,
+ 419, 419, 419, 419, 419, 418, 419, 419,
+ 418, 419, 419, 418, 418, 418, 418, 418,
+ 418, 419, 419, 418, 418, 419, 418, 419,
+ 419, 419, 418, 421, 422, 423, 424, 425,
+ 426, 427, 428, 429, 430, 431, 432, 433,
+ 434, 435, 436, 437, 438, 439, 440, 441,
+ 442, 443, 444, 445, 446, 447, 448, 449,
+ 450, 451, 452, 418, 419, 418, 419, 418,
+ 419, 419, 418, 419, 419, 418, 418, 418,
+ 419, 418, 418, 418, 418, 418, 418, 418,
+ 419, 418, 418, 418, 418, 418, 418, 418,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 418, 418, 418, 418, 418,
+ 418, 418, 418, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 418, 418, 418, 418,
+ 418, 418, 418, 418, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 418, 419, 419,
+ 419, 419, 419, 419, 419, 419, 418, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 418, 419, 419, 419, 419, 419,
+ 419, 418, 419, 419, 419, 419, 419, 419,
+ 418, 418, 418, 418, 418, 418, 418, 418,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 418, 419, 419, 419, 419, 419, 419, 419,
+ 419, 418, 419, 419, 419, 419, 419, 418,
+ 418, 418, 418, 418, 418, 418, 418, 419,
+ 419, 419, 419, 419, 419, 418, 419, 419,
+ 419, 419, 419, 419, 419, 418, 419, 418,
+ 419, 419, 418, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 418, 419, 419, 419, 419, 419, 418, 419,
+ 419, 419, 419, 419, 419, 419, 418, 419,
+ 419, 419, 418, 419, 419, 419, 418, 419,
+ 418, 453, 454, 455, 456, 457, 458, 459,
+ 460, 461, 462, 463, 464, 465, 466, 467,
+ 468, 469, 470, 471, 472, 473, 474, 475,
+ 476, 477, 478, 479, 480, 481, 482, 483,
+ 484, 485, 486, 487, 488, 425, 489, 490,
+ 491, 492, 493, 494, 425, 470, 425, 418,
+ 419, 418, 419, 419, 418, 418, 419, 418,
+ 418, 418, 418, 419, 418, 418, 418, 418,
+ 418, 419, 418, 418, 418, 418, 418, 419,
+ 419, 419, 419, 419, 418, 418, 418, 419,
+ 418, 418, 418, 419, 419, 419, 418, 418,
+ 418, 419, 419, 418, 418, 418, 419, 419,
+ 419, 418, 418, 418, 419, 419, 419, 419,
+ 418, 419, 419, 419, 419, 418, 418, 418,
+ 418, 418, 419, 419, 419, 419, 418, 418,
+ 419, 419, 419, 418, 418, 419, 419, 419,
+ 419, 418, 419, 419, 418, 419, 419, 418,
+ 418, 418, 419, 419, 419, 418, 418, 418,
+ 418, 419, 419, 419, 419, 419, 418, 418,
+ 418, 418, 419, 418, 419, 419, 418, 419,
+ 419, 418, 419, 418, 419, 419, 419, 418,
+ 419, 419, 418, 418, 418, 419, 418, 418,
+ 418, 418, 418, 418, 418, 419, 419, 419,
+ 419, 418, 419, 419, 419, 419, 419, 419,
+ 419, 418, 495, 496, 497, 498, 499, 500,
+ 501, 502, 503, 425, 504, 505, 506, 507,
+ 508, 418, 419, 418, 418, 418, 418, 418,
+ 419, 419, 418, 419, 419, 419, 418, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 418, 419, 419, 419, 418, 418, 419,
+ 419, 419, 418, 418, 419, 418, 418, 419,
+ 419, 419, 419, 419, 418, 418, 418, 418,
+ 419, 419, 419, 419, 419, 419, 418, 419,
+ 419, 419, 419, 419, 418, 509, 464, 510,
+ 511, 512, 425, 513, 514, 470, 425, 418,
+ 419, 419, 419, 419, 418, 418, 418, 419,
+ 418, 418, 419, 419, 419, 418, 418, 418,
+ 419, 419, 418, 475, 418, 470, 425, 425,
+ 515, 418, 425, 418, 419, 470, 516, 517,
+ 470, 518, 519, 470, 520, 521, 522, 523,
+ 524, 525, 470, 526, 527, 528, 470, 529,
+ 530, 531, 489, 532, 533, 534, 489, 535,
+ 470, 425, 418, 418, 419, 419, 418, 418,
+ 418, 419, 419, 419, 419, 418, 419, 419,
+ 418, 418, 418, 418, 419, 419, 418, 418,
+ 419, 419, 418, 418, 418, 418, 418, 418,
+ 419, 419, 419, 418, 418, 418, 419, 418,
+ 418, 418, 419, 419, 418, 419, 419, 419,
+ 419, 418, 419, 419, 419, 419, 418, 419,
+ 419, 419, 419, 419, 419, 418, 418, 418,
+ 419, 419, 419, 419, 418, 536, 537, 418,
+ 425, 418, 419, 418, 418, 419, 470, 538,
+ 539, 540, 541, 520, 542, 543, 544, 545,
+ 546, 547, 548, 549, 550, 551, 552, 553,
+ 425, 418, 418, 419, 418, 419, 419, 419,
+ 419, 419, 419, 419, 418, 419, 419, 419,
+ 418, 419, 418, 418, 419, 418, 419, 418,
+ 418, 419, 419, 419, 419, 418, 419, 419,
+ 419, 418, 418, 419, 419, 419, 419, 418,
+ 419, 419, 418, 418, 419, 419, 419, 419,
+ 419, 418, 554, 555, 556, 557, 558, 559,
+ 560, 561, 562, 563, 564, 560, 566, 567,
+ 568, 569, 565, 418, 570, 571, 470, 572,
+ 573, 574, 575, 576, 577, 578, 579, 580,
+ 470, 425, 581, 582, 583, 584, 470, 585,
+ 586, 587, 588, 589, 590, 591, 592, 593,
+ 594, 595, 596, 597, 598, 599, 470, 501,
+ 425, 600, 418, 419, 419, 419, 419, 419,
+ 418, 418, 418, 419, 418, 419, 419, 418,
+ 419, 418, 419, 419, 418, 418, 418, 419,
+ 419, 419, 418, 418, 418, 419, 419, 419,
+ 418, 418, 418, 418, 419, 418, 418, 419,
+ 418, 418, 419, 419, 419, 418, 418, 419,
+ 418, 419, 419, 419, 418, 419, 419, 419,
+ 419, 419, 419, 418, 418, 418, 419, 419,
+ 418, 419, 419, 418, 419, 419, 418, 419,
+ 419, 418, 419, 419, 419, 419, 419, 419,
+ 419, 418, 419, 418, 419, 418, 419, 419,
+ 418, 419, 418, 419, 419, 418, 419, 418,
+ 419, 418, 601, 572, 602, 603, 604, 605,
+ 606, 607, 608, 609, 610, 453, 611, 470,
+ 612, 613, 614, 470, 615, 485, 616, 617,
+ 618, 619, 620, 621, 622, 623, 470, 418,
+ 418, 418, 419, 419, 419, 418, 419, 419,
+ 418, 419, 419, 418, 418, 418, 418, 418,
+ 419, 419, 419, 419, 418, 419, 419, 419,
+ 419, 419, 419, 418, 418, 418, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 418,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 418, 419, 419, 418, 418, 418, 418, 419,
+ 419, 419, 418, 418, 418, 419, 418, 418,
+ 418, 419, 419, 418, 419, 419, 419, 418,
+ 419, 418, 418, 418, 419, 419, 418, 419,
+ 419, 419, 418, 419, 419, 419, 418, 418,
+ 418, 418, 419, 470, 539, 624, 625, 425,
+ 470, 425, 418, 418, 419, 418, 419, 470,
+ 624, 425, 418, 470, 626, 425, 418, 418,
+ 419, 470, 627, 628, 629, 530, 630, 631,
+ 470, 632, 633, 634, 425, 418, 418, 419,
+ 419, 419, 418, 419, 419, 418, 419, 419,
+ 419, 419, 418, 418, 419, 418, 418, 419,
+ 419, 418, 419, 418, 470, 425, 418, 635,
+ 470, 636, 418, 425, 418, 419, 418, 419,
+ 637, 470, 638, 639, 418, 419, 418, 418,
+ 418, 419, 419, 419, 419, 418, 640, 641,
+ 642, 470, 643, 644, 645, 646, 647, 648,
+ 649, 650, 651, 652, 653, 654, 655, 656,
+ 425, 418, 419, 419, 419, 418, 418, 418,
+ 418, 419, 419, 418, 418, 419, 418, 418,
+ 418, 418, 418, 418, 418, 419, 418, 419,
+ 418, 418, 418, 418, 418, 418, 419, 419,
+ 419, 419, 419, 418, 418, 419, 418, 418,
+ 418, 419, 418, 418, 419, 418, 418, 419,
+ 418, 418, 419, 418, 418, 418, 419, 419,
+ 419, 418, 418, 418, 419, 419, 419, 419,
+ 418, 657, 470, 658, 470, 659, 660, 661,
+ 662, 425, 418, 419, 419, 419, 419, 419,
+ 418, 418, 418, 419, 418, 418, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 418, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 418, 419, 419, 419,
+ 419, 419, 418, 663, 470, 425, 418, 419,
+ 664, 470, 455, 425, 418, 419, 665, 418,
+ 425, 418, 419, 470, 666, 425, 418, 418,
+ 419, 667, 418, 470, 668, 425, 418, 418,
+ 419, 670, 669, 419, 419, 419, 419, 670,
+ 669, 419, 670, 669, 670, 670, 419, 670,
+ 669, 419, 670, 419, 670, 669, 419, 670,
+ 419, 670, 419, 669, 670, 670, 670, 670,
+ 670, 670, 670, 670, 669, 419, 419, 670,
+ 670, 419, 670, 419, 670, 669, 670, 670,
+ 670, 670, 670, 419, 670, 419, 670, 419,
+ 670, 669, 670, 670, 419, 670, 419, 670,
+ 669, 670, 670, 670, 670, 670, 419, 670,
+ 419, 670, 669, 419, 419, 670, 419, 670,
+ 669, 670, 670, 670, 419, 670, 419, 670,
+ 419, 670, 419, 670, 669, 670, 419, 670,
+ 419, 670, 669, 419, 670, 670, 670, 670,
+ 419, 670, 419, 670, 419, 670, 419, 670,
+ 419, 670, 419, 670, 669, 419, 670, 669,
+ 670, 670, 670, 419, 670, 419, 670, 669,
+ 670, 419, 670, 419, 670, 669, 419, 670,
+ 670, 670, 670, 419, 670, 419, 670, 669,
+ 419, 670, 419, 670, 419, 670, 669, 670,
+ 670, 419, 670, 419, 670, 669, 419, 670,
+ 419, 670, 419, 670, 419, 669, 670, 670,
+ 670, 419, 670, 419, 670, 669, 419, 670,
+ 669, 670, 670, 419, 670, 669, 670, 670,
+ 670, 419, 670, 670, 670, 670, 670, 670,
+ 419, 419, 670, 419, 670, 419, 670, 419,
+ 670, 669, 670, 419, 670, 419, 670, 669,
+ 419, 670, 669, 670, 419, 670, 669, 670,
+ 419, 670, 669, 419, 419, 670, 669, 419,
+ 670, 419, 670, 419, 670, 419, 670, 419,
+ 670, 419, 669, 670, 670, 419, 670, 670,
+ 670, 670, 419, 419, 670, 670, 670, 670,
+ 670, 419, 670, 670, 670, 670, 670, 669,
+ 419, 670, 670, 419, 670, 419, 669, 670,
+ 670, 419, 670, 669, 419, 419, 670, 419,
+ 669, 670, 670, 669, 419, 670, 419, 669,
+ 670, 669, 419, 670, 419, 670, 419, 669,
+ 670, 670, 669, 419, 670, 419, 670, 419,
+ 670, 669, 670, 419, 670, 419, 670, 669,
+ 419, 670, 669, 419, 419, 670, 669, 670,
+ 419, 669, 670, 669, 419, 670, 419, 670,
+ 419, 669, 670, 669, 419, 419, 670, 669,
+ 670, 419, 670, 419, 670, 669, 419, 670,
+ 419, 669, 670, 669, 419, 419, 670, 419,
+ 669, 670, 669, 419, 419, 670, 669, 670,
+ 419, 670, 669, 670, 419, 670, 669, 670,
+ 419, 670, 419, 670, 419, 669, 670, 669,
+ 419, 419, 670, 669, 670, 419, 670, 419,
+ 670, 669, 419, 670, 669, 670, 670, 419,
+ 670, 419, 670, 669, 669, 419, 669, 419,
+ 670, 670, 419, 670, 670, 670, 670, 670,
+ 670, 670, 669, 419, 670, 670, 670, 419,
+ 669, 670, 670, 670, 419, 670, 419, 670,
+ 419, 670, 419, 670, 419, 670, 669, 419,
+ 419, 670, 669, 670, 419, 670, 669, 419,
+ 419, 670, 419, 419, 419, 670, 419, 670,
+ 419, 670, 419, 670, 419, 669, 419, 670,
+ 419, 670, 419, 669, 670, 669, 419, 670,
+ 419, 669, 670, 419, 670, 670, 670, 669,
+ 419, 670, 419, 419, 670, 419, 669, 670,
+ 670, 669, 419, 670, 670, 670, 670, 419,
+ 670, 419, 669, 670, 670, 670, 419, 670,
+ 669, 670, 419, 670, 419, 670, 419, 670,
+ 419, 670, 669, 670, 670, 419, 670, 669,
+ 419, 670, 419, 670, 419, 669, 670, 670,
+ 669, 419, 670, 419, 669, 670, 669, 419,
+ 670, 669, 419, 670, 419, 670, 669, 670,
+ 670, 670, 669, 419, 419, 419, 670, 669,
+ 419, 670, 419, 669, 670, 669, 419, 670,
+ 419, 670, 419, 669, 670, 670, 670, 669,
+ 419, 670, 419, 669, 670, 670, 670, 670,
+ 669, 419, 670, 419, 670, 669, 419, 419,
+ 670, 419, 670, 669, 670, 419, 670, 419,
+ 669, 670, 670, 669, 419, 670, 419, 670,
+ 669, 419, 670, 670, 670, 419, 670, 419,
+ 669, 419, 670, 669, 670, 419, 419, 670,
+ 419, 670, 419, 669, 670, 670, 670, 670,
+ 669, 419, 670, 419, 670, 419, 670, 419,
+ 670, 419, 670, 669, 670, 670, 670, 419,
+ 670, 419, 670, 419, 670, 419, 669, 670,
+ 670, 419, 419, 670, 669, 670, 419, 670,
+ 670, 669, 419, 670, 419, 670, 669, 419,
+ 419, 670, 670, 670, 670, 419, 670, 419,
+ 670, 419, 669, 670, 670, 419, 669, 670,
+ 669, 419, 670, 419, 669, 670, 669, 419,
+ 670, 419, 669, 670, 419, 670, 670, 669,
+ 419, 670, 670, 419, 669, 670, 669, 419,
+ 670, 419, 670, 669, 670, 419, 670, 419,
+ 669, 670, 669, 419, 670, 419, 670, 419,
+ 670, 419, 670, 419, 670, 669, 671, 669,
+ 672, 673, 674, 675, 676, 677, 678, 679,
+ 680, 681, 682, 674, 683, 684, 685, 686,
+ 687, 674, 688, 689, 690, 691, 692, 693,
+ 694, 695, 696, 697, 698, 699, 700, 701,
+ 702, 674, 703, 671, 683, 671, 704, 671,
+ 669, 670, 670, 670, 670, 419, 669, 670,
+ 670, 669, 419, 670, 669, 419, 419, 670,
+ 669, 419, 670, 419, 669, 670, 669, 419,
+ 419, 670, 419, 669, 670, 670, 669, 419,
+ 670, 670, 670, 669, 419, 670, 419, 670,
+ 670, 669, 419, 419, 670, 419, 669, 670,
+ 669, 419, 670, 669, 419, 419, 670, 419,
+ 670, 669, 419, 670, 419, 419, 670, 419,
+ 670, 419, 669, 670, 670, 669, 419, 670,
+ 670, 419, 670, 669, 419, 670, 419, 670,
+ 669, 419, 670, 419, 669, 419, 670, 670,
+ 670, 419, 670, 669, 670, 419, 670, 669,
+ 419, 670, 669, 670, 419, 670, 669, 419,
+ 670, 669, 419, 670, 419, 670, 669, 419,
+ 670, 669, 419, 670, 669, 705, 706, 707,
+ 708, 709, 710, 711, 712, 713, 714, 715,
+ 716, 676, 717, 718, 719, 720, 721, 718,
+ 722, 723, 724, 725, 726, 727, 728, 729,
+ 730, 671, 669, 670, 419, 670, 669, 670,
+ 419, 670, 669, 670, 419, 670, 669, 670,
+ 419, 670, 669, 419, 670, 419, 670, 669,
+ 670, 419, 670, 669, 670, 419, 419, 419,
+ 670, 669, 670, 419, 670, 669, 670, 670,
+ 670, 670, 419, 670, 419, 669, 670, 669,
+ 419, 419, 670, 419, 670, 669, 670, 419,
+ 670, 669, 419, 670, 669, 670, 670, 419,
+ 670, 669, 419, 670, 669, 670, 419, 670,
+ 669, 419, 670, 669, 419, 670, 669, 419,
+ 670, 669, 670, 669, 419, 419, 670, 669,
+ 670, 419, 670, 669, 419, 670, 419, 669,
+ 670, 669, 419, 674, 731, 671, 674, 732,
+ 674, 733, 683, 671, 669, 670, 669, 419,
+ 670, 669, 419, 674, 732, 683, 671, 669,
+ 674, 734, 671, 683, 671, 669, 670, 669,
+ 419, 674, 735, 692, 736, 718, 737, 730,
+ 674, 738, 739, 740, 671, 683, 671, 669,
+ 670, 669, 419, 670, 419, 670, 669, 419,
+ 670, 419, 670, 419, 669, 670, 670, 669,
+ 419, 670, 419, 670, 669, 419, 670, 669,
+ 674, 683, 425, 669, 741, 674, 742, 683,
+ 671, 669, 425, 670, 669, 419, 670, 669,
+ 419, 743, 674, 744, 745, 671, 669, 419,
+ 670, 669, 670, 670, 669, 419, 419, 670,
+ 419, 670, 669, 674, 746, 747, 748, 749,
+ 750, 751, 752, 753, 754, 755, 756, 671,
+ 683, 671, 669, 670, 419, 670, 670, 670,
+ 670, 670, 670, 670, 419, 670, 419, 670,
+ 670, 670, 670, 670, 670, 669, 419, 670,
+ 670, 419, 670, 419, 669, 670, 419, 670,
+ 670, 670, 419, 670, 670, 419, 670, 670,
+ 419, 670, 670, 419, 670, 670, 669, 419,
+ 674, 757, 674, 733, 758, 759, 760, 671,
+ 683, 671, 669, 670, 669, 419, 670, 670,
+ 670, 419, 670, 670, 670, 419, 670, 419,
+ 670, 669, 419, 419, 419, 419, 670, 670,
+ 419, 419, 419, 419, 419, 670, 670, 670,
+ 670, 670, 670, 670, 419, 670, 419, 670,
+ 419, 669, 670, 670, 670, 419, 670, 419,
+ 670, 669, 683, 425, 761, 674, 683, 425,
+ 670, 669, 419, 762, 674, 763, 683, 425,
+ 670, 669, 419, 670, 419, 764, 683, 671,
+ 669, 425, 670, 669, 419, 674, 765, 671,
+ 683, 671, 669, 670, 669, 419, 766, 766,
+ 766, 768, 769, 770, 766, 767, 767, 771,
+ 768, 771, 769, 771, 767, 772, 773, 772,
+ 775, 774, 776, 774, 777, 774, 779, 778,
+ 781, 782, 780, 781, 783, 780, 785, 784,
+ 786, 784, 787, 784, 789, 788, 791, 792,
+ 790, 791, 793, 790, 795, 795, 795, 795,
+ 794, 795, 795, 795, 794, 795, 794, 795,
+ 795, 794, 794, 794, 794, 794, 794, 795,
+ 794, 794, 794, 794, 795, 795, 795, 795,
+ 795, 794, 794, 795, 794, 794, 795, 794,
+ 795, 794, 794, 795, 794, 794, 794, 795,
+ 795, 795, 795, 795, 795, 794, 795, 795,
+ 794, 795, 795, 794, 794, 794, 794, 794,
+ 794, 795, 795, 794, 794, 795, 794, 795,
+ 795, 795, 794, 797, 798, 799, 800, 801,
+ 802, 803, 804, 805, 806, 807, 808, 809,
+ 810, 811, 812, 813, 814, 815, 816, 817,
+ 818, 819, 820, 821, 822, 823, 824, 825,
+ 826, 827, 828, 794, 795, 794, 795, 794,
+ 795, 795, 794, 795, 795, 794, 794, 794,
+ 795, 794, 794, 794, 794, 794, 794, 794,
+ 795, 794, 794, 794, 794, 794, 794, 794,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 794, 794, 794, 794, 794,
+ 794, 794, 794, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 794, 794, 794, 794,
+ 794, 794, 794, 794, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 794, 795, 795,
+ 795, 795, 795, 795, 795, 795, 794, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 794, 795, 795, 795, 795, 795,
+ 795, 794, 795, 795, 795, 795, 795, 795,
+ 794, 794, 794, 794, 794, 794, 794, 794,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 794, 795, 795, 795, 795, 795, 795, 795,
+ 795, 794, 795, 795, 795, 795, 795, 794,
+ 794, 794, 794, 794, 794, 794, 794, 795,
+ 795, 795, 795, 795, 795, 794, 795, 795,
+ 795, 795, 795, 795, 795, 794, 795, 794,
+ 795, 795, 794, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 794, 795, 795, 795, 795, 795, 794, 795,
+ 795, 795, 795, 795, 795, 795, 794, 795,
+ 795, 795, 794, 795, 795, 795, 794, 795,
+ 794, 829, 830, 831, 832, 833, 834, 835,
+ 836, 837, 838, 839, 840, 841, 842, 843,
+ 844, 845, 846, 847, 848, 849, 850, 851,
+ 852, 853, 854, 855, 856, 857, 858, 859,
+ 860, 861, 862, 863, 864, 801, 865, 866,
+ 867, 868, 869, 870, 801, 846, 801, 794,
+ 795, 794, 795, 795, 794, 794, 795, 794,
+ 794, 794, 794, 795, 794, 794, 794, 794,
+ 794, 795, 794, 794, 794, 794, 794, 795,
+ 795, 795, 795, 795, 794, 794, 794, 795,
+ 794, 794, 794, 795, 795, 795, 794, 794,
+ 794, 795, 795, 794, 794, 794, 795, 795,
+ 795, 794, 794, 794, 795, 795, 795, 795,
+ 794, 795, 795, 795, 795, 794, 794, 794,
+ 794, 794, 795, 795, 795, 795, 794, 794,
+ 795, 795, 795, 794, 794, 795, 795, 795,
+ 795, 794, 795, 795, 794, 795, 795, 794,
+ 794, 794, 795, 795, 795, 794, 794, 794,
+ 794, 795, 795, 795, 795, 795, 794, 794,
+ 794, 794, 795, 794, 795, 795, 794, 795,
+ 795, 794, 795, 794, 795, 795, 795, 794,
+ 795, 795, 794, 794, 794, 795, 794, 794,
+ 794, 794, 794, 794, 794, 795, 795, 795,
+ 795, 794, 795, 795, 795, 795, 795, 795,
+ 795, 794, 871, 872, 873, 874, 875, 876,
+ 877, 878, 879, 801, 880, 881, 882, 883,
+ 884, 794, 795, 794, 794, 794, 794, 794,
+ 795, 795, 794, 795, 795, 795, 794, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 794, 795, 795, 795, 794, 794, 795,
+ 795, 795, 794, 794, 795, 794, 794, 795,
+ 795, 795, 795, 795, 794, 794, 794, 794,
+ 795, 795, 795, 795, 795, 795, 794, 795,
+ 795, 795, 795, 795, 794, 885, 840, 886,
+ 887, 888, 801, 889, 890, 846, 801, 794,
+ 795, 795, 795, 795, 794, 794, 794, 795,
+ 794, 794, 795, 795, 795, 794, 794, 794,
+ 795, 795, 794, 851, 794, 846, 801, 801,
+ 891, 794, 801, 794, 795, 846, 892, 893,
+ 846, 894, 895, 846, 896, 897, 898, 899,
+ 900, 901, 846, 902, 903, 904, 846, 905,
+ 906, 907, 865, 908, 909, 910, 865, 911,
+ 846, 801, 794, 794, 795, 795, 794, 794,
+ 794, 795, 795, 795, 795, 794, 795, 795,
+ 794, 794, 794, 794, 795, 795, 794, 794,
+ 795, 795, 794, 794, 794, 794, 794, 794,
+ 795, 795, 795, 794, 794, 794, 795, 794,
+ 794, 794, 795, 795, 794, 795, 795, 795,
+ 795, 794, 795, 795, 795, 795, 794, 795,
+ 795, 795, 795, 795, 795, 794, 794, 794,
+ 795, 795, 795, 795, 794, 912, 913, 794,
+ 801, 794, 795, 794, 794, 795, 846, 914,
+ 915, 916, 917, 896, 918, 919, 920, 921,
+ 922, 923, 924, 925, 926, 927, 928, 929,
+ 801, 794, 794, 795, 794, 795, 795, 795,
+ 795, 795, 795, 795, 794, 795, 795, 795,
+ 794, 795, 794, 794, 795, 794, 795, 794,
+ 794, 795, 795, 795, 795, 794, 795, 795,
+ 795, 794, 794, 795, 795, 795, 795, 794,
+ 795, 795, 794, 794, 795, 795, 795, 795,
+ 795, 794, 930, 931, 932, 933, 934, 935,
+ 936, 937, 938, 939, 940, 936, 942, 943,
+ 944, 945, 941, 794, 946, 947, 846, 948,
+ 949, 950, 951, 952, 953, 954, 955, 956,
+ 846, 801, 957, 958, 959, 960, 846, 961,
+ 962, 963, 964, 965, 966, 967, 968, 969,
+ 970, 971, 972, 973, 974, 975, 846, 877,
+ 801, 976, 794, 795, 795, 795, 795, 795,
+ 794, 794, 794, 795, 794, 795, 795, 794,
+ 795, 794, 795, 795, 794, 794, 794, 795,
+ 795, 795, 794, 794, 794, 795, 795, 795,
+ 794, 794, 794, 794, 795, 794, 794, 795,
+ 794, 794, 795, 795, 795, 794, 794, 795,
+ 794, 795, 795, 795, 794, 795, 795, 795,
+ 795, 795, 795, 794, 794, 794, 795, 795,
+ 794, 795, 795, 794, 795, 795, 794, 795,
+ 795, 794, 795, 795, 795, 795, 795, 795,
+ 795, 794, 795, 794, 795, 794, 795, 795,
+ 794, 795, 794, 795, 795, 794, 795, 794,
+ 795, 794, 977, 948, 978, 979, 980, 981,
+ 982, 983, 984, 985, 986, 829, 987, 846,
+ 988, 989, 990, 846, 991, 861, 992, 993,
+ 994, 995, 996, 997, 998, 999, 846, 794,
+ 794, 794, 795, 795, 795, 794, 795, 795,
+ 794, 795, 795, 794, 794, 794, 794, 794,
+ 795, 795, 795, 795, 794, 795, 795, 795,
+ 795, 795, 795, 794, 794, 794, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 794,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 794, 795, 795, 794, 794, 794, 794, 795,
+ 795, 795, 794, 794, 794, 795, 794, 794,
+ 794, 795, 795, 794, 795, 795, 795, 794,
+ 795, 794, 794, 794, 795, 795, 794, 795,
+ 795, 795, 794, 795, 795, 795, 794, 794,
+ 794, 794, 795, 846, 915, 1000, 1001, 801,
+ 846, 801, 794, 794, 795, 794, 795, 846,
+ 1000, 801, 794, 846, 1002, 801, 794, 794,
+ 795, 846, 1003, 1004, 1005, 906, 1006, 1007,
+ 846, 1008, 1009, 1010, 801, 794, 794, 795,
+ 795, 795, 794, 795, 795, 794, 795, 795,
+ 795, 795, 794, 794, 795, 794, 794, 795,
+ 795, 794, 795, 794, 846, 801, 794, 1011,
+ 846, 1012, 794, 801, 794, 795, 794, 795,
+ 1013, 846, 1014, 1015, 794, 795, 794, 794,
+ 794, 795, 795, 795, 795, 794, 1016, 1017,
+ 1018, 846, 1019, 1020, 1021, 1022, 1023, 1024,
+ 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032,
+ 801, 794, 795, 795, 795, 794, 794, 794,
+ 794, 795, 795, 794, 794, 795, 794, 794,
+ 794, 794, 794, 794, 794, 795, 794, 795,
+ 794, 794, 794, 794, 794, 794, 795, 795,
+ 795, 795, 795, 794, 794, 795, 794, 794,
+ 794, 795, 794, 794, 795, 794, 794, 795,
+ 794, 794, 795, 794, 794, 794, 795, 795,
+ 795, 794, 794, 794, 795, 795, 795, 795,
+ 794, 1033, 846, 1034, 846, 1035, 1036, 1037,
+ 1038, 801, 794, 795, 795, 795, 795, 795,
+ 794, 794, 794, 795, 794, 794, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 794, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 794, 795, 795, 795,
+ 795, 795, 794, 1039, 846, 801, 794, 795,
+ 1040, 846, 831, 801, 794, 795, 1041, 794,
+ 801, 794, 795, 846, 1042, 801, 794, 794,
+ 795, 1043, 794, 846, 1044, 801, 794, 794,
+ 795, 1046, 1045, 795, 795, 795, 795, 1046,
+ 1045, 795, 1046, 1045, 1046, 1046, 795, 1046,
+ 1045, 795, 1046, 795, 1046, 1045, 795, 1046,
+ 795, 1046, 795, 1045, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1045, 795, 795, 1046,
+ 1046, 795, 1046, 795, 1046, 1045, 1046, 1046,
+ 1046, 1046, 1046, 795, 1046, 795, 1046, 795,
+ 1046, 1045, 1046, 1046, 795, 1046, 795, 1046,
+ 1045, 1046, 1046, 1046, 1046, 1046, 795, 1046,
+ 795, 1046, 1045, 795, 795, 1046, 795, 1046,
+ 1045, 1046, 1046, 1046, 795, 1046, 795, 1046,
+ 795, 1046, 795, 1046, 1045, 1046, 795, 1046,
+ 795, 1046, 1045, 795, 1046, 1046, 1046, 1046,
+ 795, 1046, 795, 1046, 795, 1046, 795, 1046,
+ 795, 1046, 795, 1046, 1045, 795, 1046, 1045,
+ 1046, 1046, 1046, 795, 1046, 795, 1046, 1045,
+ 1046, 795, 1046, 795, 1046, 1045, 795, 1046,
+ 1046, 1046, 1046, 795, 1046, 795, 1046, 1045,
+ 795, 1046, 795, 1046, 795, 1046, 1045, 1046,
+ 1046, 795, 1046, 795, 1046, 1045, 795, 1046,
+ 795, 1046, 795, 1046, 795, 1045, 1046, 1046,
+ 1046, 795, 1046, 795, 1046, 1045, 795, 1046,
+ 1045, 1046, 1046, 795, 1046, 1045, 1046, 1046,
+ 1046, 795, 1046, 1046, 1046, 1046, 1046, 1046,
+ 795, 795, 1046, 795, 1046, 795, 1046, 795,
+ 1046, 1045, 1046, 795, 1046, 795, 1046, 1045,
+ 795, 1046, 1045, 1046, 795, 1046, 1045, 1046,
+ 795, 1046, 1045, 795, 795, 1046, 1045, 795,
+ 1046, 795, 1046, 795, 1046, 795, 1046, 795,
+ 1046, 795, 1045, 1046, 1046, 795, 1046, 1046,
+ 1046, 1046, 795, 795, 1046, 1046, 1046, 1046,
+ 1046, 795, 1046, 1046, 1046, 1046, 1046, 1045,
+ 795, 1046, 1046, 795, 1046, 795, 1045, 1046,
+ 1046, 795, 1046, 1045, 795, 795, 1046, 795,
+ 1045, 1046, 1046, 1045, 795, 1046, 795, 1045,
+ 1046, 1045, 795, 1046, 795, 1046, 795, 1045,
+ 1046, 1046, 1045, 795, 1046, 795, 1046, 795,
+ 1046, 1045, 1046, 795, 1046, 795, 1046, 1045,
+ 795, 1046, 1045, 795, 795, 1046, 1045, 1046,
+ 795, 1045, 1046, 1045, 795, 1046, 795, 1046,
+ 795, 1045, 1046, 1045, 795, 795, 1046, 1045,
+ 1046, 795, 1046, 795, 1046, 1045, 795, 1046,
+ 795, 1045, 1046, 1045, 795, 795, 1046, 795,
+ 1045, 1046, 1045, 795, 795, 1046, 1045, 1046,
+ 795, 1046, 1045, 1046, 795, 1046, 1045, 1046,
+ 795, 1046, 795, 1046, 795, 1045, 1046, 1045,
+ 795, 795, 1046, 1045, 1046, 795, 1046, 795,
+ 1046, 1045, 795, 1046, 1045, 1046, 1046, 795,
+ 1046, 795, 1046, 1045, 1045, 795, 1045, 795,
+ 1046, 1046, 795, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1045, 795, 1046, 1046, 1046, 795,
+ 1045, 1046, 1046, 1046, 795, 1046, 795, 1046,
+ 795, 1046, 795, 1046, 795, 1046, 1045, 795,
+ 795, 1046, 1045, 1046, 795, 1046, 1045, 795,
+ 795, 1046, 795, 795, 795, 1046, 795, 1046,
+ 795, 1046, 795, 1046, 795, 1045, 795, 1046,
+ 795, 1046, 795, 1045, 1046, 1045, 795, 1046,
+ 795, 1045, 1046, 795, 1046, 1046, 1046, 1045,
+ 795, 1046, 795, 795, 1046, 795, 1045, 1046,
+ 1046, 1045, 795, 1046, 1046, 1046, 1046, 795,
+ 1046, 795, 1045, 1046, 1046, 1046, 795, 1046,
+ 1045, 1046, 795, 1046, 795, 1046, 795, 1046,
+ 795, 1046, 1045, 1046, 1046, 795, 1046, 1045,
+ 795, 1046, 795, 1046, 795, 1045, 1046, 1046,
+ 1045, 795, 1046, 795, 1045, 1046, 1045, 795,
+ 1046, 1045, 795, 1046, 795, 1046, 1045, 1046,
+ 1046, 1046, 1045, 795, 795, 795, 1046, 1045,
+ 795, 1046, 795, 1045, 1046, 1045, 795, 1046,
+ 795, 1046, 795, 1045, 1046, 1046, 1046, 1045,
+ 795, 1046, 795, 1045, 1046, 1046, 1046, 1046,
+ 1045, 795, 1046, 795, 1046, 1045, 795, 795,
+ 1046, 795, 1046, 1045, 1046, 795, 1046, 795,
+ 1045, 1046, 1046, 1045, 795, 1046, 795, 1046,
+ 1045, 795, 1046, 1046, 1046, 795, 1046, 795,
+ 1045, 795, 1046, 1045, 1046, 795, 795, 1046,
+ 795, 1046, 795, 1045, 1046, 1046, 1046, 1046,
+ 1045, 795, 1046, 795, 1046, 795, 1046, 795,
+ 1046, 795, 1046, 1045, 1046, 1046, 1046, 795,
+ 1046, 795, 1046, 795, 1046, 795, 1045, 1046,
+ 1046, 795, 795, 1046, 1045, 1046, 795, 1046,
+ 1046, 1045, 795, 1046, 795, 1046, 1045, 795,
+ 795, 1046, 1046, 1046, 1046, 795, 1046, 795,
+ 1046, 795, 1045, 1046, 1046, 795, 1045, 1046,
+ 1045, 795, 1046, 795, 1045, 1046, 1045, 795,
+ 1046, 795, 1045, 1046, 795, 1046, 1046, 1045,
+ 795, 1046, 1046, 795, 1045, 1046, 1045, 795,
+ 1046, 795, 1046, 1045, 1046, 795, 1046, 795,
+ 1045, 1046, 1045, 795, 1046, 795, 1046, 795,
+ 1046, 795, 1046, 795, 1046, 1045, 1047, 1045,
+ 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,
+ 1056, 1057, 1058, 1050, 1059, 1060, 1061, 1062,
+ 1063, 1050, 1064, 1065, 1066, 1067, 1068, 1069,
+ 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077,
+ 1078, 1050, 1079, 1047, 1059, 1047, 1080, 1047,
+ 1045, 1046, 1046, 1046, 1046, 795, 1045, 1046,
+ 1046, 1045, 795, 1046, 1045, 795, 795, 1046,
+ 1045, 795, 1046, 795, 1045, 1046, 1045, 795,
+ 795, 1046, 795, 1045, 1046, 1046, 1045, 795,
+ 1046, 1046, 1046, 1045, 795, 1046, 795, 1046,
+ 1046, 1045, 795, 795, 1046, 795, 1045, 1046,
+ 1045, 795, 1046, 1045, 795, 795, 1046, 795,
+ 1046, 1045, 795, 1046, 795, 795, 1046, 795,
+ 1046, 795, 1045, 1046, 1046, 1045, 795, 1046,
+ 1046, 795, 1046, 1045, 795, 1046, 795, 1046,
+ 1045, 795, 1046, 795, 1045, 795, 1046, 1046,
+ 1046, 795, 1046, 1045, 1046, 795, 1046, 1045,
+ 795, 1046, 1045, 1046, 795, 1046, 1045, 795,
+ 1046, 1045, 795, 1046, 795, 1046, 1045, 795,
+ 1046, 1045, 795, 1046, 1045, 1081, 1082, 1083,
+ 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
+ 1092, 1052, 1093, 1094, 1095, 1096, 1097, 1094,
+ 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105,
+ 1106, 1047, 1045, 1046, 795, 1046, 1045, 1046,
+ 795, 1046, 1045, 1046, 795, 1046, 1045, 1046,
+ 795, 1046, 1045, 795, 1046, 795, 1046, 1045,
+ 1046, 795, 1046, 1045, 1046, 795, 795, 795,
+ 1046, 1045, 1046, 795, 1046, 1045, 1046, 1046,
+ 1046, 1046, 795, 1046, 795, 1045, 1046, 1045,
+ 795, 795, 1046, 795, 1046, 1045, 1046, 795,
+ 1046, 1045, 795, 1046, 1045, 1046, 1046, 795,
+ 1046, 1045, 795, 1046, 1045, 1046, 795, 1046,
+ 1045, 795, 1046, 1045, 795, 1046, 1045, 795,
+ 1046, 1045, 1046, 1045, 795, 795, 1046, 1045,
+ 1046, 795, 1046, 1045, 795, 1046, 795, 1045,
+ 1046, 1045, 795, 1050, 1107, 1047, 1050, 1108,
+ 1050, 1109, 1059, 1047, 1045, 1046, 1045, 795,
+ 1046, 1045, 795, 1050, 1108, 1059, 1047, 1045,
+ 1050, 1110, 1047, 1059, 1047, 1045, 1046, 1045,
+ 795, 1050, 1111, 1068, 1112, 1094, 1113, 1106,
+ 1050, 1114, 1115, 1116, 1047, 1059, 1047, 1045,
+ 1046, 1045, 795, 1046, 795, 1046, 1045, 795,
+ 1046, 795, 1046, 795, 1045, 1046, 1046, 1045,
+ 795, 1046, 795, 1046, 1045, 795, 1046, 1045,
+ 1050, 1059, 801, 1045, 1117, 1050, 1118, 1059,
+ 1047, 1045, 801, 1046, 1045, 795, 1046, 1045,
+ 795, 1119, 1050, 1120, 1121, 1047, 1045, 795,
+ 1046, 1045, 1046, 1046, 1045, 795, 795, 1046,
+ 795, 1046, 1045, 1050, 1122, 1123, 1124, 1125,
+ 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1047,
+ 1059, 1047, 1045, 1046, 795, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 795, 1046, 795, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1045, 795, 1046,
+ 1046, 795, 1046, 795, 1045, 1046, 795, 1046,
+ 1046, 1046, 795, 1046, 1046, 795, 1046, 1046,
+ 795, 1046, 1046, 795, 1046, 1046, 1045, 795,
+ 1050, 1133, 1050, 1109, 1134, 1135, 1136, 1047,
+ 1059, 1047, 1045, 1046, 1045, 795, 1046, 1046,
+ 1046, 795, 1046, 1046, 1046, 795, 1046, 795,
+ 1046, 1045, 795, 795, 795, 795, 1046, 1046,
+ 795, 795, 795, 795, 795, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 795, 1046, 795, 1046,
+ 795, 1045, 1046, 1046, 1046, 795, 1046, 795,
+ 1046, 1045, 1059, 801, 1137, 1050, 1059, 801,
+ 1046, 1045, 795, 1138, 1050, 1139, 1059, 801,
+ 1046, 1045, 795, 1046, 795, 1140, 1059, 1047,
+ 1045, 801, 1046, 1045, 795, 1050, 1141, 1047,
+ 1059, 1047, 1045, 1046, 1045, 795, 1142, 1143,
+ 1144, 1142, 1145, 1146, 1147, 1149, 1150, 1151,
+ 1152, 1153, 1154, 1155, 670, 670, 419, 1156,
+ 1157, 1158, 1159, 670, 1162, 1163, 1165, 1166,
+ 1167, 1161, 1168, 1169, 1170, 1171, 1172, 1173,
+ 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181,
+ 1182, 1183, 1184, 1185, 1186, 1187, 1189, 1190,
+ 1191, 1192, 1193, 1194, 670, 1148, 7, 1148,
+ 419, 1148, 419, 1161, 1164, 1188, 1195, 1160,
+ 1142, 1142, 1196, 1143, 1197, 1199, 1198, 4,
+ 1147, 1201, 1198, 1202, 1198, 2, 1147, 1198,
+ 6, 8, 8, 7, 1203, 1204, 1198, 1205,
+ 1206, 1198, 1207, 1208, 1198, 1209, 1198, 419,
+ 419, 1211, 1212, 489, 470, 1213, 470, 1214,
+ 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222,
+ 1223, 1224, 544, 1225, 520, 1226, 1227, 1228,
+ 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236,
+ 1237, 419, 419, 419, 425, 565, 1210, 1238,
+ 1198, 1239, 1198, 670, 1240, 419, 419, 419,
+ 670, 1240, 670, 670, 419, 1240, 419, 1240,
+ 419, 1240, 419, 670, 670, 670, 670, 670,
+ 1240, 419, 670, 670, 670, 419, 670, 419,
+ 1240, 419, 670, 670, 670, 670, 419, 1240,
+ 670, 419, 670, 419, 670, 419, 670, 670,
+ 419, 670, 1240, 419, 670, 419, 670, 419,
+ 670, 1240, 670, 419, 1240, 670, 419, 670,
+ 419, 1240, 670, 670, 670, 670, 670, 1240,
+ 419, 419, 670, 419, 670, 1240, 670, 419,
+ 1240, 670, 670, 1240, 419, 419, 670, 419,
+ 670, 419, 670, 1240, 1241, 1242, 1243, 1244,
+ 1245, 1246, 1247, 1248, 1249, 1250, 1251, 715,
+ 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259,
+ 1260, 1261, 1262, 1263, 1262, 1264, 1265, 1266,
+ 1267, 1268, 671, 1240, 1269, 1270, 1271, 1272,
+ 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280,
+ 1281, 1282, 1283, 1284, 1285, 1286, 1287, 725,
+ 1288, 1289, 1290, 692, 1291, 1292, 1293, 1294,
+ 1295, 1296, 671, 1297, 1298, 1299, 1300, 1301,
+ 1302, 1303, 1304, 674, 1305, 671, 674, 1306,
+ 1307, 1308, 1309, 683, 1240, 1310, 1311, 1312,
+ 1313, 703, 1314, 1315, 683, 1316, 1317, 1318,
+ 1319, 1320, 671, 1240, 1321, 1280, 1322, 1323,
+ 1324, 683, 1325, 1326, 674, 671, 683, 425,
+ 1240, 1290, 671, 674, 683, 425, 683, 425,
+ 1327, 683, 1240, 425, 674, 1328, 1329, 674,
+ 1330, 1331, 681, 1332, 1333, 1334, 1335, 1336,
+ 1286, 1337, 1338, 1339, 1340, 1341, 1342, 1343,
+ 1344, 1345, 1346, 1347, 1348, 1305, 1349, 674,
+ 683, 425, 1240, 1350, 1351, 683, 671, 1240,
+ 425, 671, 1240, 674, 1352, 731, 1353, 1354,
+ 1355, 1356, 1357, 1358, 1359, 1360, 671, 1361,
+ 1362, 1363, 1364, 1365, 1366, 671, 683, 1240,
+ 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375,
+ 1376, 1377, 1378, 1374, 1380, 1381, 1382, 1383,
+ 1367, 1379, 1367, 1240, 1367, 1240, 1384, 1384,
+ 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392,
+ 1389, 767, 1393, 1393, 1393, 1394, 1393, 1393,
+ 768, 769, 770, 1393, 767, 1384, 1384, 1395,
+ 1398, 1399, 1397, 1400, 1401, 1400, 1402, 1393,
+ 1404, 1403, 1398, 1405, 1397, 1407, 1406, 1396,
+ 1396, 1396, 768, 769, 770, 1396, 767, 767,
+ 1408, 773, 1408, 1409, 1408, 775, 1410, 1411,
+ 1412, 1413, 1414, 1415, 1416, 1413, 776, 775,
+ 1410, 1417, 1417, 777, 779, 1418, 1417, 776,
+ 1420, 1421, 1419, 1420, 1421, 1422, 1419, 775,
+ 1410, 1423, 1417, 775, 1410, 1417, 1425, 1424,
+ 1427, 1426, 776, 1428, 777, 1428, 779, 1428,
+ 785, 1429, 1430, 1431, 1432, 1433, 1434, 1435,
+ 1432, 786, 785, 1429, 1436, 1436, 787, 789,
+ 1437, 1436, 786, 1439, 1440, 1438, 1439, 1440,
+ 1441, 1438, 785, 1429, 1442, 1436, 785, 1429,
+ 1436, 1444, 1443, 1446, 1445, 786, 1447, 787,
+ 1447, 789, 1447, 795, 1450, 1451, 1453, 1454,
+ 1455, 1449, 1456, 1457, 1458, 1459, 1460, 1461,
+ 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469,
+ 1470, 1471, 1472, 1473, 1474, 1475, 1477, 1478,
+ 1479, 1480, 1481, 1482, 795, 795, 1448, 1449,
+ 1452, 1476, 1483, 1448, 1046, 795, 795, 1485,
+ 1486, 865, 846, 1487, 846, 1488, 1489, 1490,
+ 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498,
+ 920, 1499, 896, 1500, 1501, 1502, 1503, 1504,
+ 1505, 1506, 1507, 1508, 1509, 1510, 1511, 795,
+ 795, 795, 801, 941, 1484, 1046, 1512, 795,
+ 795, 795, 1046, 1512, 1046, 1046, 795, 1512,
+ 795, 1512, 795, 1512, 795, 1046, 1046, 1046,
+ 1046, 1046, 1512, 795, 1046, 1046, 1046, 795,
+ 1046, 795, 1512, 795, 1046, 1046, 1046, 1046,
+ 795, 1512, 1046, 795, 1046, 795, 1046, 795,
+ 1046, 1046, 795, 1046, 1512, 795, 1046, 795,
+ 1046, 795, 1046, 1512, 1046, 795, 1512, 1046,
+ 795, 1046, 795, 1512, 1046, 1046, 1046, 1046,
+ 1046, 1512, 795, 795, 1046, 795, 1046, 1512,
+ 1046, 795, 1512, 1046, 1046, 1512, 795, 795,
+ 1046, 795, 1046, 795, 1046, 1512, 1513, 1514,
+ 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522,
+ 1523, 1091, 1524, 1525, 1526, 1527, 1528, 1529,
+ 1530, 1531, 1532, 1533, 1534, 1535, 1534, 1536,
+ 1537, 1538, 1539, 1540, 1047, 1512, 1541, 1542,
+ 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550,
+ 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558,
+ 1559, 1101, 1560, 1561, 1562, 1068, 1563, 1564,
+ 1565, 1566, 1567, 1568, 1047, 1569, 1570, 1571,
+ 1572, 1573, 1574, 1575, 1576, 1050, 1577, 1047,
+ 1050, 1578, 1579, 1580, 1581, 1059, 1512, 1582,
+ 1583, 1584, 1585, 1079, 1586, 1587, 1059, 1588,
+ 1589, 1590, 1591, 1592, 1047, 1512, 1593, 1552,
+ 1594, 1595, 1596, 1059, 1597, 1598, 1050, 1047,
+ 1059, 801, 1512, 1562, 1047, 1050, 1059, 801,
+ 1059, 801, 1599, 1059, 1512, 801, 1050, 1600,
+ 1601, 1050, 1602, 1603, 1057, 1604, 1605, 1606,
+ 1607, 1608, 1558, 1609, 1610, 1611, 1612, 1613,
+ 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1577,
+ 1621, 1050, 1059, 801, 1512, 1622, 1623, 1059,
+ 1047, 1512, 801, 1047, 1512, 1050, 1624, 1107,
+ 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632,
+ 1047, 1633, 1634, 1635, 1636, 1637, 1638, 1047,
+ 1059, 1512, 1640, 1641, 1642, 1643, 1644, 1645,
+ 1646, 1647, 1648, 1649, 1650, 1646, 1652, 1653,
+ 1654, 1655, 1639, 1651, 1639, 1512, 1639, 1512,
+}
+
+var _hcltok_trans_targs []int16 = []int16{
+ 1459, 1459, 2, 3, 1459, 1459, 4, 1467,
+ 5, 6, 8, 9, 286, 12, 13, 14,
+ 15, 16, 287, 288, 19, 289, 21, 22,
+ 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, 328, 348, 353, 127, 128, 129,
+ 356, 151, 371, 375, 1459, 10, 11, 17,
+ 18, 20, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 64, 105, 120, 131,
+ 154, 170, 283, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 121, 122, 123, 124, 125, 126, 130, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 152, 153, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 171, 203, 227, 230, 231,
+ 233, 242, 243, 246, 250, 268, 275, 277,
+ 279, 281, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 204, 205, 206, 207, 208, 209, 210,
+ 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226,
+ 228, 229, 232, 234, 235, 236, 237, 238,
+ 239, 240, 241, 244, 245, 247, 248, 249,
+ 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 269, 270, 271, 272, 273, 274, 276,
+ 278, 280, 282, 284, 285, 300, 301, 302,
+ 303, 304, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, 317, 318,
+ 319, 320, 321, 322, 323, 324, 325, 326,
+ 327, 329, 330, 331, 332, 333, 334, 335,
+ 336, 337, 338, 339, 340, 341, 342, 343,
+ 344, 345, 346, 347, 349, 350, 351, 352,
+ 354, 355, 357, 358, 359, 360, 361, 362,
+ 363, 364, 365, 366, 367, 368, 369, 370,
+ 372, 373, 374, 376, 382, 404, 409, 411,
+ 413, 377, 378, 379, 380, 381, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392,
+ 393, 394, 395, 396, 397, 398, 399, 400,
+ 401, 402, 403, 405, 406, 407, 408, 410,
+ 412, 414, 1459, 1472, 1459, 437, 438, 439,
+ 440, 417, 441, 442, 443, 444, 445, 446,
+ 447, 448, 449, 450, 451, 452, 453, 454,
+ 455, 456, 457, 458, 459, 460, 461, 462,
+ 463, 464, 465, 466, 467, 469, 470, 471,
+ 472, 473, 474, 475, 476, 477, 478, 479,
+ 480, 481, 482, 483, 484, 485, 419, 486,
+ 487, 488, 489, 490, 491, 492, 493, 494,
+ 495, 496, 497, 498, 499, 500, 501, 502,
+ 503, 418, 504, 505, 506, 507, 508, 510,
+ 511, 512, 513, 514, 515, 516, 517, 518,
+ 519, 520, 521, 522, 523, 525, 526, 527,
+ 528, 529, 530, 534, 536, 537, 538, 539,
+ 434, 540, 541, 542, 543, 544, 545, 546,
+ 547, 548, 549, 550, 551, 552, 553, 554,
+ 556, 557, 559, 560, 561, 562, 563, 564,
+ 432, 565, 566, 567, 568, 569, 570, 571,
+ 572, 573, 575, 607, 631, 634, 635, 637,
+ 646, 647, 650, 654, 672, 532, 679, 681,
+ 683, 685, 576, 577, 578, 579, 580, 581,
+ 582, 583, 584, 585, 586, 587, 588, 589,
+ 590, 591, 592, 593, 594, 595, 596, 597,
+ 598, 599, 600, 601, 602, 603, 604, 605,
+ 606, 608, 609, 610, 611, 612, 613, 614,
+ 615, 616, 617, 618, 619, 620, 621, 622,
+ 623, 624, 625, 626, 627, 628, 629, 630,
+ 632, 633, 636, 638, 639, 640, 641, 642,
+ 643, 644, 645, 648, 649, 651, 652, 653,
+ 655, 656, 657, 658, 659, 660, 661, 662,
+ 663, 664, 665, 666, 667, 668, 669, 670,
+ 671, 673, 674, 675, 676, 677, 678, 680,
+ 682, 684, 686, 688, 689, 1459, 1459, 690,
+ 827, 828, 759, 829, 830, 831, 832, 833,
+ 834, 788, 835, 724, 836, 837, 838, 839,
+ 840, 841, 842, 843, 744, 844, 845, 846,
+ 847, 848, 849, 850, 851, 852, 853, 769,
+ 854, 856, 857, 858, 859, 860, 861, 862,
+ 863, 864, 865, 702, 866, 867, 868, 869,
+ 870, 871, 872, 873, 874, 740, 875, 876,
+ 877, 878, 879, 810, 881, 882, 885, 887,
+ 888, 889, 890, 891, 892, 895, 896, 898,
+ 899, 900, 902, 903, 904, 905, 906, 907,
+ 908, 909, 910, 911, 912, 914, 915, 916,
+ 917, 920, 922, 923, 925, 927, 1510, 1511,
+ 929, 930, 931, 1510, 1510, 932, 1524, 1524,
+ 1525, 935, 1524, 936, 1526, 1527, 1530, 1531,
+ 1535, 1535, 1536, 941, 1535, 942, 1537, 1538,
+ 1541, 1542, 1546, 1547, 1546, 968, 969, 970,
+ 971, 948, 972, 973, 974, 975, 976, 977,
+ 978, 979, 980, 981, 982, 983, 984, 985,
+ 986, 987, 988, 989, 990, 991, 992, 993,
+ 994, 995, 996, 997, 998, 1000, 1001, 1002,
+ 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010,
+ 1011, 1012, 1013, 1014, 1015, 1016, 950, 1017,
+ 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025,
+ 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033,
+ 1034, 949, 1035, 1036, 1037, 1038, 1039, 1041,
+ 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049,
+ 1050, 1051, 1052, 1053, 1054, 1056, 1057, 1058,
+ 1059, 1060, 1061, 1065, 1067, 1068, 1069, 1070,
+ 965, 1071, 1072, 1073, 1074, 1075, 1076, 1077,
+ 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085,
+ 1087, 1088, 1090, 1091, 1092, 1093, 1094, 1095,
+ 963, 1096, 1097, 1098, 1099, 1100, 1101, 1102,
+ 1103, 1104, 1106, 1138, 1162, 1165, 1166, 1168,
+ 1177, 1178, 1181, 1185, 1203, 1063, 1210, 1212,
+ 1214, 1216, 1107, 1108, 1109, 1110, 1111, 1112,
+ 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120,
+ 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128,
+ 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136,
+ 1137, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
+ 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153,
+ 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
+ 1163, 1164, 1167, 1169, 1170, 1171, 1172, 1173,
+ 1174, 1175, 1176, 1179, 1180, 1182, 1183, 1184,
+ 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193,
+ 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201,
+ 1202, 1204, 1205, 1206, 1207, 1208, 1209, 1211,
+ 1213, 1215, 1217, 1219, 1220, 1546, 1546, 1221,
+ 1358, 1359, 1290, 1360, 1361, 1362, 1363, 1364,
+ 1365, 1319, 1366, 1255, 1367, 1368, 1369, 1370,
+ 1371, 1372, 1373, 1374, 1275, 1375, 1376, 1377,
+ 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1300,
+ 1385, 1387, 1388, 1389, 1390, 1391, 1392, 1393,
+ 1394, 1395, 1396, 1233, 1397, 1398, 1399, 1400,
+ 1401, 1402, 1403, 1404, 1405, 1271, 1406, 1407,
+ 1408, 1409, 1410, 1341, 1412, 1413, 1416, 1418,
+ 1419, 1420, 1421, 1422, 1423, 1426, 1427, 1429,
+ 1430, 1431, 1433, 1434, 1435, 1436, 1437, 1438,
+ 1439, 1440, 1441, 1442, 1443, 1445, 1446, 1447,
+ 1448, 1451, 1453, 1454, 1456, 1458, 1460, 1459,
+ 1461, 1462, 1459, 1463, 1459, 1464, 1465, 1466,
+ 1468, 1469, 1470, 1471, 1459, 1473, 1459, 1474,
+ 1459, 1475, 1476, 1477, 1478, 1479, 1480, 1481,
+ 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489,
+ 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497,
+ 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505,
+ 1506, 1507, 1508, 1509, 1459, 1459, 1459, 1459,
+ 1459, 1459, 1, 1459, 1459, 7, 1459, 1459,
+ 1459, 1459, 1459, 415, 416, 420, 421, 422,
+ 423, 424, 425, 426, 427, 428, 429, 430,
+ 431, 433, 435, 436, 468, 509, 524, 531,
+ 533, 535, 555, 558, 574, 687, 1459, 1459,
+ 1459, 691, 692, 693, 694, 695, 696, 697,
+ 698, 699, 700, 701, 703, 704, 705, 706,
+ 707, 708, 709, 710, 711, 712, 713, 714,
+ 715, 716, 717, 718, 719, 720, 721, 722,
+ 723, 725, 726, 727, 728, 729, 730, 731,
+ 732, 733, 734, 735, 736, 737, 738, 739,
+ 741, 742, 743, 745, 746, 747, 748, 749,
+ 750, 751, 752, 753, 754, 755, 756, 757,
+ 758, 760, 761, 762, 763, 764, 765, 766,
+ 767, 768, 770, 771, 772, 773, 774, 775,
+ 776, 777, 778, 779, 780, 781, 782, 783,
+ 784, 785, 786, 787, 789, 790, 791, 792,
+ 793, 794, 795, 796, 797, 798, 799, 800,
+ 801, 802, 803, 804, 805, 806, 807, 808,
+ 809, 811, 812, 813, 814, 815, 816, 817,
+ 818, 819, 820, 821, 822, 823, 824, 825,
+ 826, 855, 880, 883, 884, 886, 893, 894,
+ 897, 901, 913, 918, 919, 921, 924, 926,
+ 1512, 1510, 1513, 1518, 1520, 1510, 1521, 1522,
+ 1523, 1510, 928, 1510, 1510, 1514, 1515, 1517,
+ 1510, 1516, 1510, 1510, 1510, 1519, 1510, 1510,
+ 1510, 933, 934, 938, 939, 1524, 1532, 1533,
+ 1534, 1524, 937, 1524, 1524, 934, 1528, 1529,
+ 1524, 1524, 1524, 1524, 1524, 940, 944, 945,
+ 1535, 1543, 1544, 1545, 1535, 943, 1535, 1535,
+ 940, 1539, 1540, 1535, 1535, 1535, 1535, 1535,
+ 1546, 1548, 1549, 1550, 1551, 1552, 1553, 1554,
+ 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562,
+ 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570,
+ 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578,
+ 1579, 1580, 1581, 1582, 1546, 946, 947, 951,
+ 952, 953, 954, 955, 956, 957, 958, 959,
+ 960, 961, 962, 964, 966, 967, 999, 1040,
+ 1055, 1062, 1064, 1066, 1086, 1089, 1105, 1218,
+ 1546, 1222, 1223, 1224, 1225, 1226, 1227, 1228,
+ 1229, 1230, 1231, 1232, 1234, 1235, 1236, 1237,
+ 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245,
+ 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253,
+ 1254, 1256, 1257, 1258, 1259, 1260, 1261, 1262,
+ 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270,
+ 1272, 1273, 1274, 1276, 1277, 1278, 1279, 1280,
+ 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288,
+ 1289, 1291, 1292, 1293, 1294, 1295, 1296, 1297,
+ 1298, 1299, 1301, 1302, 1303, 1304, 1305, 1306,
+ 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314,
+ 1315, 1316, 1317, 1318, 1320, 1321, 1322, 1323,
+ 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331,
+ 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339,
+ 1340, 1342, 1343, 1344, 1345, 1346, 1347, 1348,
+ 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356,
+ 1357, 1386, 1411, 1414, 1415, 1417, 1424, 1425,
+ 1428, 1432, 1444, 1449, 1450, 1452, 1455, 1457,
+}
+
+var _hcltok_trans_actions []byte = []byte{
+ 147, 109, 0, 0, 91, 143, 0, 7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 123, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 145, 195, 151, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 149, 127, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 31, 171,
+ 0, 0, 0, 35, 33, 0, 55, 41,
+ 177, 0, 53, 0, 177, 177, 0, 0,
+ 75, 61, 183, 0, 73, 0, 183, 183,
+ 0, 0, 85, 189, 89, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 87, 79, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 93,
+ 0, 0, 121, 0, 113, 0, 7, 7,
+ 0, 7, 0, 0, 115, 0, 117, 0,
+ 125, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7,
+ 7, 7, 198, 198, 198, 198, 198, 198,
+ 7, 7, 198, 7, 129, 141, 137, 97,
+ 135, 103, 0, 131, 107, 0, 101, 95,
+ 111, 99, 133, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 105, 119,
+ 139, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 13, 0, 0, 174, 17, 0, 7,
+ 7, 23, 0, 25, 27, 0, 0, 0,
+ 153, 0, 15, 19, 9, 0, 21, 11,
+ 29, 0, 0, 0, 0, 43, 0, 180,
+ 180, 49, 0, 159, 156, 1, 177, 177,
+ 45, 37, 47, 39, 51, 0, 0, 0,
+ 63, 0, 186, 186, 69, 0, 165, 162,
+ 1, 183, 183, 65, 57, 67, 59, 71,
+ 77, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7,
+ 7, 7, 192, 192, 192, 192, 192, 192,
+ 7, 7, 192, 7, 81, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 83, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+}
+
+var _hcltok_to_state_actions []byte = []byte{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 168, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 168,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+}
+
+var _hcltok_from_state_actions []byte = []byte{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+}
+
+var _hcltok_eof_trans []int16 = []int16{
+ 0, 1, 1, 1, 6, 6, 6, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 419,
+ 419, 421, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 419, 419,
+ 419, 419, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670,
+ 767, 772, 772, 772, 773, 773, 775, 775,
+ 775, 779, 0, 0, 785, 785, 785, 789,
+ 0, 0, 795, 795, 797, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795,
+ 795, 795, 795, 795, 795, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
+ 1046, 1046, 1046, 0, 1197, 1198, 1199, 1201,
+ 1199, 1199, 1199, 1204, 1199, 1199, 1199, 1199,
+ 1211, 1199, 1199, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 0, 1394,
+ 1396, 1397, 1401, 1401, 1394, 1404, 1397, 1407,
+ 1397, 1409, 1409, 1409, 0, 1418, 1420, 1420,
+ 1418, 1418, 1425, 1427, 1429, 1429, 1429, 0,
+ 1437, 1439, 1439, 1437, 1437, 1444, 1446, 1448,
+ 1448, 1448, 0, 1485, 1513, 1513, 1513, 1513,
+ 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513,
+ 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513,
+ 1513, 1513, 1513, 1513, 1513, 1513, 1513, 1513,
+ 1513, 1513, 1513, 1513, 1513, 1513, 1513,
+}
+
+const hcltok_start int = 1459
+const hcltok_first_final int = 1459
+const hcltok_error int = 0
+
+const hcltok_en_stringTemplate int = 1510
+const hcltok_en_heredocTemplate int = 1524
+const hcltok_en_bareTemplate int = 1535
+const hcltok_en_identOnly int = 1546
+const hcltok_en_main int = 1459
+
+//line scan_tokens.rl:18
+
+func scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {
+ stripData := stripUTF8BOM(data)
+ start.Byte += len(data) - len(stripData)
+ data = stripData
+
+ f := &tokenAccum{
+ Filename: filename,
+ Bytes: data,
+ Pos: start,
+ StartByte: start.Byte,
+ }
+
+//line scan_tokens.rl:317
+
+ // Ragel state
+ p := 0 // "Pointer" into data
+ pe := len(data) // End-of-data "pointer"
+ ts := 0
+ te := 0
+ act := 0
+ eof := pe
+ var stack []int
+ var top int
+
+ var cs int // current state
+ switch mode {
+ case scanNormal:
+ cs = hcltok_en_main
+ case scanTemplate:
+ cs = hcltok_en_bareTemplate
+ case scanIdentOnly:
+ cs = hcltok_en_identOnly
+ default:
+ panic("invalid scanMode")
+ }
+
+ braces := 0
+ var retBraces []int // stack of brace levels that cause us to use fret
+ var heredocs []heredocInProgress // stack of heredocs we're currently processing
+
+//line scan_tokens.rl:352
+
+ // Make Go compiler happy
+ _ = ts
+ _ = te
+ _ = act
+ _ = eof
+
+ token := func(ty TokenType) {
+ f.emitToken(ty, ts, te)
+ }
+ selfToken := func() {
+ b := data[ts:te]
+ if len(b) != 1 {
+ // should never happen
+ panic("selfToken only works for single-character tokens")
+ }
+ f.emitToken(TokenType(b[0]), ts, te)
+ }
+
+//line scan_tokens.go:4292
+ {
+ top = 0
+ ts = 0
+ te = 0
+ act = 0
+ }
+
+//line scan_tokens.go:4300
+ {
+ var _klen int
+ var _trans int
+ var _acts int
+ var _nacts uint
+ var _keys int
+ if p == pe {
+ goto _test_eof
+ }
+ if cs == 0 {
+ goto _out
+ }
+ _resume:
+ _acts = int(_hcltok_from_state_actions[cs])
+ _nacts = uint(_hcltok_actions[_acts])
+ _acts++
+ for ; _nacts > 0; _nacts-- {
+ _acts++
+ switch _hcltok_actions[_acts-1] {
+ case 3:
+//line NONE:1
+ ts = p
+
+//line scan_tokens.go:4323
+ }
+ }
+
+ _keys = int(_hcltok_key_offsets[cs])
+ _trans = int(_hcltok_index_offsets[cs])
+
+ _klen = int(_hcltok_single_lengths[cs])
+ if _klen > 0 {
+ _lower := int(_keys)
+ var _mid int
+ _upper := int(_keys + _klen - 1)
+ for {
+ if _upper < _lower {
+ break
+ }
+
+ _mid = _lower + ((_upper - _lower) >> 1)
+ switch {
+ case data[p] < _hcltok_trans_keys[_mid]:
+ _upper = _mid - 1
+ case data[p] > _hcltok_trans_keys[_mid]:
+ _lower = _mid + 1
+ default:
+ _trans += int(_mid - int(_keys))
+ goto _match
+ }
+ }
+ _keys += _klen
+ _trans += _klen
+ }
+
+ _klen = int(_hcltok_range_lengths[cs])
+ if _klen > 0 {
+ _lower := int(_keys)
+ var _mid int
+ _upper := int(_keys + (_klen << 1) - 2)
+ for {
+ if _upper < _lower {
+ break
+ }
+
+ _mid = _lower + (((_upper - _lower) >> 1) & ^1)
+ switch {
+ case data[p] < _hcltok_trans_keys[_mid]:
+ _upper = _mid - 2
+ case data[p] > _hcltok_trans_keys[_mid+1]:
+ _lower = _mid + 2
+ default:
+ _trans += int((_mid - int(_keys)) >> 1)
+ goto _match
+ }
+ }
+ _trans += _klen
+ }
+
+ _match:
+ _trans = int(_hcltok_indicies[_trans])
+ _eof_trans:
+ cs = int(_hcltok_trans_targs[_trans])
+
+ if _hcltok_trans_actions[_trans] == 0 {
+ goto _again
+ }
+
+ _acts = int(_hcltok_trans_actions[_trans])
+ _nacts = uint(_hcltok_actions[_acts])
+ _acts++
+ for ; _nacts > 0; _nacts-- {
+ _acts++
+ switch _hcltok_actions[_acts-1] {
+ case 0:
+//line scan_tokens.rl:235
+ p--
+
+ case 4:
+//line NONE:1
+ te = p + 1
+
+ case 5:
+//line scan_tokens.rl:259
+ act = 4
+ case 6:
+//line scan_tokens.rl:261
+ act = 6
+ case 7:
+//line scan_tokens.rl:171
+ te = p + 1
+ {
+ token(TokenTemplateInterp)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 8:
+//line scan_tokens.rl:181
+ te = p + 1
+ {
+ token(TokenTemplateControl)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 9:
+//line scan_tokens.rl:95
+ te = p + 1
+ {
+ token(TokenCQuote)
+ top--
+ cs = stack[top]
+ {
+ stack = stack[:len(stack)-1]
+ }
+ goto _again
+
+ }
+ case 10:
+//line scan_tokens.rl:259
+ te = p + 1
+ {
+ token(TokenQuotedLit)
+ }
+ case 11:
+//line scan_tokens.rl:262
+ te = p + 1
+ {
+ token(TokenBadUTF8)
+ }
+ case 12:
+//line scan_tokens.rl:171
+ te = p
+ p--
+ {
+ token(TokenTemplateInterp)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 13:
+//line scan_tokens.rl:181
+ te = p
+ p--
+ {
+ token(TokenTemplateControl)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 14:
+//line scan_tokens.rl:259
+ te = p
+ p--
+ {
+ token(TokenQuotedLit)
+ }
+ case 15:
+//line scan_tokens.rl:260
+ te = p
+ p--
+ {
+ token(TokenQuotedNewline)
+ }
+ case 16:
+//line scan_tokens.rl:261
+ te = p
+ p--
+ {
+ token(TokenInvalid)
+ }
+ case 17:
+//line scan_tokens.rl:262
+ te = p
+ p--
+ {
+ token(TokenBadUTF8)
+ }
+ case 18:
+//line scan_tokens.rl:259
+ p = (te) - 1
+ {
+ token(TokenQuotedLit)
+ }
+ case 19:
+//line scan_tokens.rl:262
+ p = (te) - 1
+ {
+ token(TokenBadUTF8)
+ }
+ case 20:
+//line NONE:1
+ switch act {
+ case 4:
+ {
+ p = (te) - 1
+ token(TokenQuotedLit)
+ }
+ case 6:
+ {
+ p = (te) - 1
+ token(TokenInvalid)
+ }
+ }
+
+ case 21:
+//line scan_tokens.rl:159
+ act = 11
+ case 22:
+//line scan_tokens.rl:270
+ act = 12
+ case 23:
+//line scan_tokens.rl:171
+ te = p + 1
+ {
+ token(TokenTemplateInterp)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 24:
+//line scan_tokens.rl:181
+ te = p + 1
+ {
+ token(TokenTemplateControl)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 25:
+//line scan_tokens.rl:122
+ te = p + 1
+ {
+ // This action is called specificially when a heredoc literal
+ // ends with a newline character.
+
+ // This might actually be our end marker.
+ topdoc := &heredocs[len(heredocs)-1]
+ if topdoc.StartOfLine {
+ maybeMarker := bytes.TrimSpace(data[ts:te])
+ if bytes.Equal(maybeMarker, topdoc.Marker) {
+ // We actually emit two tokens here: the end-of-heredoc
+ // marker first, and then separately the newline that
+ // follows it. This then avoids issues with the closing
+ // marker consuming a newline that would normally be used
+ // to mark the end of an attribute definition.
+ // We might have either a \n sequence or an \r\n sequence
+ // here, so we must handle both.
+ nls := te - 1
+ nle := te
+ te--
+ if data[te-1] == '\r' {
+ // back up one more byte
+ nls--
+ te--
+ }
+ token(TokenCHeredoc)
+ ts = nls
+ te = nle
+ token(TokenNewline)
+ heredocs = heredocs[:len(heredocs)-1]
+ top--
+ cs = stack[top]
+ {
+ stack = stack[:len(stack)-1]
+ }
+ goto _again
+
+ }
+ }
+
+ topdoc.StartOfLine = true
+ token(TokenStringLit)
+ }
+ case 26:
+//line scan_tokens.rl:270
+ te = p + 1
+ {
+ token(TokenBadUTF8)
+ }
+ case 27:
+//line scan_tokens.rl:171
+ te = p
+ p--
+ {
+ token(TokenTemplateInterp)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 28:
+//line scan_tokens.rl:181
+ te = p
+ p--
+ {
+ token(TokenTemplateControl)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 29:
+//line scan_tokens.rl:159
+ te = p
+ p--
+ {
+ // This action is called when a heredoc literal _doesn't_ end
+ // with a newline character, e.g. because we're about to enter
+ // an interpolation sequence.
+ heredocs[len(heredocs)-1].StartOfLine = false
+ token(TokenStringLit)
+ }
+ case 30:
+//line scan_tokens.rl:270
+ te = p
+ p--
+ {
+ token(TokenBadUTF8)
+ }
+ case 31:
+//line scan_tokens.rl:159
+ p = (te) - 1
+ {
+ // This action is called when a heredoc literal _doesn't_ end
+ // with a newline character, e.g. because we're about to enter
+ // an interpolation sequence.
+ heredocs[len(heredocs)-1].StartOfLine = false
+ token(TokenStringLit)
+ }
+ case 32:
+//line NONE:1
+ switch act {
+ case 0:
+ {
+ cs = 0
+ goto _again
+ }
+ case 11:
+ {
+ p = (te) - 1
+
+ // This action is called when a heredoc literal _doesn't_ end
+ // with a newline character, e.g. because we're about to enter
+ // an interpolation sequence.
+ heredocs[len(heredocs)-1].StartOfLine = false
+ token(TokenStringLit)
+ }
+ case 12:
+ {
+ p = (te) - 1
+ token(TokenBadUTF8)
+ }
+ }
+
+ case 33:
+//line scan_tokens.rl:167
+ act = 15
+ case 34:
+//line scan_tokens.rl:277
+ act = 16
+ case 35:
+//line scan_tokens.rl:171
+ te = p + 1
+ {
+ token(TokenTemplateInterp)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 36:
+//line scan_tokens.rl:181
+ te = p + 1
+ {
+ token(TokenTemplateControl)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 37:
+//line scan_tokens.rl:167
+ te = p + 1
+ {
+ token(TokenStringLit)
+ }
+ case 38:
+//line scan_tokens.rl:277
+ te = p + 1
+ {
+ token(TokenBadUTF8)
+ }
+ case 39:
+//line scan_tokens.rl:171
+ te = p
+ p--
+ {
+ token(TokenTemplateInterp)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 40:
+//line scan_tokens.rl:181
+ te = p
+ p--
+ {
+ token(TokenTemplateControl)
+ braces++
+ retBraces = append(retBraces, braces)
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false
+ }
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1459
+ goto _again
+ }
+ }
+ case 41:
+//line scan_tokens.rl:167
+ te = p
+ p--
+ {
+ token(TokenStringLit)
+ }
+ case 42:
+//line scan_tokens.rl:277
+ te = p
+ p--
+ {
+ token(TokenBadUTF8)
+ }
+ case 43:
+//line scan_tokens.rl:167
+ p = (te) - 1
+ {
+ token(TokenStringLit)
+ }
+ case 44:
+//line NONE:1
+ switch act {
+ case 0:
+ {
+ cs = 0
+ goto _again
+ }
+ case 15:
+ {
+ p = (te) - 1
+
+ token(TokenStringLit)
+ }
+ case 16:
+ {
+ p = (te) - 1
+ token(TokenBadUTF8)
+ }
+ }
+
+ case 45:
+//line scan_tokens.rl:281
+ act = 17
+ case 46:
+//line scan_tokens.rl:282
+ act = 18
+ case 47:
+//line scan_tokens.rl:282
+ te = p + 1
+ {
+ token(TokenBadUTF8)
+ }
+ case 48:
+//line scan_tokens.rl:283
+ te = p + 1
+ {
+ token(TokenInvalid)
+ }
+ case 49:
+//line scan_tokens.rl:281
+ te = p
+ p--
+ {
+ token(TokenIdent)
+ }
+ case 50:
+//line scan_tokens.rl:282
+ te = p
+ p--
+ {
+ token(TokenBadUTF8)
+ }
+ case 51:
+//line scan_tokens.rl:281
+ p = (te) - 1
+ {
+ token(TokenIdent)
+ }
+ case 52:
+//line scan_tokens.rl:282
+ p = (te) - 1
+ {
+ token(TokenBadUTF8)
+ }
+ case 53:
+//line NONE:1
+ switch act {
+ case 17:
+ {
+ p = (te) - 1
+ token(TokenIdent)
+ }
+ case 18:
+ {
+ p = (te) - 1
+ token(TokenBadUTF8)
+ }
+ }
+
+ case 54:
+//line scan_tokens.rl:289
+ act = 22
+ case 55:
+//line scan_tokens.rl:313
+ act = 40
+ case 56:
+//line scan_tokens.rl:291
+ te = p + 1
+ {
+ token(TokenComment)
+ }
+ case 57:
+//line scan_tokens.rl:292
+ te = p + 1
+ {
+ token(TokenNewline)
+ }
+ case 58:
+//line scan_tokens.rl:294
+ te = p + 1
+ {
+ token(TokenEqualOp)
+ }
+ case 59:
+//line scan_tokens.rl:295
+ te = p + 1
+ {
+ token(TokenNotEqual)
+ }
+ case 60:
+//line scan_tokens.rl:296
+ te = p + 1
+ {
+ token(TokenGreaterThanEq)
+ }
+ case 61:
+//line scan_tokens.rl:297
+ te = p + 1
+ {
+ token(TokenLessThanEq)
+ }
+ case 62:
+//line scan_tokens.rl:298
+ te = p + 1
+ {
+ token(TokenAnd)
+ }
+ case 63:
+//line scan_tokens.rl:299
+ te = p + 1
+ {
+ token(TokenOr)
+ }
+ case 64:
+//line scan_tokens.rl:300
+ te = p + 1
+ {
+ token(TokenDoubleColon)
+ }
+ case 65:
+//line scan_tokens.rl:301
+ te = p + 1
+ {
+ token(TokenEllipsis)
+ }
+ case 66:
+//line scan_tokens.rl:302
+ te = p + 1
+ {
+ token(TokenFatArrow)
+ }
+ case 67:
+//line scan_tokens.rl:303
+ te = p + 1
+ {
+ selfToken()
+ }
+ case 68:
+//line scan_tokens.rl:191
+ te = p + 1
+ {
+ token(TokenOBrace)
+ braces++
+ }
+ case 69:
+//line scan_tokens.rl:196
+ te = p + 1
+ {
+ if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {
+ token(TokenTemplateSeqEnd)
+ braces--
+ retBraces = retBraces[0 : len(retBraces)-1]
+ top--
+ cs = stack[top]
+ {
+ stack = stack[:len(stack)-1]
+ }
+ goto _again
+
+ } else {
+ token(TokenCBrace)
+ braces--
+ }
+ }
+ case 70:
+//line scan_tokens.rl:208
+ te = p + 1
+ {
+ // Only consume from the retBraces stack and return if we are at
+ // a suitable brace nesting level, otherwise things will get
+ // confused. (Not entering this branch indicates a syntax error,
+ // which we will catch in the parser.)
+ if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {
+ token(TokenTemplateSeqEnd)
+ braces--
+ retBraces = retBraces[0 : len(retBraces)-1]
+ top--
+ cs = stack[top]
+ {
+ stack = stack[:len(stack)-1]
+ }
+ goto _again
+
+ } else {
+ // We intentionally generate a TokenTemplateSeqEnd here,
+ // even though the user apparently wanted a brace, because
+ // we want to allow the parser to catch the incorrect use
+ // of a ~} to balance a generic opening brace, rather than
+ // a template sequence.
+ token(TokenTemplateSeqEnd)
+ braces--
+ }
+ }
+ case 71:
+//line scan_tokens.rl:90
+ te = p + 1
+ {
+ token(TokenOQuote)
+ {
+ stack = append(stack, 0)
+ stack[top] = cs
+ top++
+ cs = 1510
+ goto _again
+ }
+ }
+ case 72:
+//line scan_tokens.rl:100
+ te = p + 1
+ {
+ token(TokenOHeredoc)
+ // the token is currently the whole heredoc introducer, like
+ // < 0; _nacts-- {
+ _acts++
+ switch _hcltok_actions[_acts-1] {
+ case 1:
+//line NONE:1
+ ts = 0
+
+ case 2:
+//line NONE:1
+ act = 0
+
+//line scan_tokens.go:5080
+ }
+ }
+
+ if cs == 0 {
+ goto _out
+ }
+ p++
+ if p != pe {
+ goto _resume
+ }
+ _test_eof:
+ {
+ }
+ if p == eof {
+ if _hcltok_eof_trans[cs] > 0 {
+ _trans = int(_hcltok_eof_trans[cs] - 1)
+ goto _eof_trans
+ }
+ }
+
+ _out:
+ {
+ }
+ }
+
+//line scan_tokens.rl:375
+
+ // If we fall out here without being in a final state then we've
+ // encountered something that the scanner can't match, which we'll
+ // deal with as an invalid.
+ if cs < hcltok_first_final {
+ if mode == scanTemplate && len(stack) == 0 {
+ // If we're scanning a bare template then any straggling
+ // top-level stuff is actually literal string, rather than
+ // invalid. This handles the case where the template ends
+ // with a single "$" or "%", which trips us up because we
+ // want to see another character to decide if it's a sequence
+ // or an escape.
+ f.emitToken(TokenStringLit, ts, len(data))
+ } else {
+ f.emitToken(TokenInvalid, ts, len(data))
+ }
+ }
+
+ // We always emit a synthetic EOF token at the end, since it gives the
+ // parser position information for an "unexpected EOF" diagnostic.
+ f.emitToken(TokenEOF, len(data), len(data))
+
+ return f.Tokens
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.rl b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.rl
new file mode 100644
index 00000000000..66bb47146c9
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/scan_tokens.rl
@@ -0,0 +1,399 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// This file is generated from scan_tokens.rl. DO NOT EDIT.
+%%{
+ # (except when you are actually in scan_tokens.rl here, so edit away!)
+
+ machine hcltok;
+ write data;
+}%%
+
+func scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {
+ stripData := stripUTF8BOM(data)
+ start.Byte += len(data) - len(stripData)
+ data = stripData
+
+ f := &tokenAccum{
+ Filename: filename,
+ Bytes: data,
+ Pos: start,
+ StartByte: start.Byte,
+ }
+
+ %%{
+ include UnicodeDerived "unicode_derived.rl";
+
+ UTF8Cont = 0x80 .. 0xBF;
+ AnyUTF8 = (
+ 0x00..0x7F |
+ 0xC0..0xDF . UTF8Cont |
+ 0xE0..0xEF . UTF8Cont . UTF8Cont |
+ 0xF0..0xF7 . UTF8Cont . UTF8Cont . UTF8Cont
+ );
+ BrokenUTF8 = any - AnyUTF8;
+
+ NumberLitContinue = (digit|'.'|('e'|'E') ('+'|'-')? digit);
+ NumberLit = digit ("" | (NumberLitContinue - '.') | (NumberLitContinue* (NumberLitContinue - '.')));
+ Ident = (ID_Start | '_') (ID_Continue | '-')*;
+
+ # Symbols that just represent themselves are handled as a single rule.
+ SelfToken = "[" | "]" | "(" | ")" | "." | "," | "*" | "/" | "%" | "+" | "-" | "=" | "<" | ">" | "!" | "?" | ":" | "\n" | "&" | "|" | "~" | "^" | ";" | "`" | "'";
+
+ EqualOp = "==";
+ NotEqual = "!=";
+ GreaterThanEqual = ">=";
+ LessThanEqual = "<=";
+ LogicalAnd = "&&";
+ LogicalOr = "||";
+
+ DoubleColon = "::";
+ Ellipsis = "...";
+ FatArrow = "=>";
+
+ Newline = '\r' ? '\n';
+ EndOfLine = Newline;
+
+ BeginStringTmpl = '"';
+ BeginHeredocTmpl = '<<' ('-')? Ident Newline;
+
+ Comment = (
+ # The :>> operator in these is a "finish-guarded concatenation",
+ # which terminates the sequence on its left when it completes
+ # the sequence on its right.
+ # In the single-line comment cases this is allowing us to make
+ # the trailing EndOfLine optional while still having the overall
+ # pattern terminate. In the multi-line case it ensures that
+ # the first comment in the file ends at the first */, rather than
+ # gobbling up all of the "any*" until the _final_ */ in the file.
+ ("#" (any - EndOfLine)* :>> EndOfLine?) |
+ ("//" (any - EndOfLine)* :>> EndOfLine?) |
+ ("/*" any* :>> "*/")
+ );
+
+ # Note: hclwrite assumes that only ASCII spaces appear between tokens,
+ # and uses this assumption to recreate the spaces between tokens by
+ # looking at byte offset differences. This means it will produce
+ # incorrect results in the presence of tabs, but that's acceptable
+ # because the canonical style (which hclwrite itself can impose
+ # automatically is to never use tabs).
+ Spaces = (' ' | 0x09)+;
+
+ action beginStringTemplate {
+ token(TokenOQuote);
+ fcall stringTemplate;
+ }
+
+ action endStringTemplate {
+ token(TokenCQuote);
+ fret;
+ }
+
+ action beginHeredocTemplate {
+ token(TokenOHeredoc);
+ // the token is currently the whole heredoc introducer, like
+ // < 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false;
+ }
+ fcall main;
+ }
+
+ action beginTemplateControl {
+ token(TokenTemplateControl);
+ braces++;
+ retBraces = append(retBraces, braces);
+ if len(heredocs) > 0 {
+ heredocs[len(heredocs)-1].StartOfLine = false;
+ }
+ fcall main;
+ }
+
+ action openBrace {
+ token(TokenOBrace);
+ braces++;
+ }
+
+ action closeBrace {
+ if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {
+ token(TokenTemplateSeqEnd);
+ braces--;
+ retBraces = retBraces[0:len(retBraces)-1]
+ fret;
+ } else {
+ token(TokenCBrace);
+ braces--;
+ }
+ }
+
+ action closeTemplateSeqEatWhitespace {
+ // Only consume from the retBraces stack and return if we are at
+ // a suitable brace nesting level, otherwise things will get
+ // confused. (Not entering this branch indicates a syntax error,
+ // which we will catch in the parser.)
+ if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {
+ token(TokenTemplateSeqEnd);
+ braces--;
+ retBraces = retBraces[0:len(retBraces)-1]
+ fret;
+ } else {
+ // We intentionally generate a TokenTemplateSeqEnd here,
+ // even though the user apparently wanted a brace, because
+ // we want to allow the parser to catch the incorrect use
+ // of a ~} to balance a generic opening brace, rather than
+ // a template sequence.
+ token(TokenTemplateSeqEnd);
+ braces--;
+ }
+ }
+
+ TemplateInterp = "${" ("~")?;
+ TemplateControl = "%{" ("~")?;
+ EndStringTmpl = '"';
+ NewlineChars = ("\r"|"\n");
+ NewlineCharsSeq = NewlineChars+;
+ StringLiteralChars = (AnyUTF8 - NewlineChars);
+ TemplateIgnoredNonBrace = (^'{' %{ fhold; });
+ TemplateNotInterp = '$' (TemplateIgnoredNonBrace | TemplateInterp);
+ TemplateNotControl = '%' (TemplateIgnoredNonBrace | TemplateControl);
+ QuotedStringLiteralWithEsc = ('\\' StringLiteralChars) | (StringLiteralChars - ("$" | '%' | '"' | "\\"));
+ TemplateStringLiteral = (
+ (TemplateNotInterp) |
+ (TemplateNotControl) |
+ (QuotedStringLiteralWithEsc)+
+ );
+ HeredocStringLiteral = (
+ (TemplateNotInterp) |
+ (TemplateNotControl) |
+ (StringLiteralChars - ("$" | '%'))*
+ );
+ BareStringLiteral = (
+ (TemplateNotInterp) |
+ (TemplateNotControl) |
+ (StringLiteralChars - ("$" | '%'))*
+ ) Newline?;
+
+ stringTemplate := |*
+ TemplateInterp => beginTemplateInterp;
+ TemplateControl => beginTemplateControl;
+ EndStringTmpl => endStringTemplate;
+ TemplateStringLiteral => { token(TokenQuotedLit); };
+ NewlineCharsSeq => { token(TokenQuotedNewline); };
+ AnyUTF8 => { token(TokenInvalid); };
+ BrokenUTF8 => { token(TokenBadUTF8); };
+ *|;
+
+ heredocTemplate := |*
+ TemplateInterp => beginTemplateInterp;
+ TemplateControl => beginTemplateControl;
+ HeredocStringLiteral EndOfLine => heredocLiteralEOL;
+ HeredocStringLiteral => heredocLiteralMidline;
+ BrokenUTF8 => { token(TokenBadUTF8); };
+ *|;
+
+ bareTemplate := |*
+ TemplateInterp => beginTemplateInterp;
+ TemplateControl => beginTemplateControl;
+ BareStringLiteral => bareTemplateLiteral;
+ BrokenUTF8 => { token(TokenBadUTF8); };
+ *|;
+
+ identOnly := |*
+ Ident => { token(TokenIdent) };
+ BrokenUTF8 => { token(TokenBadUTF8) };
+ AnyUTF8 => { token(TokenInvalid) };
+ *|;
+
+ main := |*
+ Spaces => {};
+ NumberLit => { token(TokenNumberLit) };
+ Ident => { token(TokenIdent) };
+
+ Comment => { token(TokenComment) };
+ Newline => { token(TokenNewline) };
+
+ EqualOp => { token(TokenEqualOp); };
+ NotEqual => { token(TokenNotEqual); };
+ GreaterThanEqual => { token(TokenGreaterThanEq); };
+ LessThanEqual => { token(TokenLessThanEq); };
+ LogicalAnd => { token(TokenAnd); };
+ LogicalOr => { token(TokenOr); };
+ DoubleColon => { token(TokenDoubleColon); };
+ Ellipsis => { token(TokenEllipsis); };
+ FatArrow => { token(TokenFatArrow); };
+ SelfToken => { selfToken() };
+
+ "{" => openBrace;
+ "}" => closeBrace;
+
+ "~}" => closeTemplateSeqEatWhitespace;
+
+ BeginStringTmpl => beginStringTemplate;
+ BeginHeredocTmpl => beginHeredocTemplate;
+
+ BrokenUTF8 => { token(TokenBadUTF8) };
+ AnyUTF8 => { token(TokenInvalid) };
+ *|;
+
+ }%%
+
+ // Ragel state
+ p := 0 // "Pointer" into data
+ pe := len(data) // End-of-data "pointer"
+ ts := 0
+ te := 0
+ act := 0
+ eof := pe
+ var stack []int
+ var top int
+
+ var cs int // current state
+ switch mode {
+ case scanNormal:
+ cs = hcltok_en_main
+ case scanTemplate:
+ cs = hcltok_en_bareTemplate
+ case scanIdentOnly:
+ cs = hcltok_en_identOnly
+ default:
+ panic("invalid scanMode")
+ }
+
+ braces := 0
+ var retBraces []int // stack of brace levels that cause us to use fret
+ var heredocs []heredocInProgress // stack of heredocs we're currently processing
+
+ %%{
+ prepush {
+ stack = append(stack, 0);
+ }
+ postpop {
+ stack = stack[:len(stack)-1];
+ }
+ }%%
+
+ // Make Go compiler happy
+ _ = ts
+ _ = te
+ _ = act
+ _ = eof
+
+ token := func (ty TokenType) {
+ f.emitToken(ty, ts, te)
+ }
+ selfToken := func () {
+ b := data[ts:te]
+ if len(b) != 1 {
+ // should never happen
+ panic("selfToken only works for single-character tokens")
+ }
+ f.emitToken(TokenType(b[0]), ts, te)
+ }
+
+ %%{
+ write init nocs;
+ write exec;
+ }%%
+
+ // If we fall out here without being in a final state then we've
+ // encountered something that the scanner can't match, which we'll
+ // deal with as an invalid.
+ if cs < hcltok_first_final {
+ if mode == scanTemplate && len(stack) == 0 {
+ // If we're scanning a bare template then any straggling
+ // top-level stuff is actually literal string, rather than
+ // invalid. This handles the case where the template ends
+ // with a single "$" or "%", which trips us up because we
+ // want to see another character to decide if it's a sequence
+ // or an escape.
+ f.emitToken(TokenStringLit, ts, len(data))
+ } else {
+ f.emitToken(TokenInvalid, ts, len(data))
+ }
+ }
+
+ // We always emit a synthetic EOF token at the end, since it gives the
+ // parser position information for an "unexpected EOF" diagnostic.
+ f.emitToken(TokenEOF, len(data), len(data))
+
+ return f.Tokens
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/spec.md b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/spec.md
new file mode 100644
index 00000000000..88925410ab7
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/spec.md
@@ -0,0 +1,943 @@
+# HCL Native Syntax Specification
+
+This is the specification of the syntax and semantics of the native syntax
+for HCL. HCL is a system for defining configuration languages for applications.
+The HCL information model is designed to support multiple concrete syntaxes
+for configuration, but this native syntax is considered the primary format
+and is optimized for human authoring and maintenance, as opposed to machine
+generation of configuration.
+
+The language consists of three integrated sub-languages:
+
+- The _structural_ language defines the overall hierarchical configuration
+ structure, and is a serialization of HCL bodies, blocks and attributes.
+
+- The _expression_ language is used to express attribute values, either as
+ literals or as derivations of other values.
+
+- The _template_ language is used to compose values together into strings,
+ as one of several types of expression in the expression language.
+
+In normal use these three sub-languages are used together within configuration
+files to describe an overall configuration, with the structural language
+being used at the top level. The expression and template languages can also
+be used in isolation, to implement features such as REPLs, debuggers, and
+integration into more limited HCL syntaxes such as the JSON profile.
+
+## Syntax Notation
+
+Within this specification a semi-formal notation is used to illustrate the
+details of syntax. This notation is intended for human consumption rather
+than machine consumption, with the following conventions:
+
+- A naked name starting with an uppercase letter is a global production,
+ common to all of the syntax specifications in this document.
+- A naked name starting with a lowercase letter is a local production,
+ meaningful only within the specification where it is defined.
+- Double and single quotes (`"` and `'`) are used to mark literal character
+ sequences, which may be either punctuation markers or keywords.
+- The default operator for combining items, which has no punctuation,
+ is concatenation.
+- The symbol `|` indicates that any one of its left and right operands may
+ be present.
+- The `*` symbol indicates zero or more repetitions of the item to its left.
+- The `?` symbol indicates zero or one of the item to its left.
+- Parentheses (`(` and `)`) are used to group items together to apply
+ the `|`, `*` and `?` operators to them collectively.
+
+The grammar notation does not fully describe the language. The prose may
+augment or conflict with the illustrated grammar. In case of conflict, prose
+has priority.
+
+## Source Code Representation
+
+Source code is unicode text expressed in the UTF-8 encoding. The language
+itself does not perform unicode normalization, so syntax features such as
+identifiers are sequences of unicode code points and so e.g. a precombined
+accented character is distinct from a letter associated with a combining
+accent. (String literals have some special handling with regard to Unicode
+normalization which will be covered later in the relevant section.)
+
+UTF-8 encoded Unicode byte order marks are not permitted. Invalid or
+non-normalized UTF-8 encoding is always a parse error.
+
+## Lexical Elements
+
+### Comments and Whitespace
+
+Comments and Whitespace are recognized as lexical elements but are ignored
+except as described below.
+
+Whitespace is defined as a sequence of zero or more space characters
+(U+0020). Newline sequences (either U+000A or U+000D followed by U+000A)
+are _not_ considered whitespace but are ignored as such in certain contexts.
+Horizontal tab characters (U+0009) are also treated as whitespace, but are
+counted only as one "column" for the purpose of reporting source positions.
+
+Comments serve as program documentation and come in two forms:
+
+- _Line comments_ start with either the `//` or `#` sequences and end with
+ the next newline sequence. A line comment is considered equivalent to a
+ newline sequence.
+
+- _Inline comments_ start with the `/*` sequence and end with the `*/`
+ sequence, and may have any characters within except the ending sequence.
+ An inline comment is considered equivalent to a whitespace sequence.
+
+Comments and whitespace cannot begin within other comments, or within
+template literals except inside an interpolation sequence or template directive.
+
+### Identifiers
+
+Identifiers name entities such as blocks, attributes and expression variables.
+Identifiers are interpreted as per [UAX #31][uax31] Section 2. Specifically,
+their syntax is defined in terms of the `ID_Start` and `ID_Continue`
+character properties as follows:
+
+```ebnf
+Identifier = ID_Start (ID_Continue | '-')*;
+```
+
+The Unicode specification provides the normative requirements for identifier
+parsing. Non-normatively, the spirit of this specification is that `ID_Start`
+consists of Unicode letter and certain unambiguous punctuation tokens, while
+`ID_Continue` augments that set with Unicode digits, combining marks, etc.
+
+The dash character `-` is additionally allowed in identifiers, even though
+that is not part of the unicode `ID_Continue` definition. This is to allow
+attribute names and block type names to contain dashes, although underscores
+as word separators are considered the idiomatic usage.
+
+[uax31]: http://unicode.org/reports/tr31/ "Unicode Identifier and Pattern Syntax"
+
+### Keywords
+
+There are no globally-reserved words, but in some contexts certain identifiers
+are reserved to function as keywords. These are discussed further in the
+relevant documentation sections that follow. In such situations, the
+identifier's role as a keyword supersedes any other valid interpretation that
+may be possible. Outside of these specific situations, the keywords have no
+special meaning and are interpreted as regular identifiers.
+
+### Operators and Delimiters
+
+The following character sequences represent operators, delimiters, and other
+special tokens:
+
+```
++ && == < : { [ ( ${
+- || != > ? } ] ) %{
+* ! <= = .
+/ >= => ,
+% ...
+```
+
+### Numeric Literals
+
+A numeric literal is a decimal representation of a
+real number. It has an integer part, a fractional part,
+and an exponent part.
+
+```ebnf
+NumericLit = decimal+ ("." decimal+)? (expmark decimal+)?;
+decimal = '0' .. '9';
+expmark = ('e' | 'E') ("+" | "-")?;
+```
+
+## Structural Elements
+
+The structural language consists of syntax representing the following
+constructs:
+
+- _Attributes_, which assign a value to a specified name.
+- _Blocks_, which create a child body annotated by a type and optional labels.
+- _Body Content_, which consists of a collection of attributes and blocks.
+
+These constructs correspond to the similarly-named concepts in the
+language-agnostic HCL information model.
+
+```ebnf
+ConfigFile = Body;
+Body = (Attribute | Block | OneLineBlock)*;
+Attribute = Identifier "=" Expression Newline;
+Block = Identifier (StringLit|Identifier)* "{" Newline Body "}" Newline;
+OneLineBlock = Identifier (StringLit|Identifier)* "{" (Identifier "=" Expression)? "}" Newline;
+```
+
+### Configuration Files
+
+A _configuration file_ is a sequence of characters whose top-level is
+interpreted as a Body.
+
+### Bodies
+
+A _body_ is a collection of associated attributes and blocks. The meaning of
+this association is defined by the calling application.
+
+### Attribute Definitions
+
+An _attribute definition_ assigns a value to a particular attribute name within
+a body. Each distinct attribute name may be defined no more than once within a
+single body.
+
+The attribute value is given as an expression, which is retained literally
+for later evaluation by the calling application.
+
+### Blocks
+
+A _block_ creates a child body that is annotated with a block _type_ and
+zero or more block _labels_. Blocks create a structural hierarchy which can be
+interpreted by the calling application.
+
+Block labels can either be quoted literal strings or naked identifiers.
+
+## Expressions
+
+The expression sub-language is used within attribute definitions to specify
+values.
+
+```ebnf
+Expression = (
+ ExprTerm |
+ Operation |
+ Conditional
+);
+```
+
+### Types
+
+The value types used within the expression language are those defined by the
+syntax-agnostic HCL information model. An expression may return any valid
+type, but only a subset of the available types have first-class syntax.
+A calling application may make other types available via _variables_ and
+_functions_.
+
+### Expression Terms
+
+Expression _terms_ are the operands for unary and binary expressions, as well
+as acting as expressions in their own right.
+
+```ebnf
+ExprTerm = (
+ LiteralValue |
+ CollectionValue |
+ TemplateExpr |
+ VariableExpr |
+ FunctionCall |
+ ForExpr |
+ ExprTerm Index |
+ ExprTerm GetAttr |
+ ExprTerm Splat |
+ "(" Expression ")"
+);
+```
+
+The productions for these different term types are given in their corresponding
+sections.
+
+Between the `(` and `)` characters denoting a sub-expression, newline
+characters are ignored as whitespace.
+
+### Literal Values
+
+A _literal value_ immediately represents a particular value of a primitive
+type.
+
+```ebnf
+LiteralValue = (
+ NumericLit |
+ "true" |
+ "false" |
+ "null"
+);
+```
+
+- Numeric literals represent values of type _number_.
+- The `true` and `false` keywords represent values of type _bool_.
+- The `null` keyword represents a null value of the dynamic pseudo-type.
+
+String literals are not directly available in the expression sub-language, but
+are available via the template sub-language, which can in turn be incorporated
+via _template expressions_.
+
+### Collection Values
+
+A _collection value_ combines zero or more other expressions to produce a
+collection value.
+
+```ebnf
+CollectionValue = tuple | object;
+tuple = "[" (
+ (Expression (("," | Newline) Expression)* ","?)?
+) "]";
+object = "{" (
+ (objectelem (( "," | Newline) objectelem)* ","?)?
+) "}";
+objectelem = (Identifier | Expression) ("=" | ":") Expression;
+```
+
+Only tuple and object values can be directly constructed via native syntax.
+Tuple and object values can in turn be converted to list, set and map values
+with other operations, which behaves as defined by the syntax-agnostic HCL
+information model.
+
+When specifying an object element, an identifier is interpreted as a literal
+attribute name as opposed to a variable reference. To populate an item key
+from a variable, use parentheses to disambiguate:
+
+- `{foo = "baz"}` is interpreted as an attribute literally named `foo`.
+- `{(foo) = "baz"}` is interpreted as an attribute whose name is taken
+ from the variable named `foo`.
+
+Between the open and closing delimiters of these sequences, newline sequences
+are ignored as whitespace.
+
+There is a syntax ambiguity between _for expressions_ and collection values
+whose first element starts with an identifier named `for`. The _for expression_
+interpretation has priority, so to write a key literally named `for`
+or an expression derived from a variable named `for` you must use parentheses
+or quotes to disambiguate:
+
+- `[for, foo, baz]` is a syntax error.
+- `[(for), foo, baz]` is a tuple whose first element is the value of variable
+ `for`.
+- `{for = 1, baz = 2}` is a syntax error.
+- `{"for" = 1, baz = 2}` is an object with an attribute literally named `for`.
+- `{baz = 2, for = 1}` is equivalent to the previous example, and resolves the
+ ambiguity by reordering.
+- `{(for) = 1, baz = 2}` is an object with a key with the same value as the
+ variable `for`.
+
+### Template Expressions
+
+A _template expression_ embeds a program written in the template sub-language
+as an expression. Template expressions come in two forms:
+
+- A _quoted_ template expression is delimited by quote characters (`"`) and
+ defines a template as a single-line expression with escape characters.
+- A _heredoc_ template expression is introduced by a `<<` sequence and
+ defines a template via a multi-line sequence terminated by a user-chosen
+ delimiter.
+
+In both cases the template interpolation and directive syntax is available for
+use within the delimiters, and any text outside of these special sequences is
+interpreted as a literal string.
+
+In _quoted_ template expressions any literal string sequences within the
+template behave in a special way: literal newline sequences are not permitted
+and instead _escape sequences_ can be included, starting with the
+backslash `\`:
+
+```
+ \n Unicode newline control character
+ \r Unicode carriage return control character
+ \t Unicode tab control character
+ \" Literal quote mark, used to prevent interpretation as end of string
+ \\ Literal backslash, used to prevent interpretation as escape sequence
+ \uNNNN Unicode character from Basic Multilingual Plane (NNNN is four hexadecimal digits)
+ \UNNNNNNNN Unicode character from supplementary planes (NNNNNNNN is eight hexadecimal digits)
+```
+
+The _heredoc_ template expression type is introduced by either `<<` or `<<-`,
+followed by an identifier. The template expression ends when the given
+identifier subsequently appears again on a line of its own.
+
+If a heredoc template is introduced with the `<<-` symbol, any literal string
+at the start of each line is analyzed to find the minimum number of leading
+spaces, and then that number of prefix spaces is removed from all line-leading
+literal strings. The final closing marker may also have an arbitrary number
+of spaces preceding it on its line.
+
+```ebnf
+TemplateExpr = quotedTemplate | heredocTemplate;
+quotedTemplate = (as defined in prose above);
+heredocTemplate = (
+ ("<<" | "<<-") Identifier Newline
+ (content as defined in prose above)
+ Identifier Newline
+);
+```
+
+A quoted template expression containing only a single literal string serves
+as a syntax for defining literal string _expressions_. In certain contexts
+the template syntax is restricted in this manner:
+
+```ebnf
+StringLit = '"' (quoted literals as defined in prose above) '"';
+```
+
+The `StringLit` production permits the escape sequences discussed for quoted
+template expressions as above, but does _not_ permit template interpolation
+or directive sequences.
+
+### Variables and Variable Expressions
+
+A _variable_ is a value that has been assigned a symbolic name. Variables are
+made available for use in expressions by the calling application, by populating
+the _global scope_ used for expression evaluation.
+
+Variables can also be created by expressions themselves, which always creates
+a _child scope_ that incorporates the variables from its parent scope but
+(re-)defines zero or more names with new values.
+
+The value of a variable is accessed using a _variable expression_, which is
+a standalone `Identifier` whose name corresponds to a defined variable:
+
+```ebnf
+VariableExpr = Identifier;
+```
+
+Variables in a particular scope are immutable, but child scopes may _hide_
+a variable from an ancestor scope by defining a new variable of the same name.
+When looking up variables, the most locally-defined variable of the given name
+is used, and ancestor-scoped variables of the same name cannot be accessed.
+
+No direct syntax is provided for declaring or assigning variables, but other
+expression constructs implicitly create child scopes and define variables as
+part of their evaluation.
+
+### Functions and Function Calls
+
+A _function_ is an operation that has been assigned a symbolic name. Functions
+are made available for use in expressions by the calling application, by
+populating the _function table_ used for expression evaluation.
+
+The namespace of functions is distinct from the namespace of variables. A
+function and a variable may share the same name with no implication that they
+are in any way related.
+
+A function can be executed via a _function call_ expression:
+
+```ebnf
+FunctionCall = Identifier "(" arguments ")";
+Arguments = (
+ () ||
+ (Expression ("," Expression)* ("," | "...")?)
+);
+```
+
+The definition of functions and the semantics of calling them are defined by
+the language-agnostic HCL information model. The given arguments are mapped
+onto the function's _parameters_ and the result of a function call expression
+is the return value of the named function when given those arguments.
+
+If the final argument expression is followed by the ellipsis symbol (`...`),
+the final argument expression must evaluate to either a list or tuple value.
+The elements of the value are each mapped to a single parameter of the
+named function, beginning at the first parameter remaining after all other
+argument expressions have been mapped.
+
+Within the parentheses that delimit the function arguments, newline sequences
+are ignored as whitespace.
+
+### For Expressions
+
+A _for expression_ is a construct for constructing a collection by projecting
+the items from another collection.
+
+```ebnf
+ForExpr = forTupleExpr | forObjectExpr;
+forTupleExpr = "[" forIntro Expression forCond? "]";
+forObjectExpr = "{" forIntro Expression "=>" Expression "..."? forCond? "}";
+forIntro = "for" Identifier ("," Identifier)? "in" Expression ":";
+forCond = "if" Expression;
+```
+
+The punctuation used to delimit a for expression decide whether it will produce
+a tuple value (`[` and `]`) or an object value (`{` and `}`).
+
+The "introduction" is equivalent in both cases: the keyword `for` followed by
+either one or two identifiers separated by a comma which define the temporary
+variable names used for iteration, followed by the keyword `in` and then
+an expression that must evaluate to a value that can be iterated. The
+introduction is then terminated by the colon (`:`) symbol.
+
+If only one identifier is provided, it is the name of a variable that will
+be temporarily assigned the value of each element during iteration. If both
+are provided, the first is the key and the second is the value.
+
+Tuple, object, list, map, and set types are iterable. The type of collection
+used defines how the key and value variables are populated:
+
+- For tuple and list types, the _key_ is the zero-based index into the
+ sequence for each element, and the _value_ is the element value. The
+ elements are visited in index order.
+- For object and map types, the _key_ is the string attribute name or element
+ key, and the _value_ is the attribute or element value. The elements are
+ visited in the order defined by a lexicographic sort of the attribute names
+ or keys.
+- For set types, the _key_ and _value_ are both the element value. The elements
+ are visited in an undefined but consistent order.
+
+The expression after the colon and (in the case of object `for`) the expression
+after the `=>` are both evaluated once for each element of the source
+collection, in a local scope that defines the key and value variable names
+specified.
+
+The results of evaluating these expressions for each input element are used
+to populate an element in the new collection. In the case of tuple `for`, the
+single expression becomes an element, appending values to the tuple in visit
+order. In the case of object `for`, the pair of expressions is used as an
+attribute name and value respectively, creating an element in the resulting
+object.
+
+In the case of object `for`, it is an error if two input elements produce
+the same result from the attribute name expression, since duplicate
+attributes are not possible. If the ellipsis symbol (`...`) appears
+immediately after the value expression, this activates the grouping mode in
+which each value in the resulting object is a _tuple_ of all of the values
+that were produced against each distinct key.
+
+- `[for v in ["a", "b"]: v]` returns `["a", "b"]`.
+- `[for i, v in ["a", "b"]: i]` returns `[0, 1]`.
+- `{for i, v in ["a", "b"]: v => i}` returns `{a = 0, b = 1}`.
+- `{for i, v in ["a", "a", "b"]: v => i}` produces an error, because attribute
+ `a` is defined twice.
+- `{for i, v in ["a", "a", "b"]: v => i...}` returns `{a = [0, 1], b = [2]}`.
+
+If the `if` keyword is used after the element expression(s), it applies an
+additional predicate that can be used to conditionally filter elements from
+the source collection from consideration. The expression following `if` is
+evaluated once for each source element, in the same scope used for the
+element expression(s). It must evaluate to a boolean value; if `true`, the
+element will be evaluated as normal, while if `false` the element will be
+skipped.
+
+- `[for i, v in ["a", "b", "c"]: v if i < 2]` returns `["a", "b"]`.
+
+If the collection value, element expression(s) or condition expression return
+unknown values that are otherwise type-valid, the result is a value of the
+dynamic pseudo-type.
+
+### Index Operator
+
+The _index_ operator returns the value of a single element of a collection
+value. It is a postfix operator and can be applied to any value that has
+a tuple, object, map, or list type.
+
+```ebnf
+Index = "[" Expression "]";
+```
+
+The expression delimited by the brackets is the _key_ by which an element
+will be looked up.
+
+If the index operator is applied to a value of tuple or list type, the
+key expression must be an non-negative integer number representing the
+zero-based element index to access. If applied to a value of object or map
+type, the key expression must be a string representing the attribute name
+or element key. If the given key value is not of the appropriate type, a
+conversion is attempted using the conversion rules from the HCL
+syntax-agnostic information model.
+
+An error is produced if the given key expression does not correspond to
+an element in the collection, either because it is of an unconvertable type,
+because it is outside the range of elements for a tuple or list, or because
+the given attribute or key does not exist.
+
+If either the collection or the key are an unknown value of an
+otherwise-suitable type, the return value is an unknown value whose type
+matches what type would be returned given known values, or a value of the
+dynamic pseudo-type if type information alone cannot determine a suitable
+return type.
+
+Within the brackets that delimit the index key, newline sequences are ignored
+as whitespace.
+
+The HCL native syntax also includes a _legacy_ index operator that exists
+only for compatibility with the precursor language HIL:
+
+```ebnf
+LegacyIndex = '.' digit+
+```
+
+This legacy index operator must be supported by parser for compatibility but
+should not be used in new configurations. This allows an attribute-access-like
+syntax for indexing, must still be interpreted as an index operation rather
+than attribute access.
+
+The legacy syntax does not support chaining of index operations, like
+`foo.0.0.bar`, because the interpretation of `0.0` as a number literal token
+takes priority and thus renders the resulting sequence invalid.
+
+### Attribute Access Operator
+
+The _attribute access_ operator returns the value of a single attribute in
+an object value. It is a postfix operator and can be applied to any value
+that has an object type.
+
+```ebnf
+GetAttr = "." Identifier;
+```
+
+The given identifier is interpreted as the name of the attribute to access.
+An error is produced if the object to which the operator is applied does not
+have an attribute with the given name.
+
+If the object is an unknown value of a type that has the attribute named, the
+result is an unknown value of the attribute's type.
+
+### Splat Operators
+
+The _splat operators_ allow convenient access to attributes or elements of
+elements in a tuple, list, or set value.
+
+There are two kinds of "splat" operator:
+
+- The _attribute-only_ splat operator supports only attribute lookups into
+ the elements from a list, but supports an arbitrary number of them.
+
+- The _full_ splat operator additionally supports indexing into the elements
+ from a list, and allows any combination of attribute access and index
+ operations.
+
+```ebnf
+Splat = attrSplat | fullSplat;
+attrSplat = "." "*" GetAttr*;
+fullSplat = "[" "*" "]" (GetAttr | Index)*;
+```
+
+The splat operators can be thought of as shorthands for common operations that
+could otherwise be performed using _for expressions_:
+
+- `tuple.*.foo.bar[0]` is approximately equivalent to
+ `[for v in tuple: v.foo.bar][0]`.
+- `tuple[*].foo.bar[0]` is approximately equivalent to
+ `[for v in tuple: v.foo.bar[0]]`
+
+Note the difference in how the trailing index operator is interpreted in
+each case. This different interpretation is the key difference between the
+_attribute-only_ and _full_ splat operators.
+
+Splat operators have one additional behavior compared to the equivalent
+_for expressions_ shown above: if a splat operator is applied to a value that
+is _not_ of tuple, list, or set type, the value is coerced automatically into
+a single-value list of the value type:
+
+- `any_object.*.id` is equivalent to `[any_object.id]`, assuming that `any_object`
+ is a single object.
+- `any_number.*` is equivalent to `[any_number]`, assuming that `any_number`
+ is a single number.
+
+If applied to a null value that is not tuple, list, or set, the result is always
+an empty tuple, which allows conveniently converting a possibly-null scalar
+value into a tuple of zero or one elements. It is illegal to apply a splat
+operator to a null value of tuple, list, or set type.
+
+### Operations
+
+Operations apply a particular operator to either one or two expression terms.
+
+```ebnf
+Operation = unaryOp | binaryOp;
+unaryOp = ("-" | "!") ExprTerm;
+binaryOp = ExprTerm binaryOperator ExprTerm;
+binaryOperator = compareOperator | arithmeticOperator | logicOperator;
+compareOperator = "==" | "!=" | "<" | ">" | "<=" | ">=";
+arithmeticOperator = "+" | "-" | "*" | "/" | "%";
+logicOperator = "&&" | "||";
+```
+
+The unary operators have the highest precedence.
+
+The binary operators are grouped into the following precedence levels:
+
+```
+Level Operators
+ 6 * / %
+ 5 + -
+ 4 > >= < <=
+ 3 == !=
+ 2 &&
+ 1 ||
+```
+
+Higher values of "level" bind tighter. Operators within the same precedence
+level have left-to-right associativity. For example, `x / y * z` is equivalent
+to `(x / y) * z`.
+
+### Comparison Operators
+
+Comparison operators always produce boolean values, as a result of testing
+the relationship between two values.
+
+The two equality operators apply to values of any type:
+
+```
+a == b equal
+a != b not equal
+```
+
+Two values are equal if they are of identical types and their values are
+equal as defined in the HCL syntax-agnostic information model. The equality
+operators are commutative and opposite, such that `(a == b) == !(a != b)`
+and `(a == b) == (b == a)` for all values `a` and `b`.
+
+The four numeric comparison operators apply only to numbers:
+
+```
+a < b less than
+a <= b less than or equal to
+a > b greater than
+a >= b greater than or equal to
+```
+
+If either operand of a comparison operator is a correctly-typed unknown value
+or a value of the dynamic pseudo-type, the result is an unknown boolean.
+
+### Arithmetic Operators
+
+Arithmetic operators apply only to number values and always produce number
+values as results.
+
+```
+a + b sum (addition)
+a - b difference (subtraction)
+a * b product (multiplication)
+a / b quotient (division)
+a % b remainder (modulo)
+-a negation
+```
+
+Arithmetic operations are considered to be performed in an arbitrary-precision
+number space.
+
+If either operand of an arithmetic operator is an unknown number or a value
+of the dynamic pseudo-type, the result is an unknown number.
+
+### Logic Operators
+
+Logic operators apply only to boolean values and always produce boolean values
+as results.
+
+```
+a && b logical AND
+a || b logical OR
+!a logical NOT
+```
+
+If either operand of a logic operator is an unknown bool value or a value
+of the dynamic pseudo-type, the result is an unknown bool value.
+
+### Conditional Operator
+
+The conditional operator allows selecting from one of two expressions based on
+the outcome of a boolean expression.
+
+```ebnf
+Conditional = Expression "?" Expression ":" Expression;
+```
+
+The first expression is the _predicate_, which is evaluated and must produce
+a boolean result. If the predicate value is `true`, the result of the second
+expression is the result of the conditional. If the predicate value is
+`false`, the result of the third expression is the result of the conditional.
+
+The second and third expressions must be of the same type or must be able to
+unify into a common type using the type unification rules defined in the
+HCL syntax-agnostic information model. This unified type is the result type
+of the conditional, with both expressions converted as necessary to the
+unified type.
+
+If the predicate is an unknown boolean value or a value of the dynamic
+pseudo-type then the result is an unknown value of the unified type of the
+other two expressions.
+
+If either the second or third expressions produce errors when evaluated,
+these errors are passed through only if the erroneous expression is selected.
+This allows for expressions such as
+`length(some_list) > 0 ? some_list[0] : default` (given some suitable `length`
+function) without producing an error when the predicate is `false`.
+
+## Templates
+
+The template sub-language is used within template expressions to concisely
+combine strings and other values to produce other strings. It can also be
+used in isolation as a standalone template language.
+
+```ebnf
+Template = (
+ TemplateLiteral |
+ TemplateInterpolation |
+ TemplateDirective
+)*
+TemplateDirective = TemplateIf | TemplateFor;
+```
+
+A template behaves like an expression that always returns a string value.
+The different elements of the template are evaluated and combined into a
+single string to return. If any of the elements produce an unknown string
+or a value of the dynamic pseudo-type, the result is an unknown string.
+
+An important use-case for standalone templates is to enable the use of
+expressions in alternative HCL syntaxes where a native expression grammar is
+not available. For example, the HCL JSON profile treats the values of JSON
+strings as standalone templates when attributes are evaluated in expression
+mode.
+
+### Template Literals
+
+A template literal is a literal sequence of characters to include in the
+resulting string. When the template sub-language is used standalone, a
+template literal can contain any unicode character, with the exception
+of the sequences that introduce interpolations and directives, and for the
+sequences that escape those introductions.
+
+The interpolation and directive introductions are escaped by doubling their
+leading characters. The `${` sequence is escaped as `$${` and the `%{`
+sequence is escaped as `%%{`.
+
+When the template sub-language is embedded in the expression language via
+_template expressions_, additional constraints and transforms are applied to
+template literals as described in the definition of template expressions.
+
+The value of a template literal can be modified by _strip markers_ in any
+interpolations or directives that are adjacent to it. A strip marker is
+a tilde (`~`) placed immediately after the opening `{` or before the closing
+`}` of a template sequence:
+
+- `hello ${~ "world" }` produces `"helloworld"`.
+- `%{ if true ~} hello %{~ endif }` produces `"hello"`.
+
+When a strip marker is present, any spaces adjacent to it in the corresponding
+string literal (if any) are removed before producing the final value. Space
+characters are interpreted as per Unicode's definition.
+
+Stripping is done at syntax level rather than value level. Values returned
+by interpolations or directives are not subject to stripping:
+
+- `${"hello" ~}${" world"}` produces `"hello world"`, and not `"helloworld"`,
+ because the space is not in a template literal directly adjacent to the
+ strip marker.
+
+### Template Interpolations
+
+An _interpolation sequence_ evaluates an expression (written in the
+expression sub-language), converts the result to a string value, and
+replaces itself with the resulting string.
+
+```ebnf
+TemplateInterpolation = ("${" | "${~") Expression ("}" | "~}";
+```
+
+If the expression result cannot be converted to a string, an error is
+produced.
+
+### Template If Directive
+
+The template `if` directive is the template equivalent of the
+_conditional expression_, allowing selection of one of two sub-templates based
+on the value of a predicate expression.
+
+```ebnf
+TemplateIf = (
+ ("%{" | "%{~") "if" Expression ("}" | "~}")
+ Template
+ (
+ ("%{" | "%{~") "else" ("}" | "~}")
+ Template
+ )?
+ ("%{" | "%{~") "endif" ("}" | "~}")
+);
+```
+
+The evaluation of the `if` directive is equivalent to the conditional
+expression, with the following exceptions:
+
+- The two sub-templates always produce strings, and thus the result value is
+ also always a string.
+- The `else` clause may be omitted, in which case the conditional's third
+ expression result is implied to be the empty string.
+
+### Template For Directive
+
+The template `for` directive is the template equivalent of the _for expression_,
+producing zero or more copies of its sub-template based on the elements of
+a collection.
+
+```ebnf
+TemplateFor = (
+ ("%{" | "%{~") "for" Identifier ("," Identifier) "in" Expression ("}" | "~}")
+ Template
+ ("%{" | "%{~") "endfor" ("}" | "~}")
+);
+```
+
+The evaluation of the `for` directive is equivalent to the _for expression_
+when producing a tuple, with the following exceptions:
+
+- The sub-template always produces a string.
+- There is no equivalent of the "if" clause on the for expression.
+- The elements of the resulting tuple are all converted to strings and
+ concatenated to produce a flat string result.
+
+### Template Interpolation Unwrapping
+
+As a special case, a template that consists only of a single interpolation,
+with no surrounding literals, directives or other interpolations, is
+"unwrapped". In this case, the result of the interpolation expression is
+returned verbatim, without conversion to string.
+
+This special case exists primarily to enable the native template language
+to be used inside strings in alternative HCL syntaxes that lack a first-class
+template or expression syntax. Unwrapping allows arbitrary expressions to be
+used to populate attributes when strings in such languages are interpreted
+as templates.
+
+- `${true}` produces the boolean value `true`
+- `${"${true}"}` produces the boolean value `true`, because both the inner
+ and outer interpolations are subject to unwrapping.
+- `hello ${true}` produces the string `"hello true"`
+- `${""}${true}` produces the string `"true"` because there are two
+ interpolation sequences, even though one produces an empty result.
+- `%{ for v in [true] }${v}%{ endfor }` produces the string `true` because
+ the presence of the `for` directive circumvents the unwrapping even though
+ the final result is a single value.
+
+In some contexts this unwrapping behavior may be circumvented by the calling
+application, by converting the final template result to string. This is
+necessary, for example, if a standalone template is being used to produce
+the direct contents of a file, since the result in that case must always be a
+string.
+
+## Static Analysis
+
+The HCL static analysis operations are implemented for some expression types
+in the native syntax, as described in the following sections.
+
+A goal for static analysis of the native syntax is for the interpretation to
+be as consistent as possible with the dynamic evaluation interpretation of
+the given expression, though some deviations are intentionally made in order
+to maximize the potential for analysis.
+
+### Static List
+
+The tuple construction syntax can be interpreted as a static list. All of
+the expression elements given are returned as the static list elements,
+with no further interpretation.
+
+### Static Map
+
+The object construction syntax can be interpreted as a static map. All of the
+key/value pairs given are returned as the static pairs, with no further
+interpretation.
+
+The usual requirement that an attribute name be interpretable as a string
+does not apply to this static analysis, allowing callers to provide map-like
+constructs with different key types by building on the map syntax.
+
+### Static Call
+
+The function call syntax can be interpreted as a static call. The called
+function name is returned verbatim and the given argument expressions are
+returned as the static arguments, with no further interpretation.
+
+### Static Traversal
+
+A variable expression and any attached attribute access operations and
+constant index operations can be interpreted as a static traversal.
+
+The keywords `true`, `false` and `null` can also be interpreted as
+static traversals, behaving as if they were references to variables of those
+names, to allow callers to redefine the meaning of those keywords in certain
+contexts.
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure.go
new file mode 100644
index 00000000000..545ef42f5d4
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure.go
@@ -0,0 +1,396 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// AsHCLBlock returns the block data expressed as a *hcl.Block.
+func (b *Block) AsHCLBlock() *hcl.Block {
+ if b == nil {
+ return nil
+ }
+
+ return &hcl.Block{
+ Type: b.Type,
+ Labels: b.Labels,
+ Body: b.Body,
+
+ DefRange: b.DefRange(),
+ TypeRange: b.TypeRange,
+ LabelRanges: b.LabelRanges,
+ }
+}
+
+// Body is the implementation of hcl.Body for the HCL native syntax.
+type Body struct {
+ Attributes Attributes
+ Blocks Blocks
+
+ // These are used with PartialContent to produce a "remaining items"
+ // body to return. They are nil on all bodies fresh out of the parser.
+ hiddenAttrs map[string]struct{}
+ hiddenBlocks map[string]struct{}
+
+ SrcRange hcl.Range
+ EndRange hcl.Range // Final token of the body (zero-length range)
+}
+
+// Assert that *Body implements hcl.Body
+var _ hcl.Body = &Body{}
+
+func (b *Body) walkChildNodes(w internalWalkFunc) {
+ w(b.Attributes)
+ w(b.Blocks)
+}
+
+func (b *Body) Range() hcl.Range {
+ return b.SrcRange
+}
+
+func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
+ content, remainHCL, diags := b.PartialContent(schema)
+
+ // No we'll see if anything actually remains, to produce errors about
+ // extraneous items.
+ remain := remainHCL.(*Body)
+
+ for name, attr := range b.Attributes {
+ if _, hidden := remain.hiddenAttrs[name]; !hidden {
+ var suggestions []string
+ for _, attrS := range schema.Attributes {
+ if _, defined := content.Attributes[attrS.Name]; defined {
+ continue
+ }
+ suggestions = append(suggestions, attrS.Name)
+ }
+ suggestion := nameSuggestion(name, suggestions)
+ if suggestion != "" {
+ suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
+ } else {
+ // Is there a block of the same name?
+ for _, blockS := range schema.Blocks {
+ if blockS.Type == name {
+ suggestion = fmt.Sprintf(" Did you mean to define a block of type %q?", name)
+ break
+ }
+ }
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unsupported argument",
+ Detail: fmt.Sprintf("An argument named %q is not expected here.%s", name, suggestion),
+ Subject: &attr.NameRange,
+ })
+ }
+ }
+
+ for _, block := range b.Blocks {
+ blockTy := block.Type
+ if _, hidden := remain.hiddenBlocks[blockTy]; !hidden {
+ var suggestions []string
+ for _, blockS := range schema.Blocks {
+ suggestions = append(suggestions, blockS.Type)
+ }
+ suggestion := nameSuggestion(blockTy, suggestions)
+ if suggestion != "" {
+ suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
+ } else {
+ // Is there an attribute of the same name?
+ for _, attrS := range schema.Attributes {
+ if attrS.Name == blockTy {
+ suggestion = fmt.Sprintf(" Did you mean to define argument %q? If so, use the equals sign to assign it a value.", blockTy)
+ break
+ }
+ }
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unsupported block type",
+ Detail: fmt.Sprintf("Blocks of type %q are not expected here.%s", blockTy, suggestion),
+ Subject: &block.TypeRange,
+ })
+ }
+ }
+
+ return content, diags
+}
+
+func (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
+ attrs := make(hcl.Attributes)
+ var blocks hcl.Blocks
+ var diags hcl.Diagnostics
+ hiddenAttrs := make(map[string]struct{})
+ hiddenBlocks := make(map[string]struct{})
+
+ if b.hiddenAttrs != nil {
+ for k, v := range b.hiddenAttrs {
+ hiddenAttrs[k] = v
+ }
+ }
+ if b.hiddenBlocks != nil {
+ for k, v := range b.hiddenBlocks {
+ hiddenBlocks[k] = v
+ }
+ }
+
+ for _, attrS := range schema.Attributes {
+ name := attrS.Name
+ attr, exists := b.Attributes[name]
+ _, hidden := hiddenAttrs[name]
+ if hidden || !exists {
+ if attrS.Required {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing required argument",
+ Detail: fmt.Sprintf("The argument %q is required, but no definition was found.", attrS.Name),
+ Subject: b.MissingItemRange().Ptr(),
+ })
+ }
+ continue
+ }
+
+ hiddenAttrs[name] = struct{}{}
+ attrs[name] = attr.AsHCLAttribute()
+ }
+
+ blocksWanted := make(map[string]hcl.BlockHeaderSchema)
+ for _, blockS := range schema.Blocks {
+ blocksWanted[blockS.Type] = blockS
+ }
+
+ for _, block := range b.Blocks {
+ if _, hidden := hiddenBlocks[block.Type]; hidden {
+ continue
+ }
+ blockS, wanted := blocksWanted[block.Type]
+ if !wanted {
+ continue
+ }
+
+ if len(block.Labels) > len(blockS.LabelNames) {
+ name := block.Type
+ if len(blockS.LabelNames) == 0 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Extraneous label for %s", name),
+ Detail: fmt.Sprintf(
+ "No labels are expected for %s blocks.", name,
+ ),
+ Subject: block.LabelRanges[0].Ptr(),
+ Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),
+ })
+ } else {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Extraneous label for %s", name),
+ Detail: fmt.Sprintf(
+ "Only %d labels (%s) are expected for %s blocks.",
+ len(blockS.LabelNames), strings.Join(blockS.LabelNames, ", "), name,
+ ),
+ Subject: block.LabelRanges[len(blockS.LabelNames)].Ptr(),
+ Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),
+ })
+ }
+ continue
+ }
+
+ if len(block.Labels) < len(blockS.LabelNames) {
+ name := block.Type
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Missing %s for %s", blockS.LabelNames[len(block.Labels)], name),
+ Detail: fmt.Sprintf(
+ "All %s blocks must have %d labels (%s).",
+ name, len(blockS.LabelNames), strings.Join(blockS.LabelNames, ", "),
+ ),
+ Subject: &block.OpenBraceRange,
+ Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),
+ })
+ continue
+ }
+
+ blocks = append(blocks, block.AsHCLBlock())
+ }
+
+ // We hide blocks only after we've processed all of them, since otherwise
+ // we can't process more than one of the same type.
+ for _, blockS := range schema.Blocks {
+ hiddenBlocks[blockS.Type] = struct{}{}
+ }
+
+ remain := &Body{
+ Attributes: b.Attributes,
+ Blocks: b.Blocks,
+
+ hiddenAttrs: hiddenAttrs,
+ hiddenBlocks: hiddenBlocks,
+
+ SrcRange: b.SrcRange,
+ EndRange: b.EndRange,
+ }
+
+ return &hcl.BodyContent{
+ Attributes: attrs,
+ Blocks: blocks,
+
+ MissingItemRange: b.MissingItemRange(),
+ }, remain, diags
+}
+
+func (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
+ attrs := make(hcl.Attributes)
+ var diags hcl.Diagnostics
+
+ if len(b.Blocks) > 0 {
+ example := b.Blocks[0]
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Unexpected %q block", example.Type),
+ Detail: "Blocks are not allowed here.",
+ Subject: &example.TypeRange,
+ })
+ // we will continue processing anyway, and return the attributes
+ // we are able to find so that certain analyses can still be done
+ // in the face of errors.
+ }
+
+ if b.Attributes == nil {
+ return attrs, diags
+ }
+
+ for name, attr := range b.Attributes {
+ if _, hidden := b.hiddenAttrs[name]; hidden {
+ continue
+ }
+ attrs[name] = attr.AsHCLAttribute()
+ }
+
+ return attrs, diags
+}
+
+func (b *Body) MissingItemRange() hcl.Range {
+ return hcl.Range{
+ Filename: b.SrcRange.Filename,
+ Start: b.SrcRange.Start,
+ End: b.SrcRange.Start,
+ }
+}
+
+// Attributes is the collection of attribute definitions within a body.
+type Attributes map[string]*Attribute
+
+func (a Attributes) walkChildNodes(w internalWalkFunc) {
+ for _, attr := range a {
+ w(attr)
+ }
+}
+
+// Range returns the range of some arbitrary point within the set of
+// attributes, or an invalid range if there are no attributes.
+//
+// This is provided only to complete the Node interface, but has no practical
+// use.
+func (a Attributes) Range() hcl.Range {
+ // An attributes doesn't really have a useful range to report, since
+ // it's just a grouping construct. So we'll arbitrarily take the
+ // range of one of the attributes, or produce an invalid range if we have
+ // none. In practice, there's little reason to ask for the range of
+ // an Attributes.
+ for _, attr := range a {
+ return attr.Range()
+ }
+ return hcl.Range{
+ Filename: "",
+ }
+}
+
+// Attribute represents a single attribute definition within a body.
+type Attribute struct {
+ Name string
+ Expr Expression
+
+ SrcRange hcl.Range
+ NameRange hcl.Range
+ EqualsRange hcl.Range
+}
+
+func (a *Attribute) walkChildNodes(w internalWalkFunc) {
+ w(a.Expr)
+}
+
+func (a *Attribute) Range() hcl.Range {
+ return a.SrcRange
+}
+
+// AsHCLAttribute returns the block data expressed as a *hcl.Attribute.
+func (a *Attribute) AsHCLAttribute() *hcl.Attribute {
+ if a == nil {
+ return nil
+ }
+ return &hcl.Attribute{
+ Name: a.Name,
+ Expr: a.Expr,
+
+ Range: a.SrcRange,
+ NameRange: a.NameRange,
+ }
+}
+
+// Blocks is the list of nested blocks within a body.
+type Blocks []*Block
+
+func (bs Blocks) walkChildNodes(w internalWalkFunc) {
+ for _, block := range bs {
+ w(block)
+ }
+}
+
+// Range returns the range of some arbitrary point within the list of
+// blocks, or an invalid range if there are no blocks.
+//
+// This is provided only to complete the Node interface, but has no practical
+// use.
+func (bs Blocks) Range() hcl.Range {
+ if len(bs) > 0 {
+ return bs[0].Range()
+ }
+ return hcl.Range{
+ Filename: "",
+ }
+}
+
+// Block represents a nested block structure
+type Block struct {
+ Type string
+ Labels []string
+ Body *Body
+
+ TypeRange hcl.Range
+ LabelRanges []hcl.Range
+ OpenBraceRange hcl.Range
+ CloseBraceRange hcl.Range
+}
+
+func (b *Block) walkChildNodes(w internalWalkFunc) {
+ w(b.Body)
+}
+
+func (b *Block) Range() hcl.Range {
+ return hcl.RangeBetween(b.TypeRange, b.CloseBraceRange)
+}
+
+func (b *Block) DefRange() hcl.Range {
+ lastHeaderRange := b.TypeRange
+ if len(b.LabelRanges) > 0 {
+ lastHeaderRange = b.LabelRanges[len(b.LabelRanges)-1]
+ }
+ return hcl.RangeBetween(b.TypeRange, lastHeaderRange)
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure_at_pos.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure_at_pos.go
new file mode 100644
index 00000000000..5085716845a
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/structure_at_pos.go
@@ -0,0 +1,121 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+// -----------------------------------------------------------------------------
+// The methods in this file are all optional extension methods that serve to
+// implement the methods of the same name on *hcl.File when its root body
+// is provided by this package.
+// -----------------------------------------------------------------------------
+
+// BlocksAtPos implements the method of the same name for an *hcl.File that
+// is backed by a *Body.
+func (b *Body) BlocksAtPos(pos hcl.Pos) []*hcl.Block {
+ list, _ := b.blocksAtPos(pos, true)
+ return list
+}
+
+// InnermostBlockAtPos implements the method of the same name for an *hcl.File
+// that is backed by a *Body.
+func (b *Body) InnermostBlockAtPos(pos hcl.Pos) *hcl.Block {
+ _, innermost := b.blocksAtPos(pos, false)
+ return innermost.AsHCLBlock()
+}
+
+// OutermostBlockAtPos implements the method of the same name for an *hcl.File
+// that is backed by a *Body.
+func (b *Body) OutermostBlockAtPos(pos hcl.Pos) *hcl.Block {
+ return b.outermostBlockAtPos(pos).AsHCLBlock()
+}
+
+// blocksAtPos is the internal engine of both BlocksAtPos and
+// InnermostBlockAtPos, which both need to do the same logic but return a
+// differently-shaped result.
+//
+// list is nil if makeList is false, avoiding an allocation. Innermost is
+// always set, and if the returned list is non-nil it will always match the
+// final element from that list.
+func (b *Body) blocksAtPos(pos hcl.Pos, makeList bool) (list []*hcl.Block, innermost *Block) {
+ current := b
+
+Blocks:
+ for current != nil {
+ for _, block := range current.Blocks {
+ wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)
+ if wholeRange.ContainsPos(pos) {
+ innermost = block
+ if makeList {
+ list = append(list, innermost.AsHCLBlock())
+ }
+ current = block.Body
+ continue Blocks
+ }
+ }
+
+ // If we fall out here then none of the current body's nested blocks
+ // contain the position we are looking for, and so we're done.
+ break
+ }
+
+ return
+}
+
+// outermostBlockAtPos is the internal version of OutermostBlockAtPos that
+// returns a hclsyntax.Block rather than an hcl.Block, allowing for further
+// analysis if necessary.
+func (b *Body) outermostBlockAtPos(pos hcl.Pos) *Block {
+ // This is similar to blocksAtPos, but simpler because we know it only
+ // ever needs to search the first level of nested blocks.
+
+ for _, block := range b.Blocks {
+ wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)
+ if wholeRange.ContainsPos(pos) {
+ return block
+ }
+ }
+
+ return nil
+}
+
+// AttributeAtPos implements the method of the same name for an *hcl.File
+// that is backed by a *Body.
+func (b *Body) AttributeAtPos(pos hcl.Pos) *hcl.Attribute {
+ return b.attributeAtPos(pos).AsHCLAttribute()
+}
+
+// attributeAtPos is the internal version of AttributeAtPos that returns a
+// hclsyntax.Block rather than an hcl.Block, allowing for further analysis if
+// necessary.
+func (b *Body) attributeAtPos(pos hcl.Pos) *Attribute {
+ searchBody := b
+ _, block := b.blocksAtPos(pos, false)
+ if block != nil {
+ searchBody = block.Body
+ }
+
+ for _, attr := range searchBody.Attributes {
+ if attr.SrcRange.ContainsPos(pos) {
+ return attr
+ }
+ }
+
+ return nil
+}
+
+// OutermostExprAtPos implements the method of the same name for an *hcl.File
+// that is backed by a *Body.
+func (b *Body) OutermostExprAtPos(pos hcl.Pos) hcl.Expression {
+ attr := b.attributeAtPos(pos)
+ if attr == nil {
+ return nil
+ }
+ if !attr.Expr.Range().ContainsPos(pos) {
+ return nil
+ }
+ return attr.Expr
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/token.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/token.go
new file mode 100644
index 00000000000..47648b8f006
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclsyntax/token.go
@@ -0,0 +1,337 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclsyntax
+
+import (
+ "bytes"
+ "fmt"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+ "github.com/hashicorp/hcl/v2"
+)
+
+// Token represents a sequence of bytes from some HCL code that has been
+// tagged with a type and its range within the source file.
+type Token struct {
+ Type TokenType
+ Bytes []byte
+ Range hcl.Range
+}
+
+// Tokens is a slice of Token.
+type Tokens []Token
+
+// TokenType is an enumeration used for the Type field on Token.
+type TokenType rune
+
+const (
+ // Single-character tokens are represented by their own character, for
+ // convenience in producing these within the scanner. However, the values
+ // are otherwise arbitrary and just intended to be mnemonic for humans
+ // who might see them in debug output.
+
+ TokenOBrace TokenType = '{'
+ TokenCBrace TokenType = '}'
+ TokenOBrack TokenType = '['
+ TokenCBrack TokenType = ']'
+ TokenOParen TokenType = '('
+ TokenCParen TokenType = ')'
+ TokenOQuote TokenType = '«'
+ TokenCQuote TokenType = '»'
+ TokenOHeredoc TokenType = 'H'
+ TokenCHeredoc TokenType = 'h'
+
+ TokenStar TokenType = '*'
+ TokenSlash TokenType = '/'
+ TokenPlus TokenType = '+'
+ TokenMinus TokenType = '-'
+ TokenPercent TokenType = '%'
+
+ TokenEqual TokenType = '='
+ TokenEqualOp TokenType = '≔'
+ TokenNotEqual TokenType = '≠'
+ TokenLessThan TokenType = '<'
+ TokenLessThanEq TokenType = '≤'
+ TokenGreaterThan TokenType = '>'
+ TokenGreaterThanEq TokenType = '≥'
+
+ TokenAnd TokenType = '∧'
+ TokenOr TokenType = '∨'
+ TokenBang TokenType = '!'
+
+ TokenDot TokenType = '.'
+ TokenComma TokenType = ','
+
+ TokenDoubleColon TokenType = '⸬'
+ TokenEllipsis TokenType = '…'
+ TokenFatArrow TokenType = '⇒'
+
+ TokenQuestion TokenType = '?'
+ TokenColon TokenType = ':'
+
+ TokenTemplateInterp TokenType = '∫'
+ TokenTemplateControl TokenType = 'λ'
+ TokenTemplateSeqEnd TokenType = '∎'
+
+ TokenQuotedLit TokenType = 'Q' // might contain backslash escapes
+ TokenStringLit TokenType = 'S' // cannot contain backslash escapes
+ TokenNumberLit TokenType = 'N'
+ TokenIdent TokenType = 'I'
+
+ TokenComment TokenType = 'C'
+
+ TokenNewline TokenType = '\n'
+ TokenEOF TokenType = '␄'
+
+ // The rest are not used in the language but recognized by the scanner so
+ // we can generate good diagnostics in the parser when users try to write
+ // things that might work in other languages they are familiar with, or
+ // simply make incorrect assumptions about the HCL language.
+
+ TokenBitwiseAnd TokenType = '&'
+ TokenBitwiseOr TokenType = '|'
+ TokenBitwiseNot TokenType = '~'
+ TokenBitwiseXor TokenType = '^'
+ TokenStarStar TokenType = '➚'
+ TokenApostrophe TokenType = '\''
+ TokenBacktick TokenType = '`'
+ TokenSemicolon TokenType = ';'
+ TokenTabs TokenType = '␉'
+ TokenInvalid TokenType = '�'
+ TokenBadUTF8 TokenType = '💩'
+ TokenQuotedNewline TokenType = ''
+
+ // TokenNil is a placeholder for when a token is required but none is
+ // available, e.g. when reporting errors. The scanner will never produce
+ // this as part of a token stream.
+ TokenNil TokenType = '\x00'
+)
+
+func (t TokenType) GoString() string {
+ return fmt.Sprintf("hclsyntax.%s", t.String())
+}
+
+type scanMode int
+
+const (
+ scanNormal scanMode = iota
+ scanTemplate
+ scanIdentOnly
+)
+
+type tokenAccum struct {
+ Filename string
+ Bytes []byte
+ Pos hcl.Pos
+ Tokens []Token
+ StartByte int
+}
+
+func (f *tokenAccum) emitToken(ty TokenType, startOfs, endOfs int) {
+ // Walk through our buffer to figure out how much we need to adjust
+ // the start pos to get our end pos.
+
+ start := f.Pos
+ start.Column += startOfs + f.StartByte - f.Pos.Byte // Safe because only ASCII spaces can be in the offset
+ start.Byte = startOfs + f.StartByte
+
+ end := start
+ end.Byte = endOfs + f.StartByte
+ b := f.Bytes[startOfs:endOfs]
+ for len(b) > 0 {
+ advance, seq, _ := textseg.ScanGraphemeClusters(b, true)
+ if (len(seq) == 1 && seq[0] == '\n') || (len(seq) == 2 && seq[0] == '\r' && seq[1] == '\n') {
+ end.Line++
+ end.Column = 1
+ } else {
+ end.Column++
+ }
+ b = b[advance:]
+ }
+
+ f.Pos = end
+
+ f.Tokens = append(f.Tokens, Token{
+ Type: ty,
+ Bytes: f.Bytes[startOfs:endOfs],
+ Range: hcl.Range{
+ Filename: f.Filename,
+ Start: start,
+ End: end,
+ },
+ })
+}
+
+type heredocInProgress struct {
+ Marker []byte
+ StartOfLine bool
+}
+
+func tokenOpensFlushHeredoc(tok Token) bool {
+ if tok.Type != TokenOHeredoc {
+ return false
+ }
+ return bytes.HasPrefix(tok.Bytes, []byte{'<', '<', '-'})
+}
+
+// checkInvalidTokens does a simple pass across the given tokens and generates
+// diagnostics for tokens that should _never_ appear in HCL source. This
+// is intended to avoid the need for the parser to have special support
+// for them all over.
+//
+// Returns a diagnostics with no errors if everything seems acceptable.
+// Otherwise, returns zero or more error diagnostics, though tries to limit
+// repetition of the same information.
+func checkInvalidTokens(tokens Tokens) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ toldBitwise := 0
+ toldExponent := 0
+ toldBacktick := 0
+ toldApostrophe := 0
+ toldSemicolon := 0
+ toldTabs := 0
+ toldBadUTF8 := 0
+
+ for _, tok := range tokens {
+ tokRange := func() *hcl.Range {
+ r := tok.Range
+ return &r
+ }
+
+ switch tok.Type {
+ case TokenBitwiseAnd, TokenBitwiseOr, TokenBitwiseXor, TokenBitwiseNot:
+ if toldBitwise < 4 {
+ var suggestion string
+ switch tok.Type {
+ case TokenBitwiseAnd:
+ suggestion = " Did you mean boolean AND (\"&&\")?"
+ case TokenBitwiseOr:
+ suggestion = " Did you mean boolean OR (\"||\")?"
+ case TokenBitwiseNot:
+ suggestion = " Did you mean boolean NOT (\"!\")?"
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unsupported operator",
+ Detail: fmt.Sprintf("Bitwise operators are not supported.%s", suggestion),
+ Subject: tokRange(),
+ })
+ toldBitwise++
+ }
+ case TokenStarStar:
+ if toldExponent < 1 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unsupported operator",
+ Detail: "\"**\" is not a supported operator. Exponentiation is not supported as an operator.",
+ Subject: tokRange(),
+ })
+
+ toldExponent++
+ }
+ case TokenBacktick:
+ // Only report for alternating (even) backticks, so we won't report both start and ends of the same
+ // backtick-quoted string.
+ if (toldBacktick % 2) == 0 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid character",
+ Detail: "The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<
+#
+# This script uses the unicode spec to generate a Ragel state machine
+# that recognizes unicode alphanumeric characters. It generates 5
+# character classes: uupper, ulower, ualpha, udigit, and ualnum.
+# Currently supported encodings are UTF-8 [default] and UCS-4.
+#
+# Usage: unicode2ragel.rb [options]
+# -e, --encoding [ucs4 | utf8] Data encoding
+# -h, --help Show this message
+#
+# This script was originally written as part of the Ferret search
+# engine library.
+#
+# Author: Rakan El-Khalil
+
+require 'optparse'
+require 'open-uri'
+
+ENCODINGS = [ :utf8, :ucs4 ]
+ALPHTYPES = { :utf8 => "byte", :ucs4 => "rune" }
+DEFAULT_CHART_URL = "http://www.unicode.org/Public/5.1.0/ucd/DerivedCoreProperties.txt"
+DEFAULT_MACHINE_NAME= "WChar"
+
+###
+# Display vars & default option
+
+TOTAL_WIDTH = 80
+RANGE_WIDTH = 23
+@encoding = :utf8
+@chart_url = DEFAULT_CHART_URL
+machine_name = DEFAULT_MACHINE_NAME
+properties = []
+@output = $stdout
+
+###
+# Option parsing
+
+cli_opts = OptionParser.new do |opts|
+ opts.on("-e", "--encoding [ucs4 | utf8]", "Data encoding") do |o|
+ @encoding = o.downcase.to_sym
+ end
+ opts.on("-h", "--help", "Show this message") do
+ puts opts
+ exit
+ end
+ opts.on("-u", "--url URL", "URL to process") do |o|
+ @chart_url = o
+ end
+ opts.on("-m", "--machine MACHINE_NAME", "Machine name") do |o|
+ machine_name = o
+ end
+ opts.on("-p", "--properties x,y,z", Array, "Properties to add to machine") do |o|
+ properties = o
+ end
+ opts.on("-o", "--output FILE", "output file") do |o|
+ @output = File.new(o, "w+")
+ end
+end
+
+cli_opts.parse(ARGV)
+unless ENCODINGS.member? @encoding
+ puts "Invalid encoding: #{@encoding}"
+ puts cli_opts
+ exit
+end
+
+##
+# Downloads the document at url and yields every alpha line's hex
+# range and description.
+
+def each_alpha( url, property )
+ open( url ) do |file|
+ file.each_line do |line|
+ next if line =~ /^#/;
+ next if line !~ /; #{property} #/;
+
+ range, description = line.split(/;/)
+ range.strip!
+ description.gsub!(/.*#/, '').strip!
+
+ if range =~ /\.\./
+ start, stop = range.split '..'
+ else start = stop = range
+ end
+
+ yield start.hex .. stop.hex, description
+ end
+ end
+end
+
+###
+# Formats to hex at minimum width
+
+def to_hex( n )
+ r = "%0X" % n
+ r = "0#{r}" unless (r.length % 2).zero?
+ r
+end
+
+###
+# UCS4 is just a straight hex conversion of the unicode codepoint.
+
+def to_ucs4( range )
+ rangestr = "0x" + to_hex(range.begin)
+ rangestr << "..0x" + to_hex(range.end) if range.begin != range.end
+ [ rangestr ]
+end
+
+##
+# 0x00 - 0x7f -> 0zzzzzzz[7]
+# 0x80 - 0x7ff -> 110yyyyy[5] 10zzzzzz[6]
+# 0x800 - 0xffff -> 1110xxxx[4] 10yyyyyy[6] 10zzzzzz[6]
+# 0x010000 - 0x10ffff -> 11110www[3] 10xxxxxx[6] 10yyyyyy[6] 10zzzzzz[6]
+
+UTF8_BOUNDARIES = [0x7f, 0x7ff, 0xffff, 0x10ffff]
+
+def to_utf8_enc( n )
+ r = 0
+ if n <= 0x7f
+ r = n
+ elsif n <= 0x7ff
+ y = 0xc0 | (n >> 6)
+ z = 0x80 | (n & 0x3f)
+ r = y << 8 | z
+ elsif n <= 0xffff
+ x = 0xe0 | (n >> 12)
+ y = 0x80 | (n >> 6) & 0x3f
+ z = 0x80 | n & 0x3f
+ r = x << 16 | y << 8 | z
+ elsif n <= 0x10ffff
+ w = 0xf0 | (n >> 18)
+ x = 0x80 | (n >> 12) & 0x3f
+ y = 0x80 | (n >> 6) & 0x3f
+ z = 0x80 | n & 0x3f
+ r = w << 24 | x << 16 | y << 8 | z
+ end
+
+ to_hex(r)
+end
+
+def from_utf8_enc( n )
+ n = n.hex
+ r = 0
+ if n <= 0x7f
+ r = n
+ elsif n <= 0xdfff
+ y = (n >> 8) & 0x1f
+ z = n & 0x3f
+ r = y << 6 | z
+ elsif n <= 0xefffff
+ x = (n >> 16) & 0x0f
+ y = (n >> 8) & 0x3f
+ z = n & 0x3f
+ r = x << 10 | y << 6 | z
+ elsif n <= 0xf7ffffff
+ w = (n >> 24) & 0x07
+ x = (n >> 16) & 0x3f
+ y = (n >> 8) & 0x3f
+ z = n & 0x3f
+ r = w << 18 | x << 12 | y << 6 | z
+ end
+ r
+end
+
+###
+# Given a range, splits it up into ranges that can be continuously
+# encoded into utf8. Eg: 0x00 .. 0xff => [0x00..0x7f, 0x80..0xff]
+# This is not strictly needed since the current [5.1] unicode standard
+# doesn't have ranges that straddle utf8 boundaries. This is included
+# for completeness as there is no telling if that will ever change.
+
+def utf8_ranges( range )
+ ranges = []
+ UTF8_BOUNDARIES.each do |max|
+ if range.begin <= max
+ if range.end <= max
+ ranges << range
+ return ranges
+ end
+
+ ranges << (range.begin .. max)
+ range = (max + 1) .. range.end
+ end
+ end
+ ranges
+end
+
+def build_range( start, stop )
+ size = start.size/2
+ left = size - 1
+ return [""] if size < 1
+
+ a = start[0..1]
+ b = stop[0..1]
+
+ ###
+ # Shared prefix
+
+ if a == b
+ return build_range(start[2..-1], stop[2..-1]).map do |elt|
+ "0x#{a} " + elt
+ end
+ end
+
+ ###
+ # Unshared prefix, end of run
+
+ return ["0x#{a}..0x#{b} "] if left.zero?
+
+ ###
+ # Unshared prefix, not end of run
+ # Range can be 0x123456..0x56789A
+ # Which is equivalent to:
+ # 0x123456 .. 0x12FFFF
+ # 0x130000 .. 0x55FFFF
+ # 0x560000 .. 0x56789A
+
+ ret = []
+ ret << build_range(start, a + "FF" * left)
+
+ ###
+ # Only generate middle range if need be.
+
+ if a.hex+1 != b.hex
+ max = to_hex(b.hex - 1)
+ max = "FF" if b == "FF"
+ ret << "0x#{to_hex(a.hex+1)}..0x#{max} " + "0x00..0xFF " * left
+ end
+
+ ###
+ # Don't generate last range if it is covered by first range
+
+ ret << build_range(b + "00" * left, stop) unless b == "FF"
+ ret.flatten!
+end
+
+def to_utf8( range )
+ utf8_ranges( range ).map do |r|
+ begin_enc = to_utf8_enc(r.begin)
+ end_enc = to_utf8_enc(r.end)
+ build_range begin_enc, end_enc
+ end.flatten!
+end
+
+##
+# Perform a 3-way comparison of the number of codepoints advertised by
+# the unicode spec for the given range, the originally parsed range,
+# and the resulting utf8 encoded range.
+
+def count_codepoints( code )
+ code.split(' ').inject(1) do |acc, elt|
+ if elt =~ /0x(.+)\.\.0x(.+)/
+ if @encoding == :utf8
+ acc * (from_utf8_enc($2) - from_utf8_enc($1) + 1)
+ else
+ acc * ($2.hex - $1.hex + 1)
+ end
+ else
+ acc
+ end
+ end
+end
+
+def is_valid?( range, desc, codes )
+ spec_count = 1
+ spec_count = $1.to_i if desc =~ /\[(\d+)\]/
+ range_count = range.end - range.begin + 1
+
+ sum = codes.inject(0) { |acc, elt| acc + count_codepoints(elt) }
+ sum == spec_count and sum == range_count
+end
+
+##
+# Generate the state maching to stdout
+
+def generate_machine( name, property )
+ pipe = " "
+ @output.puts " #{name} = "
+ each_alpha( @chart_url, property ) do |range, desc|
+
+ codes = (@encoding == :ucs4) ? to_ucs4(range) : to_utf8(range)
+
+ #raise "Invalid encoding of range #{range}: #{codes.inspect}" unless
+ # is_valid? range, desc, codes
+
+ range_width = codes.map { |a| a.size }.max
+ range_width = RANGE_WIDTH if range_width < RANGE_WIDTH
+
+ desc_width = TOTAL_WIDTH - RANGE_WIDTH - 11
+ desc_width -= (range_width - RANGE_WIDTH) if range_width > RANGE_WIDTH
+
+ if desc.size > desc_width
+ desc = desc[0..desc_width - 4] + "..."
+ end
+
+ codes.each_with_index do |r, idx|
+ desc = "" unless idx.zero?
+ code = "%-#{range_width}s" % r
+ @output.puts " #{pipe} #{code} ##{desc}"
+ pipe = "|"
+ end
+ end
+ @output.puts " ;"
+ @output.puts ""
+end
+
+@output.puts < 0:
+ line.lead[0].SpacesBefore = 2 * len(indents)
+ indents = append(indents, netBrackets)
+ case netBrackets < 0:
+ closed := -netBrackets
+ for closed > 0 && len(indents) > 0 {
+ switch {
+
+ case closed > indents[len(indents)-1]:
+ closed -= indents[len(indents)-1]
+ indents = indents[:len(indents)-1]
+
+ case closed < indents[len(indents)-1]:
+ indents[len(indents)-1] -= closed
+ closed = 0
+
+ default:
+ indents = indents[:len(indents)-1]
+ closed = 0
+ }
+ }
+ line.lead[0].SpacesBefore = 2 * len(indents)
+ default:
+ line.lead[0].SpacesBefore = 2 * len(indents)
+ }
+ }
+}
+
+func formatSpaces(lines []formatLine) {
+ // placeholder token used when we don't have a token but we don't want
+ // to pass a real "nil" and complicate things with nil pointer checks
+ nilToken := &Token{
+ Type: hclsyntax.TokenNil,
+ Bytes: []byte{},
+ SpacesBefore: 0,
+ }
+
+ for _, line := range lines {
+ for i, token := range line.lead {
+ var before, after *Token
+ if i > 0 {
+ before = line.lead[i-1]
+ } else {
+ before = nilToken
+ }
+ if i < (len(line.lead) - 1) {
+ after = line.lead[i+1]
+ } else {
+ continue
+ }
+ if spaceAfterToken(token, before, after) {
+ after.SpacesBefore = 1
+ } else {
+ after.SpacesBefore = 0
+ }
+ }
+ for i, token := range line.assign {
+ if i == 0 {
+ // first token in "assign" always has one space before to
+ // separate the equals sign from what it's assigning.
+ token.SpacesBefore = 1
+ }
+
+ var before, after *Token
+ if i > 0 {
+ before = line.assign[i-1]
+ } else {
+ before = nilToken
+ }
+ if i < (len(line.assign) - 1) {
+ after = line.assign[i+1]
+ } else {
+ continue
+ }
+ if spaceAfterToken(token, before, after) {
+ after.SpacesBefore = 1
+ } else {
+ after.SpacesBefore = 0
+ }
+ }
+
+ }
+}
+
+func formatCells(lines []formatLine) {
+ chainStart := -1
+ maxColumns := 0
+
+ // We'll deal with the "assign" cell first, since moving that will
+ // also impact the "comment" cell.
+ closeAssignChain := func(i int) {
+ for _, chainLine := range lines[chainStart:i] {
+ columns := chainLine.lead.Columns()
+ spaces := (maxColumns - columns) + 1
+ chainLine.assign[0].SpacesBefore = spaces
+ }
+ chainStart = -1
+ maxColumns = 0
+ }
+ for i, line := range lines {
+ if line.assign == nil {
+ if chainStart != -1 {
+ closeAssignChain(i)
+ }
+ } else {
+ if chainStart == -1 {
+ chainStart = i
+ }
+ columns := line.lead.Columns()
+ if columns > maxColumns {
+ maxColumns = columns
+ }
+ }
+ }
+ if chainStart != -1 {
+ closeAssignChain(len(lines))
+ }
+
+ // Now we'll deal with the comments
+ closeCommentChain := func(i int) {
+ for _, chainLine := range lines[chainStart:i] {
+ columns := chainLine.lead.Columns() + chainLine.assign.Columns()
+ spaces := (maxColumns - columns) + 1
+ chainLine.comment[0].SpacesBefore = spaces
+ }
+ chainStart = -1
+ maxColumns = 0
+ }
+ for i, line := range lines {
+ if line.comment == nil {
+ if chainStart != -1 {
+ closeCommentChain(i)
+ }
+ } else {
+ if chainStart == -1 {
+ chainStart = i
+ }
+ columns := line.lead.Columns() + line.assign.Columns()
+ if columns > maxColumns {
+ maxColumns = columns
+ }
+ }
+ }
+ if chainStart != -1 {
+ closeCommentChain(len(lines))
+ }
+}
+
+// spaceAfterToken decides whether a particular subject token should have a
+// space after it when surrounded by the given before and after tokens.
+// "before" can be TokenNil, if the subject token is at the start of a sequence.
+func spaceAfterToken(subject, before, after *Token) bool {
+ switch {
+
+ case after.Type == hclsyntax.TokenNewline || after.Type == hclsyntax.TokenNil:
+ // Never add spaces before a newline
+ return false
+
+ case subject.Type == hclsyntax.TokenIdent && after.Type == hclsyntax.TokenOParen:
+ // Don't split a function name from open paren in a call
+ return false
+
+ case (subject.Type == hclsyntax.TokenIdent && after.Type == hclsyntax.TokenDoubleColon) ||
+ (subject.Type == hclsyntax.TokenDoubleColon && after.Type == hclsyntax.TokenIdent):
+ // Don't split namespace segments in a function call
+ return false
+
+ case subject.Type == hclsyntax.TokenDot || after.Type == hclsyntax.TokenDot:
+ // Don't use spaces around attribute access dots
+ return false
+
+ case after.Type == hclsyntax.TokenComma || after.Type == hclsyntax.TokenEllipsis:
+ // No space right before a comma or ... in an argument list
+ return false
+
+ case subject.Type == hclsyntax.TokenComma:
+ // Always a space after a comma
+ return true
+
+ case subject.Type == hclsyntax.TokenQuotedLit || subject.Type == hclsyntax.TokenStringLit || subject.Type == hclsyntax.TokenOQuote || subject.Type == hclsyntax.TokenOHeredoc || after.Type == hclsyntax.TokenQuotedLit || after.Type == hclsyntax.TokenStringLit || after.Type == hclsyntax.TokenCQuote || after.Type == hclsyntax.TokenCHeredoc:
+ // No extra spaces within templates
+ return false
+
+ case hclsyntax.Keyword([]byte{'i', 'n'}).TokenMatches(subject.asHCLSyntax()) && before.Type == hclsyntax.TokenIdent:
+ // This is a special case for inside for expressions where a user
+ // might want to use a literal tuple constructor:
+ // [for x in [foo]: x]
+ // ... in that case, we would normally produce in[foo] thinking that
+ // in is a reference, but we'll recognize it as a keyword here instead
+ // to make the result less confusing.
+ return true
+
+ case after.Type == hclsyntax.TokenOBrack && (subject.Type == hclsyntax.TokenIdent || subject.Type == hclsyntax.TokenNumberLit || tokenBracketChange(subject) < 0):
+ return false
+
+ case subject.Type == hclsyntax.TokenBang:
+ // No space after a bang
+ return false
+
+ case subject.Type == hclsyntax.TokenMinus:
+ // Since a minus can either be subtraction or negation, and the latter
+ // should _not_ have a space after it, we need to use some heuristics
+ // to decide which case this is.
+ // We guess that we have a negation if the token before doesn't look
+ // like it could be the end of an expression.
+
+ switch before.Type {
+
+ case hclsyntax.TokenNil:
+ // Minus at the start of input must be a negation
+ return false
+
+ case hclsyntax.TokenOParen, hclsyntax.TokenOBrace, hclsyntax.TokenOBrack, hclsyntax.TokenEqual, hclsyntax.TokenColon, hclsyntax.TokenComma, hclsyntax.TokenQuestion:
+ // Minus immediately after an opening bracket or separator must be a negation.
+ return false
+
+ case hclsyntax.TokenPlus, hclsyntax.TokenStar, hclsyntax.TokenSlash, hclsyntax.TokenPercent, hclsyntax.TokenMinus:
+ // Minus immediately after another arithmetic operator must be negation.
+ return false
+
+ case hclsyntax.TokenEqualOp, hclsyntax.TokenNotEqual, hclsyntax.TokenGreaterThan, hclsyntax.TokenGreaterThanEq, hclsyntax.TokenLessThan, hclsyntax.TokenLessThanEq:
+ // Minus immediately after another comparison operator must be negation.
+ return false
+
+ case hclsyntax.TokenAnd, hclsyntax.TokenOr, hclsyntax.TokenBang:
+ // Minus immediately after logical operator doesn't make sense but probably intended as negation.
+ return false
+
+ default:
+ return true
+ }
+
+ case subject.Type == hclsyntax.TokenOBrace || after.Type == hclsyntax.TokenCBrace:
+ // Unlike other bracket types, braces have spaces on both sides of them,
+ // both in single-line nested blocks foo { bar = baz } and in object
+ // constructor expressions foo = { bar = baz }.
+ if subject.Type == hclsyntax.TokenOBrace && after.Type == hclsyntax.TokenCBrace {
+ // An open brace followed by a close brace is an exception, however.
+ // e.g. foo {} rather than foo { }
+ return false
+ }
+ return true
+
+ // In the unlikely event that an interpolation expression is just
+ // a single object constructor, we'll put a space between the ${ and
+ // the following { to make this more obvious, and then the same
+ // thing for the two braces at the end.
+ case (subject.Type == hclsyntax.TokenTemplateInterp || subject.Type == hclsyntax.TokenTemplateControl) && after.Type == hclsyntax.TokenOBrace:
+ return true
+ case subject.Type == hclsyntax.TokenCBrace && after.Type == hclsyntax.TokenTemplateSeqEnd:
+ return true
+
+ // Don't add spaces between interpolated items
+ case subject.Type == hclsyntax.TokenTemplateSeqEnd && (after.Type == hclsyntax.TokenTemplateInterp || after.Type == hclsyntax.TokenTemplateControl):
+ return false
+
+ case tokenBracketChange(subject) > 0:
+ // No spaces after open brackets
+ return false
+
+ case tokenBracketChange(after) < 0:
+ // No spaces before close brackets
+ return false
+
+ default:
+ // Most tokens are space-separated
+ return true
+
+ }
+}
+
+func linesForFormat(tokens Tokens) []formatLine {
+ if len(tokens) == 0 {
+ return make([]formatLine, 0)
+ }
+
+ // first we'll count our lines, so we can allocate the array for them in
+ // a single block. (We want to minimize memory pressure in this codepath,
+ // so it can be run somewhat-frequently by editor integrations.)
+ lineCount := 1 // if there are zero newlines then there is one line
+ for _, tok := range tokens {
+ if tokenIsNewline(tok) {
+ lineCount++
+ }
+ }
+
+ // To start, we'll just put everything in the "lead" cell on each line,
+ // and then do another pass over the lines afterwards to adjust.
+ lines := make([]formatLine, lineCount)
+ li := 0
+ lineStart := 0
+ for i, tok := range tokens {
+ if tok.Type == hclsyntax.TokenEOF {
+ // The EOF token doesn't belong to any line, and terminates the
+ // token sequence.
+ lines[li].lead = tokens[lineStart:i]
+ break
+ }
+
+ if tokenIsNewline(tok) {
+ lines[li].lead = tokens[lineStart : i+1]
+ lineStart = i + 1
+ li++
+ }
+ }
+
+ // If a set of tokens doesn't end in TokenEOF (e.g. because it's a
+ // fragment of tokens from the middle of a file) then we might fall
+ // out here with a line still pending.
+ if lineStart < len(tokens) {
+ lines[li].lead = tokens[lineStart:]
+ if lines[li].lead[len(lines[li].lead)-1].Type == hclsyntax.TokenEOF {
+ lines[li].lead = lines[li].lead[:len(lines[li].lead)-1]
+ }
+ }
+
+ // Now we'll pick off any trailing comments and attribute assignments
+ // to shuffle off into the "comment" and "assign" cells.
+ for i := range lines {
+ line := &lines[i]
+
+ if len(line.lead) == 0 {
+ // if the line is empty then there's nothing for us to do
+ // (this should happen only for the final line, because all other
+ // lines would have a newline token of some kind)
+ continue
+ }
+
+ if len(line.lead) > 1 && line.lead[len(line.lead)-1].Type == hclsyntax.TokenComment {
+ line.comment = line.lead[len(line.lead)-1:]
+ line.lead = line.lead[:len(line.lead)-1]
+ }
+
+ for i, tok := range line.lead {
+ if i > 0 && tok.Type == hclsyntax.TokenEqual {
+ // We only move the tokens into "assign" if the RHS seems to
+ // be a whole expression, which we determine by counting
+ // brackets. If there's a net positive number of brackets
+ // then that suggests we're introducing a multi-line expression.
+ netBrackets := 0
+ for _, token := range line.lead[i:] {
+ netBrackets += tokenBracketChange(token)
+ }
+
+ if netBrackets == 0 {
+ line.assign = line.lead[i:]
+ line.lead = line.lead[:i]
+ }
+ break
+ }
+ }
+ }
+
+ return lines
+}
+
+func tokenIsNewline(tok *Token) bool {
+ switch tok.Type {
+ case hclsyntax.TokenNewline:
+ return true
+ case hclsyntax.TokenComment:
+ // Single line tokens (# and //) consume their terminating newline,
+ // so we need to treat them as newline tokens as well.
+ if len(tok.Bytes) > 0 && tok.Bytes[len(tok.Bytes)-1] == '\n' {
+ return true
+ }
+ }
+ return false
+}
+
+func tokenBracketChange(tok *Token) int {
+ switch tok.Type {
+ case hclsyntax.TokenOBrace, hclsyntax.TokenOBrack, hclsyntax.TokenOParen, hclsyntax.TokenTemplateControl, hclsyntax.TokenTemplateInterp:
+ return 1
+ case hclsyntax.TokenCBrace, hclsyntax.TokenCBrack, hclsyntax.TokenCParen, hclsyntax.TokenTemplateSeqEnd:
+ return -1
+ default:
+ return 0
+ }
+}
+
+// formatLine represents a single line of source code for formatting purposes,
+// splitting its tokens into up to three "cells":
+//
+// - lead: always present, representing everything up to one of the others
+// - assign: if line contains an attribute assignment, represents the tokens
+// starting at (and including) the equals symbol
+// - comment: if line contains any non-comment tokens and ends with a
+// single-line comment token, represents the comment.
+//
+// When formatting, the leading spaces of the first tokens in each of these
+// cells is adjusted to align vertically their occurences on consecutive
+// rows.
+type formatLine struct {
+ lead Tokens
+ assign Tokens
+ comment Tokens
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/generate.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/generate.go
new file mode 100644
index 00000000000..678d5391337
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/generate.go
@@ -0,0 +1,399 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclwrite
+
+import (
+ "fmt"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// TokensForValue returns a sequence of tokens that represents the given
+// constant value.
+//
+// This function only supports types that are used by HCL. In particular, it
+// does not support capsule types and will panic if given one.
+//
+// It is not possible to express an unknown value in source code, so this
+// function will panic if the given value is unknown or contains any unknown
+// values. A caller can call the value's IsWhollyKnown method to verify that
+// no unknown values are present before calling TokensForValue.
+func TokensForValue(val cty.Value) Tokens {
+ toks := appendTokensForValue(val, nil)
+ format(toks) // fiddle with the SpacesBefore field to get canonical spacing
+ return toks
+}
+
+// TokensForTraversal returns a sequence of tokens that represents the given
+// traversal.
+//
+// If the traversal is absolute then the result is a self-contained, valid
+// reference expression. If the traversal is relative then the returned tokens
+// could be appended to some other expression tokens to traverse into the
+// represented expression.
+func TokensForTraversal(traversal hcl.Traversal) Tokens {
+ toks := appendTokensForTraversal(traversal, nil)
+ format(toks) // fiddle with the SpacesBefore field to get canonical spacing
+ return toks
+}
+
+// TokensForIdentifier returns a sequence of tokens representing just the
+// given identifier.
+//
+// In practice this function can only ever generate exactly one token, because
+// an identifier is always a leaf token in the syntax tree.
+//
+// This is similar to calling TokensForTraversal with a single-step absolute
+// traversal, but avoids the need to construct a separate traversal object
+// for this simple common case. If you need to generate a multi-step traversal,
+// use TokensForTraversal instead.
+func TokensForIdentifier(name string) Tokens {
+ return Tokens{
+ newIdentToken(name),
+ }
+}
+
+// TokensForTuple returns a sequence of tokens that represents a tuple
+// constructor, with element expressions populated from the given list
+// of tokens.
+//
+// TokensForTuple includes the given elements verbatim into the element
+// positions in the resulting tuple expression, without any validation to
+// ensure that they represent valid expressions. Use TokensForValue or
+// TokensForTraversal to generate valid leaf expression values, or use
+// TokensForTuple, TokensForObject, and TokensForFunctionCall to
+// generate other nested compound expressions.
+func TokensForTuple(elems []Tokens) Tokens {
+ var toks Tokens
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOBrack,
+ Bytes: []byte{'['},
+ })
+ for index, elem := range elems {
+ if index > 0 {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenComma,
+ Bytes: []byte{','},
+ })
+ }
+ toks = append(toks, elem...)
+ }
+
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCBrack,
+ Bytes: []byte{']'},
+ })
+
+ format(toks) // fiddle with the SpacesBefore field to get canonical spacing
+ return toks
+}
+
+// TokensForObject returns a sequence of tokens that represents an object
+// constructor, with attribute name/value pairs populated from the given
+// list of attribute token objects.
+//
+// TokensForObject includes the given tokens verbatim into the name and
+// value positions in the resulting object expression, without any validation
+// to ensure that they represent valid expressions. Use TokensForValue or
+// TokensForTraversal to generate valid leaf expression values, or use
+// TokensForTuple, TokensForObject, and TokensForFunctionCall to
+// generate other nested compound expressions.
+//
+// Note that HCL requires placing a traversal expression in parentheses if
+// you intend to use it as an attribute name expression, because otherwise
+// the parser will interpret it as a literal attribute name. TokensForObject
+// does not handle that situation automatically, so a caller must add the
+// necessary `TokenOParen` and TokenCParen` manually if needed.
+func TokensForObject(attrs []ObjectAttrTokens) Tokens {
+ var toks Tokens
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOBrace,
+ Bytes: []byte{'{'},
+ })
+ if len(attrs) > 0 {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenNewline,
+ Bytes: []byte{'\n'},
+ })
+ }
+ for _, attr := range attrs {
+ toks = append(toks, attr.Name...)
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenEqual,
+ Bytes: []byte{'='},
+ })
+ toks = append(toks, attr.Value...)
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenNewline,
+ Bytes: []byte{'\n'},
+ })
+ }
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCBrace,
+ Bytes: []byte{'}'},
+ })
+
+ format(toks) // fiddle with the SpacesBefore field to get canonical spacing
+ return toks
+}
+
+// TokensForFunctionCall returns a sequence of tokens that represents call
+// to the function with the given name, using the argument tokens to
+// populate the argument expressions.
+//
+// TokensForFunctionCall includes the given argument tokens verbatim into the
+// positions in the resulting call expression, without any validation
+// to ensure that they represent valid expressions. Use TokensForValue or
+// TokensForTraversal to generate valid leaf expression values, or use
+// TokensForTuple, TokensForObject, and TokensForFunctionCall to
+// generate other nested compound expressions.
+//
+// This function doesn't include an explicit way to generate the expansion
+// symbol "..." on the final argument. Currently, generating that requires
+// manually appending a TokenEllipsis with the bytes "..." to the tokens for
+// the final argument.
+func TokensForFunctionCall(funcName string, args ...Tokens) Tokens {
+ var toks Tokens
+ toks = append(toks, TokensForIdentifier(funcName)...)
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOParen,
+ Bytes: []byte{'('},
+ })
+ for index, arg := range args {
+ if index > 0 {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenComma,
+ Bytes: []byte{','},
+ })
+ }
+ toks = append(toks, arg...)
+ }
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCParen,
+ Bytes: []byte{')'},
+ })
+
+ format(toks) // fiddle with the SpacesBefore field to get canonical spacing
+ return toks
+}
+
+func appendTokensForValue(val cty.Value, toks Tokens) Tokens {
+ switch {
+
+ case !val.IsKnown():
+ panic("cannot produce tokens for unknown value")
+
+ case val.IsNull():
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: []byte(`null`),
+ })
+
+ case val.Type() == cty.Bool:
+ var src []byte
+ if val.True() {
+ src = []byte(`true`)
+ } else {
+ src = []byte(`false`)
+ }
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: src,
+ })
+
+ case val.Type() == cty.Number:
+ bf := val.AsBigFloat()
+ srcStr := bf.Text('f', -1)
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenNumberLit,
+ Bytes: []byte(srcStr),
+ })
+
+ case val.Type() == cty.String:
+ // TODO: If it's a multi-line string ending in a newline, format
+ // it as a HEREDOC instead.
+ src := escapeQuotedStringLit(val.AsString())
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOQuote,
+ Bytes: []byte{'"'},
+ })
+ if len(src) > 0 {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenQuotedLit,
+ Bytes: src,
+ })
+ }
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCQuote,
+ Bytes: []byte{'"'},
+ })
+
+ case val.Type().IsListType() || val.Type().IsSetType() || val.Type().IsTupleType():
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOBrack,
+ Bytes: []byte{'['},
+ })
+
+ i := 0
+ for it := val.ElementIterator(); it.Next(); {
+ if i > 0 {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenComma,
+ Bytes: []byte{','},
+ })
+ }
+ _, eVal := it.Element()
+ toks = appendTokensForValue(eVal, toks)
+ i++
+ }
+
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCBrack,
+ Bytes: []byte{']'},
+ })
+
+ case val.Type().IsMapType() || val.Type().IsObjectType():
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOBrace,
+ Bytes: []byte{'{'},
+ })
+ if val.LengthInt() > 0 {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenNewline,
+ Bytes: []byte{'\n'},
+ })
+ }
+
+ i := 0
+ for it := val.ElementIterator(); it.Next(); {
+ eKey, eVal := it.Element()
+ if hclsyntax.ValidIdentifier(eKey.AsString()) {
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: []byte(eKey.AsString()),
+ })
+ } else {
+ toks = appendTokensForValue(eKey, toks)
+ }
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenEqual,
+ Bytes: []byte{'='},
+ })
+ toks = appendTokensForValue(eVal, toks)
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenNewline,
+ Bytes: []byte{'\n'},
+ })
+ i++
+ }
+
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCBrace,
+ Bytes: []byte{'}'},
+ })
+
+ default:
+ panic(fmt.Sprintf("cannot produce tokens for %#v", val))
+ }
+
+ return toks
+}
+
+func appendTokensForTraversal(traversal hcl.Traversal, toks Tokens) Tokens {
+ for _, step := range traversal {
+ toks = appendTokensForTraversalStep(step, toks)
+ }
+ return toks
+}
+
+func appendTokensForTraversalStep(step hcl.Traverser, toks Tokens) Tokens {
+ switch ts := step.(type) {
+ case hcl.TraverseRoot:
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: []byte(ts.Name),
+ })
+ case hcl.TraverseAttr:
+ toks = append(
+ toks,
+ &Token{
+ Type: hclsyntax.TokenDot,
+ Bytes: []byte{'.'},
+ },
+ &Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: []byte(ts.Name),
+ },
+ )
+ case hcl.TraverseIndex:
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenOBrack,
+ Bytes: []byte{'['},
+ })
+ toks = appendTokensForValue(ts.Key, toks)
+ toks = append(toks, &Token{
+ Type: hclsyntax.TokenCBrack,
+ Bytes: []byte{']'},
+ })
+ default:
+ panic(fmt.Sprintf("unsupported traversal step type %T", step))
+ }
+
+ return toks
+}
+
+func escapeQuotedStringLit(s string) []byte {
+ if len(s) == 0 {
+ return nil
+ }
+ buf := make([]byte, 0, len(s))
+ for i, r := range s {
+ switch r {
+ case '\n':
+ buf = append(buf, '\\', 'n')
+ case '\r':
+ buf = append(buf, '\\', 'r')
+ case '\t':
+ buf = append(buf, '\\', 't')
+ case '"':
+ buf = append(buf, '\\', '"')
+ case '\\':
+ buf = append(buf, '\\', '\\')
+ case '$', '%':
+ buf = appendRune(buf, r)
+ remain := s[i+1:]
+ if len(remain) > 0 && remain[0] == '{' {
+ // Double up our template introducer symbol to escape it.
+ buf = appendRune(buf, r)
+ }
+ default:
+ if !unicode.IsPrint(r) {
+ var fmted string
+ if r < 65536 {
+ fmted = fmt.Sprintf("\\u%04x", r)
+ } else {
+ fmted = fmt.Sprintf("\\U%08x", r)
+ }
+ buf = append(buf, fmted...)
+ } else {
+ buf = appendRune(buf, r)
+ }
+ }
+ }
+ return buf
+}
+
+func appendRune(b []byte, r rune) []byte {
+ l := utf8.RuneLen(r)
+ for i := 0; i < l; i++ {
+ b = append(b, 0) // make room at the end of our buffer
+ }
+ ch := b[len(b)-l:]
+ utf8.EncodeRune(ch, r)
+ return b
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/native_node_sorter.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/native_node_sorter.go
new file mode 100644
index 00000000000..0a78683bd78
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/native_node_sorter.go
@@ -0,0 +1,26 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclwrite
+
+import (
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+)
+
+type nativeNodeSorter struct {
+ Nodes []hclsyntax.Node
+}
+
+func (s nativeNodeSorter) Len() int {
+ return len(s.Nodes)
+}
+
+func (s nativeNodeSorter) Less(i, j int) bool {
+ rangeI := s.Nodes[i].Range()
+ rangeJ := s.Nodes[j].Range()
+ return rangeI.Start.Byte < rangeJ.Start.Byte
+}
+
+func (s nativeNodeSorter) Swap(i, j int) {
+ s.Nodes[i], s.Nodes[j] = s.Nodes[j], s.Nodes[i]
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/node.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/node.go
new file mode 100644
index 00000000000..7ad4bb91f4e
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/node.go
@@ -0,0 +1,299 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclwrite
+
+import (
+ "fmt"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+// node represents a node in the AST.
+type node struct {
+ content nodeContent
+
+ list *nodes
+ before, after *node
+}
+
+func newNode(c nodeContent) *node {
+ return &node{
+ content: c,
+ }
+}
+
+func (n *node) Equal(other *node) bool {
+ return cmp.Equal(n.content, other.content)
+}
+
+func (n *node) BuildTokens(to Tokens) Tokens {
+ return n.content.BuildTokens(to)
+}
+
+// Detach removes the receiver from the list it currently belongs to. If the
+// node is not currently in a list, this is a no-op.
+func (n *node) Detach() {
+ if n.list == nil {
+ return
+ }
+ if n.before != nil {
+ n.before.after = n.after
+ }
+ if n.after != nil {
+ n.after.before = n.before
+ }
+ if n.list.first == n {
+ n.list.first = n.after
+ }
+ if n.list.last == n {
+ n.list.last = n.before
+ }
+ n.list = nil
+ n.before = nil
+ n.after = nil
+}
+
+// ReplaceWith removes the receiver from the list it currently belongs to and
+// inserts a new node with the given content in its place. If the node is not
+// currently in a list, this function will panic.
+//
+// The return value is the newly-constructed node, containing the given content.
+// After this function returns, the reciever is no longer attached to a list.
+func (n *node) ReplaceWith(c nodeContent) *node {
+ if n.list == nil {
+ panic("can't replace node that is not in a list")
+ }
+
+ before := n.before
+ after := n.after
+ list := n.list
+ n.before, n.after, n.list = nil, nil, nil
+
+ nn := newNode(c)
+ nn.before = before
+ nn.after = after
+ nn.list = list
+ if before != nil {
+ before.after = nn
+ }
+ if after != nil {
+ after.before = nn
+ }
+ return nn
+}
+
+func (n *node) assertUnattached() {
+ if n.list != nil {
+ panic(fmt.Sprintf("attempt to attach already-attached node %#v", n))
+ }
+}
+
+// nodeContent is the interface type implemented by all AST content types.
+type nodeContent interface {
+ walkChildNodes(w internalWalkFunc)
+ BuildTokens(to Tokens) Tokens
+}
+
+// nodes is a list of nodes.
+type nodes struct {
+ first, last *node
+}
+
+func (ns *nodes) BuildTokens(to Tokens) Tokens {
+ for n := ns.first; n != nil; n = n.after {
+ to = n.BuildTokens(to)
+ }
+ return to
+}
+
+func (ns *nodes) Clear() {
+ ns.first = nil
+ ns.last = nil
+}
+
+func (ns *nodes) Append(c nodeContent) *node {
+ n := &node{
+ content: c,
+ }
+ ns.AppendNode(n)
+ n.list = ns
+ return n
+}
+
+func (ns *nodes) AppendNode(n *node) {
+ if ns.last != nil {
+ n.before = ns.last
+ ns.last.after = n
+ }
+ n.list = ns
+ ns.last = n
+ if ns.first == nil {
+ ns.first = n
+ }
+}
+
+// Insert inserts a nodeContent at a given position.
+// This is just a wrapper for InsertNode. See InsertNode for details.
+func (ns *nodes) Insert(pos *node, c nodeContent) *node {
+ n := &node{
+ content: c,
+ }
+ ns.InsertNode(pos, n)
+ n.list = ns
+ return n
+}
+
+// InsertNode inserts a node at a given position.
+// The first argument is a node reference before which to insert.
+// To insert it to an empty list, set position to nil.
+func (ns *nodes) InsertNode(pos *node, n *node) {
+ if pos == nil {
+ // inserts n to empty list.
+ ns.first = n
+ ns.last = n
+ } else {
+ // inserts n before pos.
+ pos.before.after = n
+ n.before = pos.before
+ pos.before = n
+ n.after = pos
+ }
+
+ n.list = ns
+}
+
+func (ns *nodes) AppendUnstructuredTokens(tokens Tokens) *node {
+ if len(tokens) == 0 {
+ return nil
+ }
+ n := newNode(tokens)
+ ns.AppendNode(n)
+ n.list = ns
+ return n
+}
+
+// FindNodeWithContent searches the nodes for a node whose content equals
+// the given content. If it finds one then it returns it. Otherwise it returns
+// nil.
+func (ns *nodes) FindNodeWithContent(content nodeContent) *node {
+ for n := ns.first; n != nil; n = n.after {
+ if n.content == content {
+ return n
+ }
+ }
+ return nil
+}
+
+// nodeSet is an unordered set of nodes. It is used to describe a set of nodes
+// that all belong to the same list that have some role or characteristic
+// in common.
+type nodeSet map[*node]struct{}
+
+func newNodeSet() nodeSet {
+ return make(nodeSet)
+}
+
+func (ns nodeSet) Has(n *node) bool {
+ if ns == nil {
+ return false
+ }
+ _, exists := ns[n]
+ return exists
+}
+
+func (ns nodeSet) Add(n *node) {
+ ns[n] = struct{}{}
+}
+
+func (ns nodeSet) Remove(n *node) {
+ delete(ns, n)
+}
+
+func (ns nodeSet) Clear() {
+ for n := range ns {
+ delete(ns, n)
+ }
+}
+
+func (ns nodeSet) List() []*node {
+ if len(ns) == 0 {
+ return nil
+ }
+
+ ret := make([]*node, 0, len(ns))
+
+ // Determine which list we are working with. We assume here that all of
+ // the nodes belong to the same list, since that is part of the contract
+ // for nodeSet.
+ var list *nodes
+ for n := range ns {
+ list = n.list
+ break
+ }
+
+ // We recover the order by iterating over the whole list. This is not
+ // the most efficient way to do it, but our node lists should always be
+ // small so not worth making things more complex.
+ for n := list.first; n != nil; n = n.after {
+ if ns.Has(n) {
+ ret = append(ret, n)
+ }
+ }
+ return ret
+}
+
+// FindNodeWithContent searches the nodes for a node whose content equals
+// the given content. If it finds one then it returns it. Otherwise it returns
+// nil.
+func (ns nodeSet) FindNodeWithContent(content nodeContent) *node {
+ for n := range ns {
+ if n.content == content {
+ return n
+ }
+ }
+ return nil
+}
+
+type internalWalkFunc func(*node)
+
+// inTree can be embedded into a content struct that has child nodes to get
+// a standard implementation of the NodeContent interface and a record of
+// a potential parent node.
+type inTree struct {
+ parent *node
+ children *nodes
+}
+
+func newInTree() inTree {
+ return inTree{
+ children: &nodes{},
+ }
+}
+
+func (it *inTree) assertUnattached() {
+ if it.parent != nil {
+ panic(fmt.Sprintf("node is already attached to %T", it.parent.content))
+ }
+}
+
+func (it *inTree) walkChildNodes(w internalWalkFunc) {
+ for n := it.children.first; n != nil; n = n.after {
+ w(n)
+ }
+}
+
+func (it *inTree) BuildTokens(to Tokens) Tokens {
+ for n := it.children.first; n != nil; n = n.after {
+ to = n.BuildTokens(to)
+ }
+ return to
+}
+
+// leafNode can be embedded into a content struct to give it a do-nothing
+// implementation of walkChildNodes
+type leafNode struct {
+}
+
+func (n *leafNode) walkChildNodes(w internalWalkFunc) {
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/parser.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/parser.go
new file mode 100644
index 00000000000..4042b3a52a6
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/parser.go
@@ -0,0 +1,641 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclwrite
+
+import (
+ "fmt"
+ "sort"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// Our "parser" here is actually not doing any parsing of its own. Instead,
+// it leans on the native parser in hclsyntax, and then uses the source ranges
+// from the AST to partition the raw token sequence to match the raw tokens
+// up to AST nodes.
+//
+// This strategy feels somewhat counter-intuitive, since most of the work the
+// parser does is thrown away here, but this strategy is chosen because the
+// normal parsing work done by hclsyntax is considered to be the "main case",
+// while modifying and re-printing source is more of an edge case, used only
+// in ancillary tools, and so it's good to keep all the main parsing logic
+// with the main case but keep all of the extra complexity of token wrangling
+// out of the main parser, which is already rather complex just serving the
+// use-cases it already serves.
+//
+// If the parsing step produces any errors, the returned File is nil because
+// we can't reliably extract tokens from the partial AST produced by an
+// erroneous parse.
+func parse(src []byte, filename string, start hcl.Pos) (*File, hcl.Diagnostics) {
+ file, diags := hclsyntax.ParseConfig(src, filename, start)
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ // To do our work here, we use the "native" tokens (those from hclsyntax)
+ // to match against source ranges in the AST, but ultimately produce
+ // slices from our sequence of "writer" tokens, which contain only
+ // *relative* position information that is more appropriate for
+ // transformation/writing use-cases.
+ nativeTokens, diags := hclsyntax.LexConfig(src, filename, start)
+ if diags.HasErrors() {
+ // should never happen, since we would've caught these diags in
+ // the first call above.
+ return nil, diags
+ }
+ writerTokens := writerTokens(nativeTokens)
+
+ from := inputTokens{
+ nativeTokens: nativeTokens,
+ writerTokens: writerTokens,
+ }
+
+ before, root, after := parseBody(file.Body.(*hclsyntax.Body), from)
+ ret := &File{
+ inTree: newInTree(),
+
+ srcBytes: src,
+ body: root,
+ }
+
+ nodes := ret.children
+ nodes.Append(before.Tokens())
+ nodes.AppendNode(root)
+ nodes.Append(after.Tokens())
+
+ return ret, diags
+}
+
+type inputTokens struct {
+ nativeTokens hclsyntax.Tokens
+ writerTokens Tokens
+}
+
+func (it inputTokens) Partition(rng hcl.Range) (before, within, after inputTokens) {
+ start, end := partitionTokens(it.nativeTokens, rng)
+ before = it.Slice(0, start)
+ within = it.Slice(start, end)
+ after = it.Slice(end, len(it.nativeTokens))
+ return
+}
+
+func (it inputTokens) PartitionType(ty hclsyntax.TokenType) (before, within, after inputTokens) {
+ for i, t := range it.writerTokens {
+ if t.Type == ty {
+ return it.Slice(0, i), it.Slice(i, i+1), it.Slice(i+1, len(it.nativeTokens))
+ }
+ }
+ panic(fmt.Sprintf("didn't find any token of type %s", ty))
+}
+
+func (it inputTokens) PartitionTypeOk(ty hclsyntax.TokenType) (before, within, after inputTokens, ok bool) {
+ for i, t := range it.writerTokens {
+ if t.Type == ty {
+ return it.Slice(0, i), it.Slice(i, i+1), it.Slice(i+1, len(it.nativeTokens)), true
+ }
+ }
+
+ return inputTokens{}, inputTokens{}, inputTokens{}, false
+}
+
+func (it inputTokens) PartitionTypeSingle(ty hclsyntax.TokenType) (before inputTokens, found *Token, after inputTokens) {
+ before, within, after := it.PartitionType(ty)
+ if within.Len() != 1 {
+ panic("PartitionType found more than one token")
+ }
+ return before, within.Tokens()[0], after
+}
+
+// PartitionIncludeComments is like Partition except the returned "within"
+// range includes any lead and line comments associated with the range.
+func (it inputTokens) PartitionIncludingComments(rng hcl.Range) (before, within, after inputTokens) {
+ start, end := partitionTokens(it.nativeTokens, rng)
+ start = partitionLeadCommentTokens(it.nativeTokens[:start])
+ _, afterNewline := partitionLineEndTokens(it.nativeTokens[end:])
+ end += afterNewline
+
+ before = it.Slice(0, start)
+ within = it.Slice(start, end)
+ after = it.Slice(end, len(it.nativeTokens))
+ return
+
+}
+
+// PartitionBlockItem is similar to PartitionIncludeComments but it returns
+// the comments as separate token sequences so that they can be captured into
+// AST attributes. It makes assumptions that apply only to block items, so
+// should not be used for other constructs.
+func (it inputTokens) PartitionBlockItem(rng hcl.Range) (before, leadComments, within, lineComments, newline, after inputTokens) {
+ before, within, after = it.Partition(rng)
+ before, leadComments = before.PartitionLeadComments()
+ lineComments, newline, after = after.PartitionLineEndTokens()
+ return
+}
+
+func (it inputTokens) PartitionLeadComments() (before, within inputTokens) {
+ start := partitionLeadCommentTokens(it.nativeTokens)
+ before = it.Slice(0, start)
+ within = it.Slice(start, len(it.nativeTokens))
+ return
+}
+
+func (it inputTokens) PartitionLineEndTokens() (comments, newline, after inputTokens) {
+ afterComments, afterNewline := partitionLineEndTokens(it.nativeTokens)
+ comments = it.Slice(0, afterComments)
+ newline = it.Slice(afterComments, afterNewline)
+ after = it.Slice(afterNewline, len(it.nativeTokens))
+ return
+}
+
+func (it inputTokens) Slice(start, end int) inputTokens {
+ // When we slice, we create a new slice with no additional capacity because
+ // we expect that these slices will be mutated in order to insert
+ // new code into the AST, and we want to ensure that a new underlying
+ // array gets allocated in that case, rather than writing into some
+ // following slice and corrupting it.
+ return inputTokens{
+ nativeTokens: it.nativeTokens[start:end:end],
+ writerTokens: it.writerTokens[start:end:end],
+ }
+}
+
+func (it inputTokens) Len() int {
+ return len(it.nativeTokens)
+}
+
+func (it inputTokens) Tokens() Tokens {
+ return it.writerTokens
+}
+
+func (it inputTokens) Types() []hclsyntax.TokenType {
+ ret := make([]hclsyntax.TokenType, len(it.nativeTokens))
+ for i, tok := range it.nativeTokens {
+ ret[i] = tok.Type
+ }
+ return ret
+}
+
+// parseBody locates the given body within the given input tokens and returns
+// the resulting *Body object as well as the tokens that appeared before and
+// after it.
+func parseBody(nativeBody *hclsyntax.Body, from inputTokens) (inputTokens, *node, inputTokens) {
+ before, within, after := from.PartitionIncludingComments(nativeBody.SrcRange)
+
+ // The main AST doesn't retain the original source ordering of the
+ // body items, so we need to reconstruct that ordering by inspecting
+ // their source ranges.
+ nativeItems := make([]hclsyntax.Node, 0, len(nativeBody.Attributes)+len(nativeBody.Blocks))
+ for _, nativeAttr := range nativeBody.Attributes {
+ nativeItems = append(nativeItems, nativeAttr)
+ }
+ for _, nativeBlock := range nativeBody.Blocks {
+ nativeItems = append(nativeItems, nativeBlock)
+ }
+ sort.Sort(nativeNodeSorter{nativeItems})
+
+ body := &Body{
+ inTree: newInTree(),
+ items: newNodeSet(),
+ }
+
+ remain := within
+ for _, nativeItem := range nativeItems {
+ beforeItem, item, afterItem := parseBodyItem(nativeItem, remain)
+
+ if beforeItem.Len() > 0 {
+ body.AppendUnstructuredTokens(beforeItem.Tokens())
+ }
+ body.appendItemNode(item)
+
+ remain = afterItem
+ }
+
+ if remain.Len() > 0 {
+ body.AppendUnstructuredTokens(remain.Tokens())
+ }
+
+ return before, newNode(body), after
+}
+
+func parseBodyItem(nativeItem hclsyntax.Node, from inputTokens) (inputTokens, *node, inputTokens) {
+ before, leadComments, within, lineComments, newline, after := from.PartitionBlockItem(nativeItem.Range())
+
+ var item *node
+
+ switch tItem := nativeItem.(type) {
+ case *hclsyntax.Attribute:
+ item = parseAttribute(tItem, within, leadComments, lineComments, newline)
+ case *hclsyntax.Block:
+ item = parseBlock(tItem, within, leadComments, lineComments, newline)
+ default:
+ // should never happen if caller is behaving
+ panic("unsupported native item type")
+ }
+
+ return before, item, after
+}
+
+func parseAttribute(nativeAttr *hclsyntax.Attribute, from, leadComments, lineComments, newline inputTokens) *node {
+ attr := &Attribute{
+ inTree: newInTree(),
+ }
+ children := attr.children
+
+ {
+ cn := newNode(newComments(leadComments.Tokens()))
+ attr.leadComments = cn
+ children.AppendNode(cn)
+ }
+
+ before, nameTokens, from := from.Partition(nativeAttr.NameRange)
+ {
+ children.AppendUnstructuredTokens(before.Tokens())
+ if nameTokens.Len() != 1 {
+ // Should never happen with valid input
+ panic("attribute name is not exactly one token")
+ }
+ token := nameTokens.Tokens()[0]
+ in := newNode(newIdentifier(token))
+ attr.name = in
+ children.AppendNode(in)
+ }
+
+ before, equalsTokens, from := from.Partition(nativeAttr.EqualsRange)
+ children.AppendUnstructuredTokens(before.Tokens())
+ children.AppendUnstructuredTokens(equalsTokens.Tokens())
+
+ before, exprTokens, from := from.Partition(nativeAttr.Expr.Range())
+ {
+ children.AppendUnstructuredTokens(before.Tokens())
+ exprNode := parseExpression(nativeAttr.Expr, exprTokens)
+ attr.expr = exprNode
+ children.AppendNode(exprNode)
+ }
+
+ {
+ cn := newNode(newComments(lineComments.Tokens()))
+ attr.lineComments = cn
+ children.AppendNode(cn)
+ }
+
+ children.AppendUnstructuredTokens(newline.Tokens())
+
+ // Collect any stragglers, though there shouldn't be any
+ children.AppendUnstructuredTokens(from.Tokens())
+
+ return newNode(attr)
+}
+
+func parseBlock(nativeBlock *hclsyntax.Block, from, leadComments, lineComments, newline inputTokens) *node {
+ block := &Block{
+ inTree: newInTree(),
+ }
+ children := block.children
+
+ {
+ cn := newNode(newComments(leadComments.Tokens()))
+ block.leadComments = cn
+ children.AppendNode(cn)
+ }
+
+ before, typeTokens, from := from.Partition(nativeBlock.TypeRange)
+ {
+ children.AppendUnstructuredTokens(before.Tokens())
+ if typeTokens.Len() != 1 {
+ // Should never happen with valid input
+ panic("block type name is not exactly one token")
+ }
+ token := typeTokens.Tokens()[0]
+ in := newNode(newIdentifier(token))
+ block.typeName = in
+ children.AppendNode(in)
+ }
+
+ _, labelsNode, from := parseBlockLabels(nativeBlock, from)
+ block.labels = labelsNode
+ children.AppendNode(labelsNode)
+
+ before, oBrace, from := from.Partition(nativeBlock.OpenBraceRange)
+ children.AppendUnstructuredTokens(before.Tokens())
+ block.open = children.AppendUnstructuredTokens(oBrace.Tokens())
+
+ // We go a bit out of order here: we go hunting for the closing brace
+ // so that we have a delimited body, but then we'll deal with the body
+ // before we actually append the closing brace and any straggling tokens
+ // that appear after it.
+ bodyTokens, cBrace, from := from.Partition(nativeBlock.CloseBraceRange)
+ before, body, after := parseBody(nativeBlock.Body, bodyTokens)
+ children.AppendUnstructuredTokens(before.Tokens())
+ block.body = body
+ children.AppendNode(body)
+ children.AppendUnstructuredTokens(after.Tokens())
+
+ block.close = children.AppendUnstructuredTokens(cBrace.Tokens())
+
+ // stragglers
+ children.AppendUnstructuredTokens(from.Tokens())
+ if lineComments.Len() > 0 {
+ // blocks don't actually have line comments, so we'll just treat
+ // them as extra stragglers
+ children.AppendUnstructuredTokens(lineComments.Tokens())
+ }
+ children.AppendUnstructuredTokens(newline.Tokens())
+
+ return newNode(block)
+}
+
+func parseBlockLabels(nativeBlock *hclsyntax.Block, from inputTokens) (inputTokens, *node, inputTokens) {
+ labelsObj := newBlockLabels(nil)
+ children := labelsObj.children
+
+ var beforeAll inputTokens
+ for i, rng := range nativeBlock.LabelRanges {
+ var before, labelTokens inputTokens
+ before, labelTokens, from = from.Partition(rng)
+ if i == 0 {
+ beforeAll = before
+ } else {
+ children.AppendUnstructuredTokens(before.Tokens())
+ }
+ tokens := labelTokens.Tokens()
+ var ln *node
+ if len(tokens) == 1 && tokens[0].Type == hclsyntax.TokenIdent {
+ ln = newNode(newIdentifier(tokens[0]))
+ } else {
+ ln = newNode(newQuoted(tokens))
+ }
+ labelsObj.items.Add(ln)
+ children.AppendNode(ln)
+ }
+
+ after := from
+ return beforeAll, newNode(labelsObj), after
+}
+
+func parseExpression(nativeExpr hclsyntax.Expression, from inputTokens) *node {
+ expr := newExpression()
+ children := expr.children
+
+ nativeVars := nativeExpr.Variables()
+
+ for _, nativeTraversal := range nativeVars {
+ before, traversal, after := parseTraversal(nativeTraversal, from)
+ children.AppendUnstructuredTokens(before.Tokens())
+ children.AppendNode(traversal)
+ expr.absTraversals.Add(traversal)
+ from = after
+ }
+ // Attach any stragglers that don't belong to a traversal to the expression
+ // itself. In an expression with no traversals at all, this is just the
+ // entirety of "from".
+ children.AppendUnstructuredTokens(from.Tokens())
+
+ return newNode(expr)
+}
+
+func parseTraversal(nativeTraversal hcl.Traversal, from inputTokens) (before inputTokens, n *node, after inputTokens) {
+ traversal := newTraversal()
+ children := traversal.children
+ before, from, after = from.Partition(nativeTraversal.SourceRange())
+
+ stepAfter := from
+ for _, nativeStep := range nativeTraversal {
+ before, step, after := parseTraversalStep(nativeStep, stepAfter)
+ children.AppendUnstructuredTokens(before.Tokens())
+ children.AppendNode(step)
+ traversal.steps.Add(step)
+ stepAfter = after
+ }
+
+ return before, newNode(traversal), after
+}
+
+func parseTraversalStep(nativeStep hcl.Traverser, from inputTokens) (before inputTokens, n *node, after inputTokens) {
+ var children *nodes
+ switch tNativeStep := nativeStep.(type) {
+
+ case hcl.TraverseRoot, hcl.TraverseAttr:
+ step := newTraverseName()
+ children = step.children
+ before, from, after = from.Partition(nativeStep.SourceRange())
+ inBefore, token, inAfter := from.PartitionTypeSingle(hclsyntax.TokenIdent)
+ name := newIdentifier(token)
+ children.AppendUnstructuredTokens(inBefore.Tokens())
+ step.name = children.Append(name)
+ children.AppendUnstructuredTokens(inAfter.Tokens())
+ return before, newNode(step), after
+
+ case hcl.TraverseIndex:
+ step := newTraverseIndex()
+ children = step.children
+ before, from, after = from.Partition(nativeStep.SourceRange())
+
+ if inBefore, dot, from, ok := from.PartitionTypeOk(hclsyntax.TokenDot); ok {
+ children.AppendUnstructuredTokens(inBefore.Tokens())
+ children.AppendUnstructuredTokens(dot.Tokens())
+
+ valBefore, valToken, valAfter := from.PartitionTypeSingle(hclsyntax.TokenNumberLit)
+ children.AppendUnstructuredTokens(valBefore.Tokens())
+ key := newNumber(valToken)
+ step.key = children.Append(key)
+ children.AppendUnstructuredTokens(valAfter.Tokens())
+
+ return before, newNode(step), after
+ }
+
+ var inBefore, oBrack, keyTokens, cBrack inputTokens
+ inBefore, oBrack, from = from.PartitionType(hclsyntax.TokenOBrack)
+ children.AppendUnstructuredTokens(inBefore.Tokens())
+ children.AppendUnstructuredTokens(oBrack.Tokens())
+ keyTokens, cBrack, from = from.PartitionType(hclsyntax.TokenCBrack)
+
+ keyVal := tNativeStep.Key
+ switch keyVal.Type() {
+ case cty.String:
+ key := newQuoted(keyTokens.Tokens())
+ step.key = children.Append(key)
+ case cty.Number:
+ valBefore, valToken, valAfter := keyTokens.PartitionTypeSingle(hclsyntax.TokenNumberLit)
+ children.AppendUnstructuredTokens(valBefore.Tokens())
+ key := newNumber(valToken)
+ step.key = children.Append(key)
+ children.AppendUnstructuredTokens(valAfter.Tokens())
+ }
+
+ children.AppendUnstructuredTokens(cBrack.Tokens())
+ children.AppendUnstructuredTokens(from.Tokens())
+
+ return before, newNode(step), after
+ default:
+ panic(fmt.Sprintf("unsupported traversal step type %T", nativeStep))
+ }
+
+}
+
+// writerTokens takes a sequence of tokens as produced by the main hclsyntax
+// package and transforms it into an equivalent sequence of tokens using
+// this package's own token model.
+//
+// The resulting list contains the same number of tokens and uses the same
+// indices as the input, allowing the two sets of tokens to be correlated
+// by index.
+func writerTokens(nativeTokens hclsyntax.Tokens) Tokens {
+ // Ultimately we want a slice of token _pointers_, but since we can
+ // predict how much memory we're going to devote to tokens we'll allocate
+ // it all as a single flat buffer and thus give the GC less work to do.
+ tokBuf := make([]Token, len(nativeTokens))
+ var lastByteOffset int
+ for i, mainToken := range nativeTokens {
+ // Create a copy of the bytes so that we can mutate without
+ // corrupting the original token stream.
+ bytes := make([]byte, len(mainToken.Bytes))
+ copy(bytes, mainToken.Bytes)
+
+ tokBuf[i] = Token{
+ Type: mainToken.Type,
+ Bytes: bytes,
+
+ // We assume here that spaces are always ASCII spaces, since
+ // that's what the scanner also assumes, and thus the number
+ // of bytes skipped is also the number of space characters.
+ SpacesBefore: mainToken.Range.Start.Byte - lastByteOffset,
+ }
+
+ lastByteOffset = mainToken.Range.End.Byte
+ }
+
+ // Now make a slice of pointers into the previous slice.
+ ret := make(Tokens, len(tokBuf))
+ for i := range ret {
+ ret[i] = &tokBuf[i]
+ }
+
+ return ret
+}
+
+// partitionTokens takes a sequence of tokens and a hcl.Range and returns
+// two indices within the token sequence that correspond with the range
+// boundaries, such that the slice operator could be used to produce
+// three token sequences for before, within, and after respectively:
+//
+// start, end := partitionTokens(toks, rng)
+// before := toks[:start]
+// within := toks[start:end]
+// after := toks[end:]
+//
+// This works best when the range is aligned with token boundaries (e.g.
+// because it was produced in terms of the scanner's result) but if that isn't
+// true then it will make a best effort that may produce strange results at
+// the boundaries.
+//
+// Native hclsyntax tokens are used here, because they contain the necessary
+// absolute position information. However, since writerTokens produces a
+// correlatable sequence of writer tokens, the resulting indices can be
+// used also to index into its result, allowing the partitioning of writer
+// tokens to be driven by the partitioning of native tokens.
+//
+// The tokens are assumed to be in source order and non-overlapping, which
+// will be true if the token sequence from the scanner is used directly.
+func partitionTokens(toks hclsyntax.Tokens, rng hcl.Range) (start, end int) {
+ // We use a linear search here because we assume that in most cases our
+ // target range is close to the beginning of the sequence, and the sequences
+ // are generally small for most reasonable files anyway.
+ for i := 0; ; i++ {
+ if i >= len(toks) {
+ // No tokens for the given range at all!
+ return len(toks), len(toks)
+ }
+
+ if toks[i].Range.Start.Byte >= rng.Start.Byte {
+ start = i
+ break
+ }
+ }
+
+ for i := start; ; i++ {
+ if i >= len(toks) {
+ // The range "hangs off" the end of the token sequence
+ return start, len(toks)
+ }
+
+ if toks[i].Range.Start.Byte >= rng.End.Byte {
+ end = i // end marker is exclusive
+ break
+ }
+ }
+
+ return start, end
+}
+
+// partitionLeadCommentTokens takes a sequence of tokens that is assumed
+// to immediately precede a construct that can have lead comment tokens,
+// and returns the index into that sequence where the lead comments begin.
+//
+// Lead comments are defined as whole lines containing only comment tokens
+// with no blank lines between. If no such lines are found, the returned
+// index will be len(toks).
+func partitionLeadCommentTokens(toks hclsyntax.Tokens) int {
+ // single-line comments (which is what we're interested in here)
+ // consume their trailing newline, so we can just walk backwards
+ // until we stop seeing comment tokens.
+ for i := len(toks) - 1; i >= 0; i-- {
+ if toks[i].Type != hclsyntax.TokenComment {
+ return i + 1
+ }
+ }
+ return 0
+}
+
+// partitionLineEndTokens takes a sequence of tokens that is assumed
+// to immediately follow a construct that can have a line comment, and
+// returns first the index where any line comments end and then second
+// the index immediately after the trailing newline.
+//
+// Line comments are defined as comments that appear immediately after
+// a construct on the same line where its significant tokens ended.
+//
+// Since single-line comment tokens (# and //) include the newline that
+// terminates them, in the presence of these the two returned indices
+// will be the same since the comment itself serves as the line end.
+func partitionLineEndTokens(toks hclsyntax.Tokens) (afterComment, afterNewline int) {
+ for i := 0; i < len(toks); i++ {
+ tok := toks[i]
+ if tok.Type != hclsyntax.TokenComment {
+ switch tok.Type {
+ case hclsyntax.TokenNewline:
+ return i, i + 1
+ case hclsyntax.TokenEOF:
+ // Although this is valid, we mustn't include the EOF
+ // itself as our "newline" or else strange things will
+ // happen when we try to append new items.
+ return i, i
+ default:
+ // If we have well-formed input here then nothing else should be
+ // possible. This path should never happen, because we only try
+ // to extract tokens from the sequence if the parser succeeded,
+ // and it should catch this problem itself.
+ panic("malformed line trailers: expected only comments and newlines")
+ }
+ }
+
+ if len(tok.Bytes) > 0 && tok.Bytes[len(tok.Bytes)-1] == '\n' {
+ // Newline at the end of a single-line comment serves both as
+ // the end of comments *and* the end of the line.
+ return i + 1, i + 1
+ }
+ }
+ return len(toks), len(toks)
+}
+
+// lexConfig uses the hclsyntax scanner to get a token stream and then
+// rewrites it into this package's token model.
+//
+// Any errors produced during scanning are ignored, so the results of this
+// function should be used with care.
+func lexConfig(src []byte) Tokens {
+ mainTokens, _ := hclsyntax.LexConfig(src, "", hcl.Pos{Byte: 0, Line: 1, Column: 1})
+ return writerTokens(mainTokens)
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/public.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/public.go
new file mode 100644
index 00000000000..b65e039efa9
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/public.go
@@ -0,0 +1,48 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclwrite
+
+import (
+ "bytes"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// NewFile creates a new file object that is empty and ready to have constructs
+// added t it.
+func NewFile() *File {
+ body := &Body{
+ inTree: newInTree(),
+ items: newNodeSet(),
+ }
+ file := &File{
+ inTree: newInTree(),
+ }
+ file.body = file.children.Append(body)
+ return file
+}
+
+// ParseConfig interprets the given source bytes into a *hclwrite.File. The
+// resulting AST can be used to perform surgical edits on the source code
+// before turning it back into bytes again.
+func ParseConfig(src []byte, filename string, start hcl.Pos) (*File, hcl.Diagnostics) {
+ return parse(src, filename, start)
+}
+
+// Format takes source code and performs simple whitespace changes to transform
+// it to a canonical layout style.
+//
+// Format skips constructing an AST and works directly with tokens, so it
+// is less expensive than formatting via the AST for situations where no other
+// changes will be made. It also ignores syntax errors and can thus be applied
+// to partial source code, although the result in that case may not be
+// desirable.
+func Format(src []byte) []byte {
+ tokens := lexConfig(src)
+ format(tokens)
+ buf := &bytes.Buffer{}
+ //nolint:errcheck // FIXME: Propogate errors upward.
+ tokens.WriteTo(buf)
+ return buf.Bytes()
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/tokens.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/tokens.go
new file mode 100644
index 00000000000..d7f09290020
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/hclwrite/tokens.go
@@ -0,0 +1,136 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hclwrite
+
+import (
+ "bytes"
+ "io"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+)
+
+// Token is a single sequence of bytes annotated with a type. It is similar
+// in purpose to hclsyntax.Token, but discards the source position information
+// since that is not useful in code generation.
+type Token struct {
+ Type hclsyntax.TokenType
+ Bytes []byte
+
+ // We record the number of spaces before each token so that we can
+ // reproduce the exact layout of the original file when we're making
+ // surgical changes in-place. When _new_ code is created it will always
+ // be in the canonical style, but we preserve layout of existing code.
+ SpacesBefore int
+}
+
+// asHCLSyntax returns the receiver expressed as an incomplete hclsyntax.Token.
+// A complete token is not possible since we don't have source location
+// information here, and so this method is unexported so we can be sure it will
+// only be used for internal purposes where we know the range isn't important.
+//
+// This is primarily intended to allow us to re-use certain functionality from
+// hclsyntax rather than re-implementing it against our own token type here.
+func (t *Token) asHCLSyntax() hclsyntax.Token {
+ return hclsyntax.Token{
+ Type: t.Type,
+ Bytes: t.Bytes,
+ Range: hcl.Range{
+ Filename: "",
+ },
+ }
+}
+
+// Tokens is a flat list of tokens.
+type Tokens []*Token
+
+func (ts Tokens) Bytes() []byte {
+ buf := &bytes.Buffer{}
+ //nolint:errcheck // FIXME: Propogate errors upward.
+ ts.WriteTo(buf)
+ return buf.Bytes()
+}
+
+func (ts Tokens) testValue() string {
+ return string(ts.Bytes())
+}
+
+// Columns returns the number of columns (grapheme clusters) the token sequence
+// occupies. The result is not meaningful if there are newline or single-line
+// comment tokens in the sequence.
+func (ts Tokens) Columns() int {
+ ret := 0
+ for _, token := range ts {
+ ret += token.SpacesBefore // spaces are always worth one column each
+ ct, _ := textseg.TokenCount(token.Bytes, textseg.ScanGraphemeClusters)
+ ret += ct
+ }
+ return ret
+}
+
+// WriteTo takes an io.Writer and writes the bytes for each token to it,
+// along with the spacing that separates each token. In other words, this
+// allows serializing the tokens to a file or other such byte stream.
+func (ts Tokens) WriteTo(wr io.Writer) (int64, error) {
+ // We know we're going to be writing a lot of small chunks of repeated
+ // space characters, so we'll prepare a buffer of these that we can
+ // easily pass to wr.Write without any further allocation.
+ spaces := make([]byte, 40)
+ for i := range spaces {
+ spaces[i] = ' '
+ }
+
+ var n int64
+ var err error
+ for _, token := range ts {
+ if err != nil {
+ return n, err
+ }
+
+ for spacesBefore := token.SpacesBefore; spacesBefore > 0; spacesBefore -= len(spaces) {
+ thisChunk := spacesBefore
+ if thisChunk > len(spaces) {
+ thisChunk = len(spaces)
+ }
+ var thisN int
+ thisN, err = wr.Write(spaces[:thisChunk])
+ n += int64(thisN)
+ if err != nil {
+ return n, err
+ }
+ }
+
+ var thisN int
+ thisN, err = wr.Write(token.Bytes)
+ n += int64(thisN)
+ }
+
+ return n, err
+}
+
+func (ts Tokens) walkChildNodes(w internalWalkFunc) {
+ // Unstructured tokens have no child nodes
+}
+
+func (ts Tokens) BuildTokens(to Tokens) Tokens {
+ return append(to, ts...)
+}
+
+// ObjectAttrTokens represents the raw tokens for the name and value of
+// one attribute in an object constructor expression.
+//
+// This is defined primarily for use with function TokensForObject. See
+// that function's documentation for more information.
+type ObjectAttrTokens struct {
+ Name Tokens
+ Value Tokens
+}
+
+func newIdentToken(name string) *Token {
+ return &Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: []byte(name),
+ }
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/merged.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/merged.go
new file mode 100644
index 00000000000..49474ee74bb
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/merged.go
@@ -0,0 +1,227 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "fmt"
+)
+
+// MergeFiles combines the given files to produce a single body that contains
+// configuration from all of the given files.
+//
+// The ordering of the given files decides the order in which contained
+// elements will be returned. If any top-level attributes are defined with
+// the same name across multiple files, a diagnostic will be produced from
+// the Content and PartialContent methods describing this error in a
+// user-friendly way.
+func MergeFiles(files []*File) Body {
+ var bodies []Body
+ for _, file := range files {
+ bodies = append(bodies, file.Body)
+ }
+ return MergeBodies(bodies)
+}
+
+// MergeBodies is like MergeFiles except it deals directly with bodies, rather
+// than with entire files.
+func MergeBodies(bodies []Body) Body {
+ if len(bodies) == 0 {
+ // Swap out for our singleton empty body, to reduce the number of
+ // empty slices we have hanging around.
+ return emptyBody
+ }
+
+ // If any of the given bodies are already merged bodies, we'll unpack
+ // to flatten to a single mergedBodies, since that's conceptually simpler.
+ // This also, as a side-effect, eliminates any empty bodies, since
+ // empties are merged bodies with no inner bodies.
+ var newLen int
+ var flatten bool
+ for _, body := range bodies {
+ if children, merged := body.(mergedBodies); merged {
+ newLen += len(children)
+ flatten = true
+ } else {
+ newLen++
+ }
+ }
+
+ if !flatten { // not just newLen == len, because we might have mergedBodies with single bodies inside
+ return mergedBodies(bodies)
+ }
+
+ if newLen == 0 {
+ // Don't allocate a new empty when we already have one
+ return emptyBody
+ }
+
+ new := make([]Body, 0, newLen)
+ for _, body := range bodies {
+ if children, merged := body.(mergedBodies); merged {
+ new = append(new, children...)
+ } else {
+ new = append(new, body)
+ }
+ }
+ return mergedBodies(new)
+}
+
+var emptyBody = mergedBodies([]Body{})
+
+// EmptyBody returns a body with no content. This body can be used as a
+// placeholder when a body is required but no body content is available.
+func EmptyBody() Body {
+ return emptyBody
+}
+
+type mergedBodies []Body
+
+// Content returns the content produced by applying the given schema to all
+// of the merged bodies and merging the result.
+//
+// Although required attributes _are_ supported, they should be used sparingly
+// with merged bodies since in this case there is no contextual information
+// with which to return good diagnostics. Applications working with merged
+// bodies may wish to mark all attributes as optional and then check for
+// required attributes afterwards, to produce better diagnostics.
+func (mb mergedBodies) Content(schema *BodySchema) (*BodyContent, Diagnostics) {
+ // the returned body will always be empty in this case, because mergedContent
+ // will only ever call Content on the child bodies.
+ content, _, diags := mb.mergedContent(schema, false)
+ return content, diags
+}
+
+func (mb mergedBodies) PartialContent(schema *BodySchema) (*BodyContent, Body, Diagnostics) {
+ return mb.mergedContent(schema, true)
+}
+
+func (mb mergedBodies) JustAttributes() (Attributes, Diagnostics) {
+ attrs := make(map[string]*Attribute)
+ var diags Diagnostics
+
+ for _, body := range mb {
+ thisAttrs, thisDiags := body.JustAttributes()
+
+ if len(thisDiags) != 0 {
+ diags = append(diags, thisDiags...)
+ }
+
+ for name, attr := range thisAttrs {
+ if existing := attrs[name]; existing != nil {
+ diags = diags.Append(&Diagnostic{
+ Severity: DiagError,
+ Summary: "Duplicate argument",
+ Detail: fmt.Sprintf(
+ "Argument %q was already set at %s",
+ name, existing.NameRange.String(),
+ ),
+ Subject: &attr.NameRange,
+ })
+ continue
+ }
+
+ attrs[name] = attr
+ }
+ }
+
+ return attrs, diags
+}
+
+func (mb mergedBodies) MissingItemRange() Range {
+ if len(mb) == 0 {
+ // Nothing useful to return here, so we'll return some garbage.
+ return Range{
+ Filename: "",
+ }
+ }
+
+ // arbitrarily use the first body's missing item range
+ return mb[0].MissingItemRange()
+}
+
+func (mb mergedBodies) mergedContent(schema *BodySchema, partial bool) (*BodyContent, Body, Diagnostics) {
+ // We need to produce a new schema with none of the attributes marked as
+ // required, since _any one_ of our bodies can contribute an attribute value.
+ // We'll separately check that all required attributes are present at
+ // the end.
+ mergedSchema := &BodySchema{
+ Blocks: schema.Blocks,
+ }
+ for _, attrS := range schema.Attributes {
+ mergedAttrS := attrS
+ mergedAttrS.Required = false
+ mergedSchema.Attributes = append(mergedSchema.Attributes, mergedAttrS)
+ }
+
+ var mergedLeftovers []Body
+ content := &BodyContent{
+ Attributes: map[string]*Attribute{},
+ }
+
+ var diags Diagnostics
+ for _, body := range mb {
+ var thisContent *BodyContent
+ var thisLeftovers Body
+ var thisDiags Diagnostics
+
+ if partial {
+ thisContent, thisLeftovers, thisDiags = body.PartialContent(mergedSchema)
+ } else {
+ thisContent, thisDiags = body.Content(mergedSchema)
+ }
+
+ if thisLeftovers != nil {
+ mergedLeftovers = append(mergedLeftovers, thisLeftovers)
+ }
+ if len(thisDiags) != 0 {
+ diags = append(diags, thisDiags...)
+ }
+
+ if thisContent.Attributes != nil {
+ for name, attr := range thisContent.Attributes {
+ if existing := content.Attributes[name]; existing != nil {
+ diags = diags.Append(&Diagnostic{
+ Severity: DiagError,
+ Summary: "Duplicate argument",
+ Detail: fmt.Sprintf(
+ "Argument %q was already set at %s",
+ name, existing.NameRange.String(),
+ ),
+ Subject: &attr.NameRange,
+ })
+ continue
+ }
+ content.Attributes[name] = attr
+ }
+ }
+
+ if len(thisContent.Blocks) != 0 {
+ content.Blocks = append(content.Blocks, thisContent.Blocks...)
+ }
+ }
+
+ // Finally, we check for required attributes.
+ for _, attrS := range schema.Attributes {
+ if !attrS.Required {
+ continue
+ }
+
+ if content.Attributes[attrS.Name] == nil {
+ // We don't have any context here to produce a good diagnostic,
+ // which is why we warn in the Content docstring to minimize the
+ // use of required attributes on merged bodies.
+ diags = diags.Append(&Diagnostic{
+ Severity: DiagError,
+ Summary: "Missing required argument",
+ Detail: fmt.Sprintf(
+ "The argument %q is required, but was not set.",
+ attrS.Name,
+ ),
+ })
+ }
+ }
+
+ leftoverBody := MergeBodies(mergedLeftovers)
+ return content, leftoverBody, diags
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/ops.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ops.go
new file mode 100644
index 00000000000..9420abdb1c4
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/ops.go
@@ -0,0 +1,436 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+// Index is a helper function that performs the same operation as the index
+// operator in the HCL expression language. That is, the result is the
+// same as it would be for collection[key] in a configuration expression.
+//
+// This is exported so that applications can perform indexing in a manner
+// consistent with how the language does it, including handling of null and
+// unknown values, etc.
+//
+// Diagnostics are produced if the given combination of values is not valid.
+// Therefore a pointer to a source range must be provided to use in diagnostics,
+// though nil can be provided if the calling application is going to
+// ignore the subject of the returned diagnostics anyway.
+func Index(collection, key cty.Value, srcRange *Range) (cty.Value, Diagnostics) {
+ const invalidIndex = "Invalid index"
+
+ if collection.IsNull() {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: "Attempt to index null value",
+ Detail: "This value is null, so it does not have any indices.",
+ Subject: srcRange,
+ },
+ }
+ }
+ if key.IsNull() {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "Can't use a null value as an indexing key.",
+ Subject: srcRange,
+ },
+ }
+ }
+ ty := collection.Type()
+ kty := key.Type()
+ if kty == cty.DynamicPseudoType || ty == cty.DynamicPseudoType {
+ return cty.DynamicVal.WithSameMarks(collection), nil
+ }
+
+ switch {
+
+ case ty.IsListType() || ty.IsTupleType() || ty.IsMapType():
+ var wantType cty.Type
+ switch {
+ case ty.IsListType() || ty.IsTupleType():
+ wantType = cty.Number
+ case ty.IsMapType():
+ wantType = cty.String
+ default:
+ // should never happen
+ panic("don't know what key type we want")
+ }
+
+ key, keyErr := convert.Convert(key, wantType)
+ if keyErr != nil {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: fmt.Sprintf(
+ "The given key does not identify an element in this collection value: %s.",
+ keyErr.Error(),
+ ),
+ Subject: srcRange,
+ },
+ }
+ }
+
+ // Here we drop marks from HasIndex result, in order to allow basic
+ // traversal of a marked list, tuple, or map in the same way we can
+ // traverse a marked object
+ has, _ := collection.HasIndex(key).Unmark()
+ if !has.IsKnown() {
+ if ty.IsTupleType() {
+ return cty.DynamicVal.WithSameMarks(collection), nil
+ } else {
+ return cty.UnknownVal(ty.ElementType()).WithSameMarks(collection), nil
+ }
+ }
+ if has.False() {
+ if (ty.IsListType() || ty.IsTupleType()) && key.Type().Equals(cty.Number) {
+ if key.IsKnown() && !key.IsNull() {
+ // NOTE: we don't know what any marks might've represented
+ // up at the calling application layer, so we must avoid
+ // showing the literal number value in these error messages
+ // in case the mark represents something important, such as
+ // a value being "sensitive".
+ key, _ := key.Unmark()
+ bf := key.AsBigFloat()
+ if _, acc := bf.Int(nil); acc != big.Exact {
+ // We have a more specialized error message for the
+ // situation of using a fractional number to index into
+ // a sequence, because that will tend to happen if the
+ // user is trying to use division to calculate an index
+ // and not realizing that HCL does float division
+ // rather than integer division.
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "The given key does not identify an element in this collection value: indexing a sequence requires a whole number, but the given index has a fractional part.",
+ Subject: srcRange,
+ },
+ }
+ }
+
+ if bf.Sign() < 0 {
+ // Some other languages allow negative indices to
+ // select "backwards" from the end of the sequence,
+ // but HCL doesn't do that in order to give better
+ // feedback if a dynamic index is calculated
+ // incorrectly.
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "The given key does not identify an element in this collection value: a negative number is not a valid index for a sequence.",
+ Subject: srcRange,
+ },
+ }
+ }
+ if lenVal := collection.Length(); lenVal.IsKnown() && !lenVal.IsMarked() {
+ // Length always returns a number, and we already
+ // checked that it's a known number, so this is safe.
+ lenBF := lenVal.AsBigFloat()
+ var result big.Float
+ result.Sub(bf, lenBF)
+ if result.Sign() < 1 {
+ if lenBF.Sign() == 0 {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "The given key does not identify an element in this collection value: the collection has no elements.",
+ Subject: srcRange,
+ },
+ }
+ } else {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "The given key does not identify an element in this collection value: the given index is greater than or equal to the length of the collection.",
+ Subject: srcRange,
+ },
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // If this is not one of the special situations we handled above
+ // then we'll fall back on a very generic message.
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "The given key does not identify an element in this collection value.",
+ Subject: srcRange,
+ },
+ }
+ }
+
+ return collection.Index(key), nil
+
+ case ty.IsObjectType():
+ wasNumber := key.Type() == cty.Number
+ key, keyErr := convert.Convert(key, cty.String)
+ if keyErr != nil {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: fmt.Sprintf(
+ "The given key does not identify an element in this collection value: %s.",
+ keyErr.Error(),
+ ),
+ Subject: srcRange,
+ },
+ }
+ }
+ if !key.IsKnown() {
+ return cty.DynamicVal.WithSameMarks(collection), nil
+ }
+
+ key, _ = key.Unmark()
+ attrName := key.AsString()
+
+ if !ty.HasAttribute(attrName) {
+ var suggestion string
+ if wasNumber {
+ // We note this only as an addendum to an error we would've
+ // already returned anyway, because it is valid (albeit weird)
+ // to have an attribute whose name is just decimal digits
+ // and then access that attribute using a number whose
+ // decimal representation is the same digits.
+ suggestion = " An object only supports looking up attributes by name, not by numeric index."
+ }
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: fmt.Sprintf("The given key does not identify an element in this collection value.%s", suggestion),
+ Subject: srcRange,
+ },
+ }
+ }
+
+ if !collection.IsKnown() {
+ return cty.UnknownVal(ty.AttributeType(attrName)).WithSameMarks(collection), nil
+ }
+
+ return collection.GetAttr(attrName), nil
+
+ case ty.IsSetType():
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "Elements of a set are identified only by their value and don't have any separate index or key to select with, so it's only possible to perform operations across all elements of the set.",
+ Subject: srcRange,
+ },
+ }
+
+ default:
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: invalidIndex,
+ Detail: "This value does not have any indices.",
+ Subject: srcRange,
+ },
+ }
+ }
+
+}
+
+// GetAttr is a helper function that performs the same operation as the
+// attribute access in the HCL expression language. That is, the result is the
+// same as it would be for obj.attr in a configuration expression.
+//
+// This is exported so that applications can access attributes in a manner
+// consistent with how the language does it, including handling of null and
+// unknown values, etc.
+//
+// Diagnostics are produced if the given combination of values is not valid.
+// Therefore a pointer to a source range must be provided to use in diagnostics,
+// though nil can be provided if the calling application is going to
+// ignore the subject of the returned diagnostics anyway.
+func GetAttr(obj cty.Value, attrName string, srcRange *Range) (cty.Value, Diagnostics) {
+ if obj.IsNull() {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: "Attempt to get attribute from null value",
+ Detail: "This value is null, so it does not have any attributes.",
+ Subject: srcRange,
+ },
+ }
+ }
+
+ const unsupportedAttr = "Unsupported attribute"
+
+ ty := obj.Type()
+ switch {
+ case ty.IsObjectType():
+ if !ty.HasAttribute(attrName) {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: unsupportedAttr,
+ Detail: fmt.Sprintf("This object does not have an attribute named %q.", attrName),
+ Subject: srcRange,
+ },
+ }
+ }
+
+ if !obj.IsKnown() {
+ return cty.UnknownVal(ty.AttributeType(attrName)).WithSameMarks(obj), nil
+ }
+
+ return obj.GetAttr(attrName), nil
+ case ty.IsMapType():
+ if !obj.IsKnown() {
+ return cty.UnknownVal(ty.ElementType()).WithSameMarks(obj), nil
+ }
+
+ idx := cty.StringVal(attrName)
+
+ // Here we drop marks from HasIndex result, in order to allow basic
+ // traversal of a marked map in the same way we can traverse a marked
+ // object
+ hasIndex, _ := obj.HasIndex(idx).Unmark()
+ if hasIndex.False() {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: "Missing map element",
+ Detail: fmt.Sprintf("This map does not have an element with the key %q.", attrName),
+ Subject: srcRange,
+ },
+ }
+ }
+
+ return obj.Index(idx), nil
+ case ty == cty.DynamicPseudoType:
+ return cty.DynamicVal.WithSameMarks(obj), nil
+ case ty.IsListType() && ty.ElementType().IsObjectType():
+ // It seems a common mistake to try to access attributes on a whole
+ // list of objects rather than on a specific individual element, so
+ // we have some extra hints for that case.
+
+ switch {
+ case ty.ElementType().HasAttribute(attrName):
+ // This is a very strong indication that the user mistook the list
+ // of objects for a single object, so we can be a little more
+ // direct in our suggestion here.
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: unsupportedAttr,
+ Detail: fmt.Sprintf("Can't access attributes on a list of objects. Did you mean to access attribute %q for a specific element of the list, or across all elements of the list?", attrName),
+ Subject: srcRange,
+ },
+ }
+ default:
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: unsupportedAttr,
+ Detail: "Can't access attributes on a list of objects. Did you mean to access an attribute for a specific element of the list, or across all elements of the list?",
+ Subject: srcRange,
+ },
+ }
+ }
+
+ case ty.IsSetType() && ty.ElementType().IsObjectType():
+ // This is similar to the previous case, but we can't give such a
+ // direct suggestion because there is no mechanism to select a single
+ // item from a set.
+ // We could potentially suggest using a for expression or splat
+ // operator here, but we typically don't get into syntax specifics
+ // in hcl.GetAttr suggestions because it's a general function used in
+ // various other situations, such as in application-specific operations
+ // that might have a more constraint set of alternative approaches.
+
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: unsupportedAttr,
+ Detail: "Can't access attributes on a set of objects. Did you mean to access an attribute across all elements of the set?",
+ Subject: srcRange,
+ },
+ }
+
+ case ty.IsPrimitiveType():
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: unsupportedAttr,
+ Detail: fmt.Sprintf("Can't access attributes on a primitive-typed value (%s).", ty.FriendlyName()),
+ Subject: srcRange,
+ },
+ }
+
+ default:
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: unsupportedAttr,
+ Detail: "This value does not have any attributes.",
+ Subject: srcRange,
+ },
+ }
+ }
+
+}
+
+// ApplyPath is a helper function that applies a cty.Path to a value using the
+// indexing and attribute access operations from HCL.
+//
+// This is similar to calling the path's own Apply method, but ApplyPath uses
+// the more relaxed typing rules that apply to these operations in HCL, rather
+// than cty's relatively-strict rules. ApplyPath is implemented in terms of
+// Index and GetAttr, and so it has the same behavior for individual steps
+// but will stop and return any errors returned by intermediate steps.
+//
+// Diagnostics are produced if the given path cannot be applied to the given
+// value. Therefore a pointer to a source range must be provided to use in
+// diagnostics, though nil can be provided if the calling application is going
+// to ignore the subject of the returned diagnostics anyway.
+func ApplyPath(val cty.Value, path cty.Path, srcRange *Range) (cty.Value, Diagnostics) {
+ var diags Diagnostics
+
+ for _, step := range path {
+ var stepDiags Diagnostics
+ switch ts := step.(type) {
+ case cty.IndexStep:
+ val, stepDiags = Index(val, ts.Key, srcRange)
+ case cty.GetAttrStep:
+ val, stepDiags = GetAttr(val, ts.Name, srcRange)
+ default:
+ // Should never happen because the above are all of the step types.
+ diags = diags.Append(&Diagnostic{
+ Severity: DiagError,
+ Summary: "Invalid path step",
+ Detail: fmt.Sprintf("Go type %T is not a valid path step. This is a bug in this program.", step),
+ Subject: srcRange,
+ })
+ return cty.DynamicVal, diags
+ }
+
+ diags = append(diags, stepDiags...)
+ if stepDiags.HasErrors() {
+ return cty.DynamicVal, diags
+ }
+ }
+
+ return val, diags
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/pos.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/pos.go
new file mode 100644
index 00000000000..1bbbce87e19
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/pos.go
@@ -0,0 +1,278 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import "fmt"
+
+// Pos represents a single position in a source file, by addressing the
+// start byte of a unicode character encoded in UTF-8.
+//
+// Pos is generally used only in the context of a Range, which then defines
+// which source file the position is within.
+type Pos struct {
+ // Line is the source code line where this position points. Lines are
+ // counted starting at 1 and incremented for each newline character
+ // encountered.
+ Line int
+
+ // Column is the source code column where this position points, in
+ // unicode characters, with counting starting at 1.
+ //
+ // Column counts characters as they appear visually, so for example a
+ // latin letter with a combining diacritic mark counts as one character.
+ // This is intended for rendering visual markers against source code in
+ // contexts where these diacritics would be rendered in a single character
+ // cell. Technically speaking, Column is counting grapheme clusters as
+ // used in unicode normalization.
+ Column int
+
+ // Byte is the byte offset into the file where the indicated character
+ // begins. This is a zero-based offset to the first byte of the first
+ // UTF-8 codepoint sequence in the character, and thus gives a position
+ // that can be resolved _without_ awareness of Unicode characters.
+ Byte int
+}
+
+// InitialPos is a suitable position to use to mark the start of a file.
+var InitialPos = Pos{Byte: 0, Line: 1, Column: 1}
+
+// Range represents a span of characters between two positions in a source
+// file.
+//
+// This struct is usually used by value in types that represent AST nodes,
+// but by pointer in types that refer to the positions of other objects,
+// such as in diagnostics.
+type Range struct {
+ // Filename is the name of the file into which this range's positions
+ // point.
+ Filename string
+
+ // Start and End represent the bounds of this range. Start is inclusive
+ // and End is exclusive.
+ Start, End Pos
+}
+
+// RangeBetween returns a new range that spans from the beginning of the
+// start range to the end of the end range.
+//
+// The result is meaningless if the two ranges do not belong to the same
+// source file or if the end range appears before the start range.
+func RangeBetween(start, end Range) Range {
+ return Range{
+ Filename: start.Filename,
+ Start: start.Start,
+ End: end.End,
+ }
+}
+
+// RangeOver returns a new range that covers both of the given ranges and
+// possibly additional content between them if the two ranges do not overlap.
+//
+// If either range is empty then it is ignored. The result is empty if both
+// given ranges are empty.
+//
+// The result is meaningless if the two ranges to not belong to the same
+// source file.
+func RangeOver(a, b Range) Range {
+ if a.Empty() {
+ return b
+ }
+ if b.Empty() {
+ return a
+ }
+
+ var start, end Pos
+ if a.Start.Byte < b.Start.Byte {
+ start = a.Start
+ } else {
+ start = b.Start
+ }
+ if a.End.Byte > b.End.Byte {
+ end = a.End
+ } else {
+ end = b.End
+ }
+ return Range{
+ Filename: a.Filename,
+ Start: start,
+ End: end,
+ }
+}
+
+// ContainsPos returns true if and only if the given position is contained within
+// the receiving range.
+//
+// In the unlikely case that the line/column information disagree with the byte
+// offset information in the given position or receiving range, the byte
+// offsets are given priority.
+func (r Range) ContainsPos(pos Pos) bool {
+ return r.ContainsOffset(pos.Byte)
+}
+
+// ContainsOffset returns true if and only if the given byte offset is within
+// the receiving Range.
+func (r Range) ContainsOffset(offset int) bool {
+ return offset >= r.Start.Byte && offset < r.End.Byte
+}
+
+// Ptr returns a pointer to a copy of the receiver. This is a convenience when
+// ranges in places where pointers are required, such as in Diagnostic, but
+// the range in question is returned from a method. Go would otherwise not
+// allow one to take the address of a function call.
+func (r Range) Ptr() *Range {
+ return &r
+}
+
+// String returns a compact string representation of the receiver.
+// Callers should generally prefer to present a range more visually,
+// e.g. via markers directly on the relevant portion of source code.
+func (r Range) String() string {
+ if r.Start.Line == r.End.Line {
+ return fmt.Sprintf(
+ "%s:%d,%d-%d",
+ r.Filename,
+ r.Start.Line, r.Start.Column,
+ r.End.Column,
+ )
+ } else {
+ return fmt.Sprintf(
+ "%s:%d,%d-%d,%d",
+ r.Filename,
+ r.Start.Line, r.Start.Column,
+ r.End.Line, r.End.Column,
+ )
+ }
+}
+
+func (r Range) Empty() bool {
+ return r.Start.Byte == r.End.Byte
+}
+
+// CanSliceBytes returns true if SliceBytes could return an accurate
+// sub-slice of the given slice.
+//
+// This effectively tests whether the start and end offsets of the range
+// are within the bounds of the slice, and thus whether SliceBytes can be
+// trusted to produce an accurate start and end position within that slice.
+func (r Range) CanSliceBytes(b []byte) bool {
+ switch {
+ case r.Start.Byte < 0 || r.Start.Byte > len(b):
+ return false
+ case r.End.Byte < 0 || r.End.Byte > len(b):
+ return false
+ case r.End.Byte < r.Start.Byte:
+ return false
+ default:
+ return true
+ }
+}
+
+// SliceBytes returns a sub-slice of the given slice that is covered by the
+// receiving range, assuming that the given slice is the source code of the
+// file indicated by r.Filename.
+//
+// If the receiver refers to any byte offsets that are outside of the slice
+// then the result is constrained to the overlapping portion only, to avoid
+// a panic. Use CanSliceBytes to determine if the result is guaranteed to
+// be an accurate span of the requested range.
+func (r Range) SliceBytes(b []byte) []byte {
+ start := r.Start.Byte
+ end := r.End.Byte
+ if start < 0 {
+ start = 0
+ } else if start > len(b) {
+ start = len(b)
+ }
+ if end < 0 {
+ end = 0
+ } else if end > len(b) {
+ end = len(b)
+ }
+ if end < start {
+ end = start
+ }
+ return b[start:end]
+}
+
+// Overlaps returns true if the receiver and the other given range share any
+// characters in common.
+func (r Range) Overlaps(other Range) bool {
+ switch {
+ case r.Filename != other.Filename:
+ // If the ranges are in different files then they can't possibly overlap
+ return false
+ case r.Empty() || other.Empty():
+ // Empty ranges can never overlap
+ return false
+ case r.ContainsOffset(other.Start.Byte) || r.ContainsOffset(other.End.Byte):
+ return true
+ case other.ContainsOffset(r.Start.Byte) || other.ContainsOffset(r.End.Byte):
+ return true
+ default:
+ return false
+ }
+}
+
+// Overlap finds a range that is either identical to or a sub-range of both
+// the receiver and the other given range. It returns an empty range
+// within the receiver if there is no overlap between the two ranges.
+//
+// A non-empty result is either identical to or a subset of the receiver.
+func (r Range) Overlap(other Range) Range {
+ if !r.Overlaps(other) {
+ // Start == End indicates an empty range
+ return Range{
+ Filename: r.Filename,
+ Start: r.Start,
+ End: r.Start,
+ }
+ }
+
+ var start, end Pos
+ if r.Start.Byte > other.Start.Byte {
+ start = r.Start
+ } else {
+ start = other.Start
+ }
+ if r.End.Byte < other.End.Byte {
+ end = r.End
+ } else {
+ end = other.End
+ }
+
+ return Range{
+ Filename: r.Filename,
+ Start: start,
+ End: end,
+ }
+}
+
+// PartitionAround finds the portion of the given range that overlaps with
+// the reciever and returns three ranges: the portion of the reciever that
+// precedes the overlap, the overlap itself, and then the portion of the
+// reciever that comes after the overlap.
+//
+// If the two ranges do not overlap then all three returned ranges are empty.
+//
+// If the given range aligns with or extends beyond either extent of the
+// reciever then the corresponding outer range will be empty.
+func (r Range) PartitionAround(other Range) (before, overlap, after Range) {
+ overlap = r.Overlap(other)
+ if overlap.Empty() {
+ return overlap, overlap, overlap
+ }
+
+ before = Range{
+ Filename: r.Filename,
+ Start: r.Start,
+ End: overlap.Start,
+ }
+ after = Range{
+ Filename: r.Filename,
+ Start: overlap.End,
+ End: r.End,
+ }
+
+ return before, overlap, after
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/pos_scanner.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/pos_scanner.go
new file mode 100644
index 00000000000..2232f374af2
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/pos_scanner.go
@@ -0,0 +1,155 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "bufio"
+ "bytes"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+)
+
+// RangeScanner is a helper that will scan over a buffer using a bufio.SplitFunc
+// and visit a source range for each token matched.
+//
+// For example, this can be used with bufio.ScanLines to find the source range
+// for each line in the file, skipping over the actual newline characters, which
+// may be useful when printing source code snippets as part of diagnostic
+// messages.
+//
+// The line and column information in the returned ranges is produced by
+// counting newline characters and grapheme clusters respectively, which
+// mimics the behavior we expect from a parser when producing ranges.
+type RangeScanner struct {
+ filename string
+ b []byte
+ cb bufio.SplitFunc
+
+ pos Pos // position of next byte to process in b
+ cur Range // latest range
+ tok []byte // slice of b that is covered by cur
+ err error // error from last scan, if any
+}
+
+// NewRangeScanner creates a new RangeScanner for the given buffer, producing
+// ranges for the given filename.
+//
+// Since ranges have grapheme-cluster granularity rather than byte granularity,
+// the scanner will produce incorrect results if the given SplitFunc creates
+// tokens between grapheme cluster boundaries. In particular, it is incorrect
+// to use RangeScanner with bufio.ScanRunes because it will produce tokens
+// around individual UTF-8 sequences, which will split any multi-sequence
+// grapheme clusters.
+func NewRangeScanner(b []byte, filename string, cb bufio.SplitFunc) *RangeScanner {
+ return NewRangeScannerFragment(b, filename, InitialPos, cb)
+}
+
+// NewRangeScannerFragment is like NewRangeScanner but the ranges it produces
+// will be offset by the given starting position, which is appropriate for
+// sub-slices of a file, whereas NewRangeScanner assumes it is scanning an
+// entire file.
+func NewRangeScannerFragment(b []byte, filename string, start Pos, cb bufio.SplitFunc) *RangeScanner {
+ return &RangeScanner{
+ filename: filename,
+ b: b,
+ cb: cb,
+ pos: start,
+ }
+}
+
+func (sc *RangeScanner) Scan() bool {
+ if sc.pos.Byte >= len(sc.b) || sc.err != nil {
+ // All done
+ return false
+ }
+
+ // Since we're operating on an in-memory buffer, we always pass the whole
+ // remainder of the buffer to our SplitFunc and set isEOF to let it know
+ // that it has the whole thing.
+ advance, token, err := sc.cb(sc.b[sc.pos.Byte:], true)
+
+ // Since we are setting isEOF to true this should never happen, but
+ // if it does we will just abort and assume the SplitFunc is misbehaving.
+ if advance == 0 && token == nil && err == nil {
+ return false
+ }
+
+ if err != nil {
+ sc.err = err
+ sc.cur = Range{
+ Filename: sc.filename,
+ Start: sc.pos,
+ End: sc.pos,
+ }
+ sc.tok = nil
+ return false
+ }
+
+ sc.tok = token
+ start := sc.pos
+ end := sc.pos
+ new := sc.pos
+
+ // adv is similar to token but it also includes any subsequent characters
+ // we're being asked to skip over by the SplitFunc.
+ // adv is a slice covering any additional bytes we are skipping over, based
+ // on what the SplitFunc told us to do with advance.
+ adv := sc.b[sc.pos.Byte : sc.pos.Byte+advance]
+
+ // We now need to scan over our token to count the grapheme clusters
+ // so we can correctly advance Column, and count the newlines so we
+ // can correctly advance Line.
+ advR := bytes.NewReader(adv)
+ gsc := bufio.NewScanner(advR)
+ advanced := 0
+ gsc.Split(textseg.ScanGraphemeClusters)
+ for gsc.Scan() {
+ gr := gsc.Bytes()
+ new.Byte += len(gr)
+ new.Column++
+
+ // We rely here on the fact that \r\n is considered a grapheme cluster
+ // and so we don't need to worry about miscounting additional lines
+ // on files with Windows-style line endings.
+ if len(gr) != 0 && (gr[0] == '\r' || gr[0] == '\n') {
+ new.Column = 1
+ new.Line++
+ }
+
+ if advanced < len(token) {
+ // If we've not yet found the end of our token then we'll
+ // also push our "end" marker along.
+ // (if advance > len(token) then we'll stop moving "end" early
+ // so that the caller only sees the range covered by token.)
+ end = new
+ }
+ advanced += len(gr)
+ }
+
+ sc.cur = Range{
+ Filename: sc.filename,
+ Start: start,
+ End: end,
+ }
+ sc.pos = new
+ return true
+}
+
+// Range returns a range that covers the latest token obtained after a call
+// to Scan returns true.
+func (sc *RangeScanner) Range() Range {
+ return sc.cur
+}
+
+// Bytes returns the slice of the input buffer that is covered by the range
+// that would be returned by Range.
+func (sc *RangeScanner) Bytes() []byte {
+ return sc.tok
+}
+
+// Err can be called after Scan returns false to determine if the latest read
+// resulted in an error, and obtain that error if so.
+func (sc *RangeScanner) Err() error {
+ return sc.err
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/schema.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/schema.go
new file mode 100644
index 00000000000..d4e339cb26e
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/schema.go
@@ -0,0 +1,24 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+// BlockHeaderSchema represents the shape of a block header, and is
+// used for matching blocks within bodies.
+type BlockHeaderSchema struct {
+ Type string
+ LabelNames []string
+}
+
+// AttributeSchema represents the requirements for an attribute, and is used
+// for matching attributes within bodies.
+type AttributeSchema struct {
+ Name string
+ Required bool
+}
+
+// BodySchema represents the desired shallow structure of a body.
+type BodySchema struct {
+ Attributes []AttributeSchema
+ Blocks []BlockHeaderSchema
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/spec.md b/hack/tools/vendor/github.com/hashicorp/hcl/v2/spec.md
new file mode 100644
index 00000000000..d52ed70bb52
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/spec.md
@@ -0,0 +1,691 @@
+# HCL Syntax-Agnostic Information Model
+
+This is the specification for the general information model (abstract types and
+semantics) for hcl. HCL is a system for defining configuration languages for
+applications. The HCL information model is designed to support multiple
+concrete syntaxes for configuration, each with a mapping to the model defined
+in this specification.
+
+The two primary syntaxes intended for use in conjunction with this model are
+[the HCL native syntax](./hclsyntax/spec.md) and [the JSON syntax](./json/spec.md).
+In principle other syntaxes are possible as long as either their language model
+is sufficiently rich to express the concepts described in this specification
+or the language targets a well-defined subset of the specification.
+
+## Structural Elements
+
+The primary structural element is the _body_, which is a container representing
+a set of zero or more _attributes_ and a set of zero or more _blocks_.
+
+A _configuration file_ is the top-level object, and will usually be produced
+by reading a file from disk and parsing it as a particular syntax. A
+configuration file has its own _body_, representing the top-level attributes
+and blocks.
+
+An _attribute_ is a name and value pair associated with a body. Attribute names
+are unique within a given body. Attribute values are provided as _expressions_,
+which are discussed in detail in a later section.
+
+A _block_ is a nested structure that has a _type name_, zero or more string
+_labels_ (e.g. identifiers), and a nested body.
+
+Together the structural elements create a hierarchical data structure, with
+attributes intended to represent the direct properties of a particular object
+in the calling application, and blocks intended to represent child objects
+of a particular object.
+
+## Body Content
+
+To support the expression of the HCL concepts in languages whose information
+model is a subset of HCL's, such as JSON, a _body_ is an opaque container
+whose content can only be accessed by providing information on the expected
+structure of the content.
+
+The specification for each syntax must describe how its physical constructs
+are mapped on to body content given a schema. For syntaxes that have
+first-class syntax distinguishing attributes and bodies this can be relatively
+straightforward, while more detailed mapping rules may be required in syntaxes
+where the representation of attributes vs. blocks is ambiguous.
+
+### Schema-driven Processing
+
+Schema-driven processing is the primary way to access body content.
+A _body schema_ is a description of what is expected within a particular body,
+which can then be used to extract the _body content_, which then provides
+access to the specific attributes and blocks requested.
+
+A _body schema_ consists of a list of _attribute schemata_ and
+_block header schemata_:
+
+- An _attribute schema_ provides the name of an attribute and whether its
+ presence is required.
+
+- A _block header schema_ provides a block type name and the semantic names
+ assigned to each of the labels of that block type, if any.
+
+Within a schema, it is an error to request the same attribute name twice or
+to request a block type whose name is also an attribute name. While this can
+in principle be supported in some syntaxes, in other syntaxes the attribute
+and block namespaces are combined and so an attribute cannot coexist with
+a block whose type name is identical to the attribute name.
+
+The result of applying a body schema to a body is _body content_, which
+consists of an _attribute map_ and a _block sequence_:
+
+- The _attribute map_ is a map data structure whose keys are attribute names
+ and whose values are _expressions_ that represent the corresponding attribute
+ values.
+
+- The _block sequence_ is an ordered sequence of blocks, with each specifying
+ a block _type name_, the sequence of _labels_ specified for the block,
+ and the body object (not body _content_) representing the block's own body.
+
+After obtaining _body content_, the calling application may continue processing
+by evaluating attribute expressions and/or recursively applying further
+schema-driven processing to the child block bodies.
+
+**Note:** The _body schema_ is intentionally minimal, to reduce the set of
+mapping rules that must be defined for each syntax. Higher-level utility
+libraries may be provided to assist in the construction of a schema and
+perform additional processing, such as automatically evaluating attribute
+expressions and assigning their result values into a data structure, or
+recursively applying a schema to child blocks. Such utilities are not part of
+this core specification and will vary depending on the capabilities and idiom
+of the implementation language.
+
+### _Dynamic Attributes_ Processing
+
+The _schema-driven_ processing model is useful when the expected structure
+of a body is known by the calling application. Some blocks are
+instead more free-form, such as a user-provided set of arbitrary key/value
+pairs.
+
+The alternative _dynamic attributes_ processing mode allows for this more
+ad-hoc approach. Processing in this mode behaves as if a schema had been
+constructed without any _block header schemata_ and with an attribute
+schema for each distinct key provided within the physical representation
+of the body.
+
+The means by which _distinct keys_ are identified is dependent on the
+physical syntax; this processing mode assumes that the syntax has a way
+to enumerate keys provided by the author and identify expressions that
+correspond with those keys, but does not define the means by which this is
+done.
+
+The result of _dynamic attributes_ processing is an _attribute map_ as
+defined in the previous section. No _block sequence_ is produced in this
+processing mode.
+
+### Partial Processing of Body Content
+
+Under _schema-driven processing_, by default the given schema is assumed
+to be exhaustive, such that any attribute or block not matched by schema
+elements is considered an error. This allows feedback about unsupported
+attributes and blocks (such as typos) to be provided.
+
+An alternative is _partial processing_, where any additional elements within
+the body are not considered an error.
+
+Under partial processing, the result is both body content as described
+above _and_ a new body that represents any body elements that remain after
+the schema has been processed.
+
+Specifically:
+
+- Any attribute whose name is specified in the schema is returned in body
+ content and elided from the new body.
+
+- Any block whose type is specified in the schema is returned in body content
+ and elided from the new body.
+
+- Any attribute or block _not_ meeting the above conditions is placed into
+ the new body, unmodified.
+
+The new body can then be recursively processed using any of the body
+processing models. This facility allows different subsets of body content
+to be processed by different parts of the calling application.
+
+Processing a body in two steps — first partial processing of a source body,
+then exhaustive processing of the returned body — is equivalent to single-step
+processing with a schema that is the union of the schemata used
+across the two steps.
+
+## Expressions
+
+Attribute values are represented by _expressions_. Depending on the concrete
+syntax in use, an expression may just be a literal value or it may describe
+a computation in terms of literal values, variables, and functions.
+
+Each syntax defines its own representation of expressions. For syntaxes based
+in languages that do not have any non-literal expression syntax, it is
+recommended to embed the template language from
+[the native syntax](./hclsyntax/spec.md) e.g. as a post-processing step on
+string literals.
+
+### Expression Evaluation
+
+In order to obtain a concrete value, each expression must be _evaluated_.
+Evaluation is performed in terms of an evaluation context, which
+consists of the following:
+
+- An _evaluation mode_, which is defined below.
+- A _variable scope_, which provides a set of named variables for use in
+ expressions.
+- A _function table_, which provides a set of named functions for use in
+ expressions.
+
+The _evaluation mode_ allows for two different interpretations of an
+expression:
+
+- In _literal-only mode_, variables and functions are not available and it
+ is assumed that the calling application's intent is to treat the attribute
+ value as a literal.
+
+- In _full expression mode_, variables and functions are defined and it is
+ assumed that the calling application wishes to provide a full expression
+ language for definition of the attribute value.
+
+The actual behavior of these two modes depends on the syntax in use. For
+languages with first-class expression syntax, these two modes may be considered
+equivalent, with _literal-only mode_ simply not defining any variables or
+functions. For languages that embed arbitrary expressions via string templates,
+_literal-only mode_ may disable such processing, allowing literal strings to
+pass through without interpretation as templates.
+
+Since literal-only mode does not support variables and functions, it is an
+error for the calling application to enable this mode and yet provide a
+variable scope and/or function table.
+
+## Values and Value Types
+
+The result of expression evaluation is a _value_. Each value has a _type_,
+which is dynamically determined during evaluation. The _variable scope_ in
+the evaluation context is a map from variable name to value, using the same
+definition of value.
+
+The type system for HCL values is intended to be of a level abstraction
+suitable for configuration of various applications. A well-defined,
+implementation-language-agnostic type system is defined to allow for
+consistent processing of configuration across many implementation languages.
+Concrete implementations may provide additional functionality to lower
+HCL values and types to corresponding native language types, which may then
+impose additional constraints on the values outside of the scope of this
+specification.
+
+Two values are _equal_ if and only if they have identical types and their
+values are equal according to the rules of their shared type.
+
+### Primitive Types
+
+The primitive types are _string_, _bool_, and _number_.
+
+A _string_ is a sequence of unicode characters. Two strings are equal if
+NFC normalization ([UAX#15](http://unicode.org/reports/tr15/)
+of each string produces two identical sequences of characters.
+NFC normalization ensures that, for example, a precomposed combination of a
+latin letter and a diacritic compares equal with the letter followed by
+a combining diacritic.
+
+The _bool_ type has only two non-null values: _true_ and _false_. Two bool
+values are equal if and only if they are either both true or both false.
+
+A _number_ is an arbitrary-precision floating point value. An implementation
+_must_ make the full-precision values available to the calling application
+for interpretation into any suitable number representation. An implementation
+may in practice implement numbers with limited precision so long as the
+following constraints are met:
+
+- Integers are represented with at least 256 bits.
+- Non-integer numbers are represented as floating point values with a
+ mantissa of at least 256 bits and a signed binary exponent of at least
+ 16 bits.
+- An error is produced if an integer value given in source cannot be
+ represented precisely.
+- An error is produced if a non-integer value cannot be represented due to
+ overflow.
+- A non-integer number is rounded to the nearest possible value when a
+ value is of too high a precision to be represented.
+
+The _number_ type also requires representation of both positive and negative
+infinity. A "not a number" (NaN) value is _not_ provided nor used.
+
+Two number values are equal if they are numerically equal to the precision
+associated with the number. Positive infinity and negative infinity are
+equal to themselves but not to each other. Positive infinity is greater than
+any other number value, and negative infinity is less than any other number
+value.
+
+Some syntaxes may be unable to represent numeric literals of arbitrary
+precision. This must be defined in the syntax specification as part of its
+description of mapping numeric literals to HCL values.
+
+### Structural Types
+
+_Structural types_ are types that are constructed by combining other types.
+Each distinct combination of other types is itself a distinct type. There
+are two structural type _kinds_:
+
+- _Object types_ are constructed of a set of named attributes, each of which
+ has a type. Attribute names are always strings. (_Object_ attributes are a
+ distinct idea from _body_ attributes, though calling applications
+ may choose to blur the distinction by use of common naming schemes.)
+- _Tuple types_ are constructed of a sequence of elements, each of which
+ has a type.
+
+Values of structural types are compared for equality in terms of their
+attributes or elements. A structural type value is equal to another if and
+only if all of the corresponding attributes or elements are equal.
+
+Two structural types are identical if they are of the same kind and
+have attributes or elements with identical types.
+
+### Collection Types
+
+_Collection types_ are types that combine together an arbitrary number of
+values of some other single type. There are three collection type _kinds_:
+
+- _List types_ represent ordered sequences of values of their element type.
+- _Map types_ represent values of their element type accessed via string keys.
+- _Set types_ represent unordered sets of distinct values of their element type.
+
+For each of these kinds and each distinct element type there is a distinct
+collection type. For example, "list of string" is a distinct type from
+"set of string", and "list of number" is a distinct type from "list of string".
+
+Values of collection types are compared for equality in terms of their
+elements. A collection type value is equal to another if and only if both
+have the same number of elements and their corresponding elements are equal.
+
+Two collection types are identical if they are of the same kind and have
+the same element type.
+
+### Null values
+
+Each type has a null value. The null value of a type represents the absence
+of a value, but with type information retained to allow for type checking.
+
+Null values are used primarily to represent the conditional absence of a
+body attribute. In a syntax with a conditional operator, one of the result
+values of that conditional may be null to indicate that the attribute should be
+considered not present in that case.
+
+Calling applications _should_ consider an attribute with a null value as
+equivalent to the value not being present at all.
+
+A null value of a particular type is equal to itself.
+
+### Unknown Values and the Dynamic Pseudo-type
+
+An _unknown value_ is a placeholder for a value that is not yet known.
+Operations on unknown values themselves return unknown values that have a
+type appropriate to the operation. For example, adding together two unknown
+numbers yields an unknown number, while comparing two unknown values of any
+type for equality yields an unknown bool.
+
+Each type has a distinct unknown value. For example, an unknown _number_ is
+a distinct value from an unknown _string_.
+
+_The dynamic pseudo-type_ is a placeholder for a type that is not yet known.
+The only values of this type are its null value and its unknown value. It is
+referred to as a _pseudo-type_ because it should not be considered a type in
+its own right, but rather as a placeholder for a type yet to be established.
+The unknown value of the dynamic pseudo-type is referred to as _the dynamic
+value_.
+
+Operations on values of the dynamic pseudo-type behave as if it is a value
+of the expected type, optimistically assuming that once the value and type
+are known they will be valid for the operation. For example, adding together
+a number and the dynamic value produces an unknown number.
+
+Unknown values and the dynamic pseudo-type can be used as a mechanism for
+partial type checking and semantic checking: by evaluating an expression with
+all variables set to an unknown value, the expression can be evaluated to
+produce an unknown value of a given type, or produce an error if any operation
+is provably invalid with only type information.
+
+Unknown values and the dynamic pseudo-type must never be returned from
+operations unless at least one operand is unknown or dynamic. Calling
+applications are guaranteed that unless the global scope includes unknown
+values, or the function table includes functions that return unknown values,
+no expression will evaluate to an unknown value. The calling application is
+thus in total control over the use and meaning of unknown values.
+
+The dynamic pseudo-type is identical only to itself.
+
+### Capsule Types
+
+A _capsule type_ is a custom type defined by the calling application. A value
+of a capsule type is considered opaque to HCL, but may be accepted
+by functions provided by the calling application.
+
+A particular capsule type is identical only to itself. The equality of two
+values of the same capsule type is defined by the calling application. No
+other operations are supported for values of capsule types.
+
+Support for capsule types in a HCL implementation is optional. Capsule types
+are intended to allow calling applications to pass through values that are
+not part of the standard type system. For example, an application that
+deals with raw binary data may define a capsule type representing a byte
+array, and provide functions that produce or operate on byte arrays.
+
+### Type Specifications
+
+In certain situations it is necessary to define expectations about the expected
+type of a value. Whereas two _types_ have a commutative _identity_ relationship,
+a type has a non-commutative _matches_ relationship with a _type specification_.
+A type specification is, in practice, just a different interpretation of a
+type such that:
+
+- Any type _matches_ any type that it is identical to.
+
+- Any type _matches_ the dynamic pseudo-type.
+
+For example, given a type specification "list of dynamic pseudo-type", the
+concrete types "list of string" and "list of map" match, but the
+type "set of string" does not.
+
+## Functions and Function Calls
+
+The evaluation context used to evaluate an expression includes a function
+table, which represents an application-defined set of named functions
+available for use in expressions.
+
+Each syntax defines whether function calls are supported and how they are
+physically represented in source code, but the semantics of function calls are
+defined here to ensure consistent results across syntaxes and to allow
+applications to provide functions that are interoperable with all syntaxes.
+
+A _function_ is defined from the following elements:
+
+- Zero or more _positional parameters_, each with a name used for documentation,
+ a type specification for expected argument values, and a flag for whether
+ each of null values, unknown values, and values of the dynamic pseudo-type
+ are accepted.
+
+- Zero or one _variadic parameters_, with the same structure as the _positional_
+ parameters, which if present collects any additional arguments provided at
+ the function call site.
+
+- A _result type definition_, which specifies the value type returned for each
+ valid sequence of argument values.
+
+- A _result value definition_, which specifies the value returned for each
+ valid sequence of argument values.
+
+A _function call_, regardless of source syntax, consists of a sequence of
+argument values. The argument values are each mapped to a corresponding
+parameter as follows:
+
+- For each of the function's positional parameters in sequence, take the next
+ argument. If there are no more arguments, the call is erroneous.
+
+- If the function has a variadic parameter, take all remaining arguments that
+ where not yet assigned to a positional parameter and collect them into
+ a sequence of variadic arguments that each correspond to the variadic
+ parameter.
+
+- If the function has _no_ variadic parameter, it is an error if any arguments
+ remain after taking one argument for each positional parameter.
+
+After mapping each argument to a parameter, semantic checking proceeds
+for each argument:
+
+- If the argument value corresponding to a parameter does not match the
+ parameter's type specification, the call is erroneous.
+
+- If the argument value corresponding to a parameter is null and the parameter
+ is not specified as accepting nulls, the call is erroneous.
+
+- If the argument value corresponding to a parameter is the dynamic value
+ and the parameter is not specified as accepting values of the dynamic
+ pseudo-type, the call is valid but its _result type_ is forced to be the
+ dynamic pseudo type.
+
+- If neither of the above conditions holds for any argument, the call is
+ valid and the function's value type definition is used to determine the
+ call's _result type_. A function _may_ vary its result type depending on
+ the argument _values_ as well as the argument _types_; for example, a
+ function that decodes a JSON value will return a different result type
+ depending on the data structure described by the given JSON source code.
+
+If semantic checking succeeds without error, the call is _executed_:
+
+- For each argument, if its value is unknown and its corresponding parameter
+ is not specified as accepting unknowns, the _result value_ is forced to be an
+ unknown value of the result type.
+
+- If the previous condition does not apply, the function's result value
+ definition is used to determine the call's _result value_.
+
+The result of a function call expression is either an error, if one of the
+erroneous conditions above applies, or the _result value_.
+
+## Type Conversions and Unification
+
+Values given in configuration may not always match the expectations of the
+operations applied to them or to the calling application. In such situations,
+automatic type conversion is attempted as a convenience to the user.
+
+Along with conversions to a _specified_ type, it is sometimes necessary to
+ensure that a selection of values are all of the _same_ type, without any
+constraint on which type that is. This is the process of _type unification_,
+which attempts to find the most general type that all of the given types can
+be converted to.
+
+Both type conversions and unification are defined in the syntax-agnostic
+model to ensure consistency of behavior between syntaxes.
+
+Type conversions are broadly characterized into two categories: _safe_ and
+_unsafe_. A conversion is "safe" if any distinct value of the source type
+has a corresponding distinct value in the target type. A conversion is
+"unsafe" if either the target type values are _not_ distinct (information
+may be lost in conversion) or if some values of the source type do not have
+any corresponding value in the target type. An unsafe conversion may result
+in an error.
+
+A given type can always be converted to itself, which is a no-op.
+
+### Conversion of Null Values
+
+All null values are safely convertable to a null value of any other type,
+regardless of other type-specific rules specified in the sections below.
+
+### Conversion to and from the Dynamic Pseudo-type
+
+Conversion _from_ the dynamic pseudo-type _to_ any other type always succeeds,
+producing an unknown value of the target type.
+
+Conversion of any value _to_ the dynamic pseudo-type is a no-op. The result
+is the input value, verbatim. This is the only situation where the conversion
+result value is not of the given target type.
+
+### Primitive Type Conversions
+
+Bidirectional conversions are available between the string and number types,
+and between the string and boolean types.
+
+The bool value true corresponds to the string containing the characters "true",
+while the bool value false corresponds to the string containing the characters
+"false". Conversion from bool to string is safe, while the converse is
+unsafe. The strings "1" and "0" are alternative string representations
+of true and false respectively. It is an error to convert a string other than
+the four in this paragraph to type bool.
+
+A number value is converted to string by translating its integer portion
+into a sequence of decimal digits (`0` through `9`), and then if it has a
+non-zero fractional part, a period `.` followed by a sequence of decimal
+digits representing its fractional part. No exponent portion is included.
+The number is converted at its full precision. Conversion from number to
+string is safe.
+
+A string is converted to a number value by reversing the above mapping.
+No exponent portion is allowed. Conversion from string to number is unsafe.
+It is an error to convert a string that does not comply with the expected
+syntax to type number.
+
+No direct conversion is available between the bool and number types.
+
+### Collection and Structural Type Conversions
+
+Conversion from set types to list types is _safe_, as long as their
+element types are safely convertable. If the element types are _unsafely_
+convertable, then the collection conversion is also unsafe. Each set element
+becomes a corresponding list element, in an undefined order. Although no
+particular ordering is required, implementations _should_ produce list
+elements in a consistent order for a given input set, as a convenience
+to calling applications.
+
+Conversion from list types to set types is _unsafe_, as long as their element
+types are convertable. Each distinct list item becomes a distinct set item.
+If two list items are equal, one of the two is lost in the conversion.
+
+Conversion from tuple types to list types permitted if all of the
+tuple element types are convertable to the target list element type.
+The safety of the conversion depends on the safety of each of the element
+conversions. Each element in turn is converted to the list element type,
+producing a list of identical length.
+
+Conversion from tuple types to set types is permitted, behaving as if the
+tuple type was first converted to a list of the same element type and then
+that list converted to the target set type.
+
+Conversion from object types to map types is permitted if all of the object
+attribute types are convertable to the target map element type. The safety
+of the conversion depends on the safety of each of the attribute conversions.
+Each attribute in turn is converted to the map element type, and map element
+keys are set to the name of each corresponding object attribute.
+
+Conversion from list and set types to tuple types is permitted, following
+the opposite steps as the converse conversions. Such conversions are _unsafe_.
+It is an error to convert a list or set to a tuple type whose number of
+elements does not match the list or set length.
+
+Conversion from map types to object types is permitted if each map key
+corresponds to an attribute in the target object type. It is an error to
+convert from a map value whose set of keys does not exactly match the target
+type's attributes. The conversion takes the opposite steps of the converse
+conversion.
+
+Conversion from one object type to another is permitted as long as the
+common attribute names have convertable types. Any attribute present in the
+target type but not in the source type is populated with a null value of
+the appropriate type.
+
+Conversion from one tuple type to another is permitted as long as the
+tuples have the same length and the elements have convertable types.
+
+### Type Unification
+
+Type unification is an operation that takes a list of types and attempts
+to find a single type to which they can all be converted. Since some
+type pairs have bidirectional conversions, preference is given to _safe_
+conversions. In technical terms, all possible types are arranged into
+a lattice, from which a most general supertype is selected where possible.
+
+The type resulting from type unification may be one of the input types, or
+it may be an entirely new type produced by combination of two or more
+input types.
+
+The following rules do not guarantee a valid result. In addition to these
+rules, unification fails if any of the given types are not convertable
+(per the above rules) to the selected result type.
+
+The following unification rules apply transitively. That is, if a rule is
+defined from A to B, and one from B to C, then A can unify to C.
+
+Number and bool types both unify with string by preferring string.
+
+Two collection types of the same kind unify according to the unification
+of their element types.
+
+List and set types unify by preferring the list type.
+
+Map and object types unify by preferring the object type.
+
+List, set and tuple types unify by preferring the tuple type.
+
+The dynamic pseudo-type unifies with any other type by selecting that other
+type. The dynamic pseudo-type is the result type only if _all_ input types
+are the dynamic pseudo-type.
+
+Two object types unify by constructing a new type whose attributes are
+the union of those of the two input types. Any common attributes themselves
+have their types unified.
+
+Two tuple types of the same length unify constructing a new type of the
+same length whose elements are the unification of the corresponding elements
+in the two input types.
+
+## Static Analysis
+
+In most applications, full expression evaluation is sufficient for understanding
+the provided configuration. However, some specialized applications require more
+direct access to the physical structures in the expressions, which can for
+example allow the construction of new language constructs in terms of the
+existing syntax elements.
+
+Since static analysis analyses the physical structure of configuration, the
+details will vary depending on syntax. Each syntax must decide which of its
+physical structures corresponds to the following analyses, producing error
+diagnostics if they are applied to inappropriate expressions.
+
+The following are the required static analysis functions:
+
+- **Static List**: Require list/tuple construction syntax to be used and
+ return a list of expressions for each of the elements given.
+
+- **Static Map**: Require map/object construction syntax to be used and
+ return a list of key/value pairs -- both expressions -- for each of
+ the elements given. The usual constraint that a map key must be a string
+ must not apply to this analysis, thus allowing applications to interpret
+ arbitrary keys as they see fit.
+
+- **Static Call**: Require function call syntax to be used and return an
+ object describing the called function name and a list of expressions
+ representing each of the call arguments.
+
+- **Static Traversal**: Require a reference to a symbol in the variable
+ scope and return a description of the path from the root scope to the
+ accessed attribute or index.
+
+The intent of a calling application using these features is to require a more
+rigid interpretation of the configuration than in expression evaluation.
+Syntax implementations should make use of the extra contextual information
+provided in order to make an intuitive mapping onto the constructs of the
+underlying syntax, possibly interpreting the expression slightly differently
+than it would be interpreted in normal evaluation.
+
+Each syntax must define which of its expression elements each of the analyses
+above applies to, and how those analyses behave given those expression elements.
+
+## Implementation Considerations
+
+Implementations of this specification are free to adopt any strategy that
+produces behavior consistent with the specification. This non-normative
+section describes some possible implementation strategies that are consistent
+with the goals of this specification.
+
+### Language-agnosticism
+
+The language-agnosticism of this specification assumes that certain behaviors
+are implemented separately for each syntax:
+
+- Matching of a body schema with the physical elements of a body in the
+ source language, to determine correspondence between physical constructs
+ and schema elements.
+
+- Implementing the _dynamic attributes_ body processing mode by either
+ interpreting all physical constructs as attributes or producing an error
+ if non-attribute constructs are present.
+
+- Providing an evaluation function for all possible expressions that produces
+ a value given an evaluation context.
+
+- Providing the static analysis functionality described above in a manner that
+ makes sense within the convention of the syntax.
+
+The suggested implementation strategy is to use an implementation language's
+closest concept to an _abstract type_, _virtual type_ or _interface type_
+to represent both Body and Expression. Each language-specific implementation
+can then provide an implementation of each of these types wrapping AST nodes
+or other physical constructs from the language parser.
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/static_expr.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/static_expr.go
new file mode 100644
index 00000000000..e14d7f890ac
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/static_expr.go
@@ -0,0 +1,43 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+type staticExpr struct {
+ val cty.Value
+ rng Range
+}
+
+// StaticExpr returns an Expression that always evaluates to the given value.
+//
+// This is useful to substitute default values for expressions that are
+// not explicitly given in configuration and thus would otherwise have no
+// Expression to return.
+//
+// Since expressions are expected to have a source range, the caller must
+// provide one. Ideally this should be a real source range, but it can
+// be a synthetic one (with an empty-string filename) if no suitable range
+// is available.
+func StaticExpr(val cty.Value, rng Range) Expression {
+ return staticExpr{val, rng}
+}
+
+func (e staticExpr) Value(ctx *EvalContext) (cty.Value, Diagnostics) {
+ return e.val, nil
+}
+
+func (e staticExpr) Variables() []Traversal {
+ return nil
+}
+
+func (e staticExpr) Range() Range {
+ return e.rng
+}
+
+func (e staticExpr) StartRange() Range {
+ return e.rng
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/structure.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/structure.go
new file mode 100644
index 00000000000..2bdf579d1d3
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/structure.go
@@ -0,0 +1,154 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// File is the top-level node that results from parsing a HCL file.
+type File struct {
+ Body Body
+ Bytes []byte
+
+ // Nav is used to integrate with the "hcled" editor integration package,
+ // and with diagnostic information formatters. It is not for direct use
+ // by a calling application.
+ Nav interface{}
+}
+
+// Block represents a nested block within a Body.
+type Block struct {
+ Type string
+ Labels []string
+ Body Body
+
+ DefRange Range // Range that can be considered the "definition" for seeking in an editor
+ TypeRange Range // Range for the block type declaration specifically.
+ LabelRanges []Range // Ranges for the label values specifically.
+}
+
+// Blocks is a sequence of Block.
+type Blocks []*Block
+
+// Attributes is a set of attributes keyed by their names.
+type Attributes map[string]*Attribute
+
+// Body is a container for attributes and blocks. It serves as the primary
+// unit of hierarchical structure within configuration.
+//
+// The content of a body cannot be meaningfully interpreted without a schema,
+// so Body represents the raw body content and has methods that allow the
+// content to be extracted in terms of a given schema.
+type Body interface {
+ // Content verifies that the entire body content conforms to the given
+ // schema and then returns it, and/or returns diagnostics. The returned
+ // body content is valid if non-nil, regardless of whether Diagnostics
+ // are provided, but diagnostics should still be eventually shown to
+ // the user.
+ Content(schema *BodySchema) (*BodyContent, Diagnostics)
+
+ // PartialContent is like Content except that it permits the configuration
+ // to contain additional blocks or attributes not specified in the
+ // schema. If any are present, the returned Body is non-nil and contains
+ // the remaining items from the body that were not selected by the schema.
+ PartialContent(schema *BodySchema) (*BodyContent, Body, Diagnostics)
+
+ // JustAttributes attempts to interpret all of the contents of the body
+ // as attributes, allowing for the contents to be accessed without a priori
+ // knowledge of the structure.
+ //
+ // The behavior of this method depends on the body's source language.
+ // Some languages, like JSON, can't distinguish between attributes and
+ // blocks without schema hints, but for languages that _can_ error
+ // diagnostics will be generated if any blocks are present in the body.
+ //
+ // Diagnostics may be produced for other reasons too, such as duplicate
+ // declarations of the same attribute.
+ JustAttributes() (Attributes, Diagnostics)
+
+ // MissingItemRange returns a range that represents where a missing item
+ // might hypothetically be inserted. This is used when producing
+ // diagnostics about missing required attributes or blocks. Not all bodies
+ // will have an obvious single insertion point, so the result here may
+ // be rather arbitrary.
+ MissingItemRange() Range
+}
+
+// BodyContent is the result of applying a BodySchema to a Body.
+type BodyContent struct {
+ Attributes Attributes
+ Blocks Blocks
+
+ MissingItemRange Range
+}
+
+// Attribute represents an attribute from within a body.
+type Attribute struct {
+ Name string
+ Expr Expression
+
+ Range Range
+ NameRange Range
+}
+
+// Expression is a literal value or an expression provided in the
+// configuration, which can be evaluated within a scope to produce a value.
+type Expression interface {
+ // Value returns the value resulting from evaluating the expression
+ // in the given evaluation context.
+ //
+ // The context may be nil, in which case the expression may contain
+ // only constants and diagnostics will be produced for any non-constant
+ // sub-expressions. (The exact definition of this depends on the source
+ // language.)
+ //
+ // The context may instead be set but have either its Variables or
+ // Functions maps set to nil, in which case only use of these features
+ // will return diagnostics.
+ //
+ // Different diagnostics are provided depending on whether the given
+ // context maps are nil or empty. In the former case, the message
+ // tells the user that variables/functions are not permitted at all,
+ // while in the latter case usage will produce a "not found" error for
+ // the specific symbol in question.
+ Value(ctx *EvalContext) (cty.Value, Diagnostics)
+
+ // Variables returns a list of variables referenced in the receiving
+ // expression. These are expressed as absolute Traversals, so may include
+ // additional information about how the variable is used, such as
+ // attribute lookups, which the calling application can potentially use
+ // to only selectively populate the scope.
+ Variables() []Traversal
+
+ Range() Range
+ StartRange() Range
+}
+
+// OfType filters the receiving block sequence by block type name,
+// returning a new block sequence including only the blocks of the
+// requested type.
+func (els Blocks) OfType(typeName string) Blocks {
+ ret := make(Blocks, 0)
+ for _, el := range els {
+ if el.Type == typeName {
+ ret = append(ret, el)
+ }
+ }
+ return ret
+}
+
+// ByType transforms the receiving block sequence into a map from type
+// name to block sequences of only that type.
+func (els Blocks) ByType() map[string]Blocks {
+ ret := make(map[string]Blocks)
+ for _, el := range els {
+ ty := el.Type
+ if ret[ty] == nil {
+ ret[ty] = make(Blocks, 0, 1)
+ }
+ ret[ty] = append(ret[ty], el)
+ }
+ return ret
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/structure_at_pos.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/structure_at_pos.go
new file mode 100644
index 00000000000..62aba139f09
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/structure_at_pos.go
@@ -0,0 +1,120 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+// -----------------------------------------------------------------------------
+// The methods in this file all have the general pattern of making a best-effort
+// to find one or more constructs that contain a given source position.
+//
+// These all operate by delegating to an optional method of the same name and
+// signature on the file's root body, allowing each syntax to potentially
+// provide its own implementations of these. For syntaxes that don't implement
+// them, the result is always nil.
+// -----------------------------------------------------------------------------
+
+// BlocksAtPos attempts to find all of the blocks that contain the given
+// position, ordered so that the outermost block is first and the innermost
+// block is last. This is a best-effort method that may not be able to produce
+// a complete result for all positions or for all HCL syntaxes.
+//
+// If the returned slice is non-empty, the first element is guaranteed to
+// represent the same block as would be the result of OutermostBlockAtPos and
+// the last element the result of InnermostBlockAtPos. However, the
+// implementation may return two different objects describing the same block,
+// so comparison by pointer identity is not possible.
+//
+// The result is nil if no blocks at all contain the given position.
+func (f *File) BlocksAtPos(pos Pos) []*Block {
+ // The root body of the file must implement this interface in order
+ // to support BlocksAtPos.
+ type Interface interface {
+ BlocksAtPos(pos Pos) []*Block
+ }
+
+ impl, ok := f.Body.(Interface)
+ if !ok {
+ return nil
+ }
+ return impl.BlocksAtPos(pos)
+}
+
+// OutermostBlockAtPos attempts to find a top-level block in the receiving file
+// that contains the given position. This is a best-effort method that may not
+// be able to produce a result for all positions or for all HCL syntaxes.
+//
+// The result is nil if no single block could be selected for any reason.
+func (f *File) OutermostBlockAtPos(pos Pos) *Block {
+ // The root body of the file must implement this interface in order
+ // to support OutermostBlockAtPos.
+ type Interface interface {
+ OutermostBlockAtPos(pos Pos) *Block
+ }
+
+ impl, ok := f.Body.(Interface)
+ if !ok {
+ return nil
+ }
+ return impl.OutermostBlockAtPos(pos)
+}
+
+// InnermostBlockAtPos attempts to find the most deeply-nested block in the
+// receiving file that contains the given position. This is a best-effort
+// method that may not be able to produce a result for all positions or for
+// all HCL syntaxes.
+//
+// The result is nil if no single block could be selected for any reason.
+func (f *File) InnermostBlockAtPos(pos Pos) *Block {
+ // The root body of the file must implement this interface in order
+ // to support InnermostBlockAtPos.
+ type Interface interface {
+ InnermostBlockAtPos(pos Pos) *Block
+ }
+
+ impl, ok := f.Body.(Interface)
+ if !ok {
+ return nil
+ }
+ return impl.InnermostBlockAtPos(pos)
+}
+
+// OutermostExprAtPos attempts to find an expression in the receiving file
+// that contains the given position. This is a best-effort method that may not
+// be able to produce a result for all positions or for all HCL syntaxes.
+//
+// Since expressions are often nested inside one another, this method returns
+// the outermost "root" expression that is not contained by any other.
+//
+// The result is nil if no single expression could be selected for any reason.
+func (f *File) OutermostExprAtPos(pos Pos) Expression {
+ // The root body of the file must implement this interface in order
+ // to support OutermostExprAtPos.
+ type Interface interface {
+ OutermostExprAtPos(pos Pos) Expression
+ }
+
+ impl, ok := f.Body.(Interface)
+ if !ok {
+ return nil
+ }
+ return impl.OutermostExprAtPos(pos)
+}
+
+// AttributeAtPos attempts to find an attribute definition in the receiving
+// file that contains the given position. This is a best-effort method that may
+// not be able to produce a result for all positions or for all HCL syntaxes.
+//
+// The result is nil if no single attribute could be selected for any reason.
+func (f *File) AttributeAtPos(pos Pos) *Attribute {
+ // The root body of the file must implement this interface in order
+ // to support OutermostExprAtPos.
+ type Interface interface {
+ AttributeAtPos(pos Pos) *Attribute
+ }
+
+ impl, ok := f.Body.(Interface)
+ if !ok {
+ return nil
+ }
+ return impl.AttributeAtPos(pos)
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/tools.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/tools.go
new file mode 100644
index 00000000000..e8c42ad1f65
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/tools.go
@@ -0,0 +1,11 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build tools
+// +build tools
+
+package hcl
+
+import (
+ _ "golang.org/x/tools/cmd/stringer"
+)
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/traversal.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/traversal.go
new file mode 100644
index 00000000000..540dde7ec72
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/traversal.go
@@ -0,0 +1,296 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// A Traversal is a description of traversing through a value through a
+// series of operations such as attribute lookup, index lookup, etc.
+//
+// It is used to look up values in scopes, for example.
+//
+// The traversal operations are implementations of interface Traverser.
+// This is a closed set of implementations, so the interface cannot be
+// implemented from outside this package.
+//
+// A traversal can be absolute (its first value is a symbol name) or relative
+// (starts from an existing value).
+type Traversal []Traverser
+
+// TraversalJoin appends a relative traversal to an absolute traversal to
+// produce a new absolute traversal.
+func TraversalJoin(abs Traversal, rel Traversal) Traversal {
+ if abs.IsRelative() {
+ panic("first argument to TraversalJoin must be absolute")
+ }
+ if !rel.IsRelative() {
+ panic("second argument to TraversalJoin must be relative")
+ }
+
+ ret := make(Traversal, len(abs)+len(rel))
+ copy(ret, abs)
+ copy(ret[len(abs):], rel)
+ return ret
+}
+
+// TraverseRel applies the receiving traversal to the given value, returning
+// the resulting value. This is supported only for relative traversals,
+// and will panic if applied to an absolute traversal.
+func (t Traversal) TraverseRel(val cty.Value) (cty.Value, Diagnostics) {
+ if !t.IsRelative() {
+ panic("can't use TraverseRel on an absolute traversal")
+ }
+
+ current := val
+ var diags Diagnostics
+ for _, tr := range t {
+ var newDiags Diagnostics
+ current, newDiags = tr.TraversalStep(current)
+ diags = append(diags, newDiags...)
+ if newDiags.HasErrors() {
+ return cty.DynamicVal, diags
+ }
+ }
+ return current, diags
+}
+
+// TraverseAbs applies the receiving traversal to the given eval context,
+// returning the resulting value. This is supported only for absolute
+// traversals, and will panic if applied to a relative traversal.
+func (t Traversal) TraverseAbs(ctx *EvalContext) (cty.Value, Diagnostics) {
+ if t.IsRelative() {
+ panic("can't use TraverseAbs on a relative traversal")
+ }
+
+ split := t.SimpleSplit()
+ root := split.Abs[0].(TraverseRoot)
+ name := root.Name
+
+ thisCtx := ctx
+ hasNonNil := false
+ for thisCtx != nil {
+ if thisCtx.Variables == nil {
+ thisCtx = thisCtx.parent
+ continue
+ }
+ hasNonNil = true
+ val, exists := thisCtx.Variables[name]
+ if exists {
+ return split.Rel.TraverseRel(val)
+ }
+ thisCtx = thisCtx.parent
+ }
+
+ if !hasNonNil {
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: "Variables not allowed",
+ Detail: "Variables may not be used here.",
+ Subject: &root.SrcRange,
+ },
+ }
+ }
+
+ suggestions := make([]string, 0, len(ctx.Variables))
+ thisCtx = ctx
+ for thisCtx != nil {
+ for k := range thisCtx.Variables {
+ suggestions = append(suggestions, k)
+ }
+ thisCtx = thisCtx.parent
+ }
+ suggestion := nameSuggestion(name, suggestions)
+ if suggestion != "" {
+ suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
+ }
+
+ return cty.DynamicVal, Diagnostics{
+ {
+ Severity: DiagError,
+ Summary: "Unknown variable",
+ Detail: fmt.Sprintf("There is no variable named %q.%s", name, suggestion),
+ Subject: &root.SrcRange,
+ },
+ }
+}
+
+// IsRelative returns true if the receiver is a relative traversal, or false
+// otherwise.
+func (t Traversal) IsRelative() bool {
+ if len(t) == 0 {
+ return true
+ }
+ if _, firstIsRoot := t[0].(TraverseRoot); firstIsRoot {
+ return false
+ }
+ return true
+}
+
+// SimpleSplit returns a TraversalSplit where the name lookup is the absolute
+// part and the remainder is the relative part. Supported only for
+// absolute traversals, and will panic if applied to a relative traversal.
+//
+// This can be used by applications that have a relatively-simple variable
+// namespace where only the top-level is directly populated in the scope, with
+// everything else handled by relative lookups from those initial values.
+func (t Traversal) SimpleSplit() TraversalSplit {
+ if t.IsRelative() {
+ panic("can't use SimpleSplit on a relative traversal")
+ }
+ return TraversalSplit{
+ Abs: t[0:1],
+ Rel: t[1:],
+ }
+}
+
+// RootName returns the root name for a absolute traversal. Will panic if
+// called on a relative traversal.
+func (t Traversal) RootName() string {
+ if t.IsRelative() {
+ panic("can't use RootName on a relative traversal")
+
+ }
+ return t[0].(TraverseRoot).Name
+}
+
+// SourceRange returns the source range for the traversal.
+func (t Traversal) SourceRange() Range {
+ if len(t) == 0 {
+ // Nothing useful to return here, but we'll return something
+ // that's correctly-typed at least.
+ return Range{}
+ }
+
+ return RangeBetween(t[0].SourceRange(), t[len(t)-1].SourceRange())
+}
+
+// TraversalSplit represents a pair of traversals, the first of which is
+// an absolute traversal and the second of which is relative to the first.
+//
+// This is used by calling applications that only populate prefixes of the
+// traversals in the scope, with Abs representing the part coming from the
+// scope and Rel representing the remaining steps once that part is
+// retrieved.
+type TraversalSplit struct {
+ Abs Traversal
+ Rel Traversal
+}
+
+// TraverseAbs traverses from a scope to the value resulting from the
+// absolute traversal.
+func (t TraversalSplit) TraverseAbs(ctx *EvalContext) (cty.Value, Diagnostics) {
+ return t.Abs.TraverseAbs(ctx)
+}
+
+// TraverseRel traverses from a given value, assumed to be the result of
+// TraverseAbs on some scope, to a final result for the entire split traversal.
+func (t TraversalSplit) TraverseRel(val cty.Value) (cty.Value, Diagnostics) {
+ return t.Rel.TraverseRel(val)
+}
+
+// Traverse is a convenience function to apply TraverseAbs followed by
+// TraverseRel.
+func (t TraversalSplit) Traverse(ctx *EvalContext) (cty.Value, Diagnostics) {
+ v1, diags := t.TraverseAbs(ctx)
+ if diags.HasErrors() {
+ return cty.DynamicVal, diags
+ }
+ v2, newDiags := t.TraverseRel(v1)
+ diags = append(diags, newDiags...)
+ return v2, diags
+}
+
+// Join concatenates together the Abs and Rel parts to produce a single
+// absolute traversal.
+func (t TraversalSplit) Join() Traversal {
+ return TraversalJoin(t.Abs, t.Rel)
+}
+
+// RootName returns the root name for the absolute part of the split.
+func (t TraversalSplit) RootName() string {
+ return t.Abs.RootName()
+}
+
+// A Traverser is a step within a Traversal.
+type Traverser interface {
+ TraversalStep(cty.Value) (cty.Value, Diagnostics)
+ SourceRange() Range
+ isTraverserSigil() isTraverser
+}
+
+// Embed this in a struct to declare it as a Traverser
+type isTraverser struct {
+}
+
+func (tr isTraverser) isTraverserSigil() isTraverser {
+ return isTraverser{}
+}
+
+// TraverseRoot looks up a root name in a scope. It is used as the first step
+// of an absolute Traversal, and cannot itself be traversed directly.
+type TraverseRoot struct {
+ isTraverser
+ Name string
+ SrcRange Range
+}
+
+// TraversalStep on a TraverseName immediately panics, because absolute
+// traversals cannot be directly traversed.
+func (tn TraverseRoot) TraversalStep(cty.Value) (cty.Value, Diagnostics) {
+ panic("Cannot traverse an absolute traversal")
+}
+
+func (tn TraverseRoot) SourceRange() Range {
+ return tn.SrcRange
+}
+
+// TraverseAttr looks up an attribute in its initial value.
+type TraverseAttr struct {
+ isTraverser
+ Name string
+ SrcRange Range
+}
+
+func (tn TraverseAttr) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
+ return GetAttr(val, tn.Name, &tn.SrcRange)
+}
+
+func (tn TraverseAttr) SourceRange() Range {
+ return tn.SrcRange
+}
+
+// TraverseIndex applies the index operation to its initial value.
+type TraverseIndex struct {
+ isTraverser
+ Key cty.Value
+ SrcRange Range
+}
+
+func (tn TraverseIndex) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
+ return Index(val, tn.Key, &tn.SrcRange)
+}
+
+func (tn TraverseIndex) SourceRange() Range {
+ return tn.SrcRange
+}
+
+// TraverseSplat applies the splat operation to its initial value.
+type TraverseSplat struct {
+ isTraverser
+ Each Traversal
+ SrcRange Range
+}
+
+func (tn TraverseSplat) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
+ panic("TraverseSplat not yet implemented")
+}
+
+func (tn TraverseSplat) SourceRange() Range {
+ return tn.SrcRange
+}
diff --git a/hack/tools/vendor/github.com/hashicorp/hcl/v2/traversal_for_expr.go b/hack/tools/vendor/github.com/hashicorp/hcl/v2/traversal_for_expr.go
new file mode 100644
index 00000000000..d3cb4507ef5
--- /dev/null
+++ b/hack/tools/vendor/github.com/hashicorp/hcl/v2/traversal_for_expr.go
@@ -0,0 +1,127 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl
+
+// AbsTraversalForExpr attempts to interpret the given expression as
+// an absolute traversal, or returns error diagnostic(s) if that is
+// not possible for the given expression.
+//
+// A particular Expression implementation can support this function by
+// offering a method called AsTraversal that takes no arguments and
+// returns either a valid absolute traversal or nil to indicate that
+// no traversal is possible. Alternatively, an implementation can support
+// UnwrapExpression to delegate handling of this function to a wrapped
+// Expression object.
+//
+// In most cases the calling application is interested in the value
+// that results from an expression, but in rarer cases the application
+// needs to see the name of the variable and subsequent
+// attributes/indexes itself, for example to allow users to give references
+// to the variables themselves rather than to their values. An implementer
+// of this function should at least support attribute and index steps.
+func AbsTraversalForExpr(expr Expression) (Traversal, Diagnostics) {
+ type asTraversal interface {
+ AsTraversal() Traversal
+ }
+
+ physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
+ _, supported := expr.(asTraversal)
+ return supported
+ })
+
+ if asT, supported := physExpr.(asTraversal); supported {
+ if traversal := asT.AsTraversal(); traversal != nil {
+ return traversal, nil
+ }
+ }
+ return nil, Diagnostics{
+ &Diagnostic{
+ Severity: DiagError,
+ Summary: "Invalid expression",
+ Detail: "A single static variable reference is required: only attribute access and indexing with constant keys. No calculations, function calls, template expressions, etc are allowed here.",
+ Subject: expr.Range().Ptr(),
+ },
+ }
+}
+
+// RelTraversalForExpr is similar to AbsTraversalForExpr but it returns
+// a relative traversal instead. Due to the nature of HCL expressions, the
+// first element of the returned traversal is always a TraverseAttr, and
+// then it will be followed by zero or more other expressions.
+//
+// Any expression accepted by AbsTraversalForExpr is also accepted by
+// RelTraversalForExpr.
+func RelTraversalForExpr(expr Expression) (Traversal, Diagnostics) {
+ traversal, diags := AbsTraversalForExpr(expr)
+ if len(traversal) > 0 {
+ ret := make(Traversal, len(traversal))
+ copy(ret, traversal)
+ root := traversal[0].(TraverseRoot)
+ ret[0] = TraverseAttr{
+ Name: root.Name,
+ SrcRange: root.SrcRange,
+ }
+ return ret, diags
+ }
+ return traversal, diags
+}
+
+// ExprAsKeyword attempts to interpret the given expression as a static keyword,
+// returning the keyword string if possible, and the empty string if not.
+//
+// A static keyword, for the sake of this function, is a single identifier.
+// For example, the following attribute has an expression that would produce
+// the keyword "foo":
+//
+// example = foo
+//
+// This function is a variant of AbsTraversalForExpr, which uses the same
+// interface on the given expression. This helper constrains the result
+// further by requiring only a single root identifier.
+//
+// This function is intended to be used with the following idiom, to recognize
+// situations where one of a fixed set of keywords is required and arbitrary
+// expressions are not allowed:
+//
+// switch hcl.ExprAsKeyword(expr) {
+// case "allow":
+// // (take suitable action for keyword "allow")
+// case "deny":
+// // (take suitable action for keyword "deny")
+// default:
+// diags = append(diags, &hcl.Diagnostic{
+// // ... "invalid keyword" diagnostic message ...
+// })
+// }
+//
+// The above approach will generate the same message for both the use of an
+// unrecognized keyword and for not using a keyword at all, which is usually
+// reasonable if the message specifies that the given value must be a keyword
+// from that fixed list.
+//
+// Note that in the native syntax the keywords "true", "false", and "null" are
+// recognized as literal values during parsing and so these reserved words
+// cannot not be accepted as keywords by this function.
+//
+// Since interpreting an expression as a keyword bypasses usual expression
+// evaluation, it should be used sparingly for situations where e.g. one of
+// a fixed set of keywords is used in a structural way in a special attribute
+// to affect the further processing of a block.
+func ExprAsKeyword(expr Expression) string {
+ type asTraversal interface {
+ AsTraversal() Traversal
+ }
+
+ physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
+ _, supported := expr.(asTraversal)
+ return supported
+ })
+
+ if asT, supported := physExpr.(asTraversal); supported {
+ if traversal := asT.AsTraversal(); len(traversal) == 1 {
+ return traversal.RootName()
+ }
+ }
+ return ""
+}
diff --git a/hack/tools/vendor/github.com/jgautheron/goconst/README.md b/hack/tools/vendor/github.com/jgautheron/goconst/README.md
index 727974d001d..b08d7b7d1bb 100644
--- a/hack/tools/vendor/github.com/jgautheron/goconst/README.md
+++ b/hack/tools/vendor/github.com/jgautheron/goconst/README.md
@@ -8,6 +8,16 @@ There are obvious benefits to using constants instead of repeating strings, most
While this could be considered a beginner mistake, across time, multiple packages and large codebases, some repetition could have slipped in.
+### How it works
+
+goconst detects string (and optionally number) literals that appear multiple times and could be replaced by a constant.
+
+A few things to keep in mind:
+
+- **Exact literal matching** — goconst compares complete, unquoted literal values. Repeated substrings inside larger strings are not detected (e.g., a shared prefix across two different string literals will not be reported).
+- **`const` declarations are skipped by default** — constant values are only analyzed when `-match-constant` (match strings against existing constants) or `-find-duplicates` (find constants sharing the same value) is enabled.
+- **String length is measured in runes**, not bytes, so multi-byte Unicode characters are counted correctly against `-min-length`.
+
### Get Started
$ go install github.com/jgautheron/goconst/cmd/goconst@latest
@@ -30,6 +40,7 @@ Flags:
-match-constant look for existing constants matching the strings
-find-duplicates look for constants with identical values
-eval-const-expr enable evaluation of constant expressions (e.g., Prefix + "suffix")
+ -ignore-calls ignore string literals in calls to these functions (comma separated)
-numbers search also for duplicated numbers
-min minimum value, only works with -numbers
-max maximum value, only works with -numbers
@@ -45,6 +56,7 @@ Examples:
goconst -numbers -min 60 -max 512 .
goconst -min-occurrences 5 $(go list -m -f '{{.Dir}}')
goconst -eval-const-expr -match-constant . # Matches constant expressions like Prefix + "suffix"
+ goconst -ignore-calls slog.Info,slog.Warn,fmt.Errorf ./... # Ignore strings in logging/error calls
```
### Development
diff --git a/hack/tools/vendor/github.com/jgautheron/goconst/api.go b/hack/tools/vendor/github.com/jgautheron/goconst/api.go
index 10cece15154..5e9e35e74c0 100644
--- a/hack/tools/vendor/github.com/jgautheron/goconst/api.go
+++ b/hack/tools/vendor/github.com/jgautheron/goconst/api.go
@@ -45,6 +45,9 @@ type Config struct {
FindDuplicates bool
// EvalConstExpressions enables evaluation of constant expressions like Prefix + "suffix"
EvalConstExpressions bool
+ // IgnoreFunctions is a list of function names whose string arguments should be ignored.
+ // Supports direct calls (e.g., "println") and one-level qualified calls (e.g., "slog.Info").
+ IgnoreFunctions []string
}
// NewWithIgnorePatterns creates a new instance of the parser with support for multiple ignore patterns.
@@ -108,6 +111,10 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
cfg.ExcludeTypes,
)
+ if len(cfg.IgnoreFunctions) > 0 {
+ p.SetIgnoreFunctions(cfg.IgnoreFunctions)
+ }
+
// Pre-allocate slice based on estimated result size
expectedIssues := len(files) * 5 // Assuming average of 5 issues per file
if expectedIssues > 1000 {
@@ -179,34 +186,40 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
sort.Strings(stringKeys)
- // Process strings in a predictable order for stable output
+ // Emit one issue per file where the string appears, so that
+ // path-based exclusion can independently filter each one without
+ // suppressing legitimate findings in other files.
for _, str := range stringKeys {
positions := p.strs[str]
if len(positions) == 0 {
continue
}
- // Use the first position as representative
- fi := positions[0]
+ occurrences := p.stringCount[str]
- // Create issue using the counted value to avoid recounting
- issue := Issue{
- Pos: fi.Position,
- OccurrencesCount: p.stringCount[str],
- Str: str,
- }
-
- // Check for matching constants
+ var matchingConst string
if len(p.consts) > 0 {
p.constMutex.RLock()
if csts, ok := p.consts[str]; ok && len(csts) > 0 {
- // const should be in the same package and exported
- issue.MatchingConst = csts[0].Name
+ matchingConst = csts[0].Name
}
p.constMutex.RUnlock()
}
- issueBuffer = append(issueBuffer, issue)
+ seen := make(map[string]bool)
+ for _, pos := range positions {
+ if seen[pos.Filename] {
+ continue
+ }
+ seen[pos.Filename] = true
+
+ issueBuffer = append(issueBuffer, Issue{
+ Pos: pos.Position,
+ OccurrencesCount: occurrences,
+ Str: str,
+ MatchingConst: matchingConst,
+ })
+ }
}
p.stringCountMutex.RUnlock()
diff --git a/hack/tools/vendor/github.com/jgautheron/goconst/parser.go b/hack/tools/vendor/github.com/jgautheron/goconst/parser.go
index 9505d463e65..fca43279c76 100644
--- a/hack/tools/vendor/github.com/jgautheron/goconst/parser.go
+++ b/hack/tools/vendor/github.com/jgautheron/goconst/parser.go
@@ -120,6 +120,7 @@ type Parser struct {
minLength, minOccurrences int
numberMin, numberMax int
excludeTypes map[Type]bool
+ ignoreFunctions map[string]struct{}
maxConcurrency int
evalConstExpressions bool // Whether to evaluate constant expressions
@@ -264,6 +265,24 @@ func (p *Parser) EnableBatchProcessing(batchSize int) {
}
}
+// SetIgnoreFunctions configures which function calls should have their string
+// arguments ignored. Supports direct calls (e.g., "println") and one-level
+// qualified calls (e.g., "slog.Info", "fmt.Errorf").
+func (p *Parser) SetIgnoreFunctions(names []string) {
+ if len(names) == 0 {
+ p.ignoreFunctions = nil
+ return
+ }
+ m := make(map[string]struct{}, len(names))
+ for _, name := range names {
+ name = strings.TrimSpace(name)
+ if name != "" {
+ m[name] = struct{}{}
+ }
+ }
+ p.ignoreFunctions = m
+}
+
// ParseTree will search the given path for occurrences that could be moved into constants.
// If "..." is appended, the search will be recursive.
//
@@ -881,4 +900,7 @@ const (
Return
// Call represents a string passed as an argument to a function call (e.g., f("foo"))
Call
+ // CompositeLit represents a string inside a composite literal
+ // (e.g., []string{"foo"}, map[string]string{"k": "v"}, MyStruct{Field: "foo"})
+ CompositeLit
)
diff --git a/hack/tools/vendor/github.com/jgautheron/goconst/visitor.go b/hack/tools/vendor/github.com/jgautheron/goconst/visitor.go
index 350e3ae627f..a788931500a 100644
--- a/hack/tools/vendor/github.com/jgautheron/goconst/visitor.go
+++ b/hack/tools/vendor/github.com/jgautheron/goconst/visitor.go
@@ -8,6 +8,7 @@ import (
"regexp"
"strconv"
"strings"
+ "unicode/utf8"
)
// treeVisitor is used to walk the AST and find strings that could be constants.
@@ -110,17 +111,68 @@ func (v *treeVisitor) Visit(node ast.Node) ast.Visitor {
// fn("http://")
case *ast.CallExpr:
- for _, item := range t.Args {
- lit, ok := item.(*ast.BasicLit)
- if ok && v.isSupported(lit.Kind) {
- v.addString(lit.Value, lit.Pos(), Call)
+ if !v.shouldIgnoreCall(t) {
+ for _, item := range t.Args {
+ lit, ok := item.(*ast.BasicLit)
+ if ok && v.isSupported(lit.Kind) {
+ v.addString(lit.Value, lit.Pos(), Call)
+ }
}
}
+
+ // []string{"foo"}, map[string]string{"k": "v"}, struct{A string}{A: "foo"}
+ case *ast.CompositeLit:
+ for _, item := range t.Elts {
+ v.addCompositeLiteralElement(item)
+ }
}
return v
}
+func (v *treeVisitor) addCompositeLiteralElement(node ast.Expr) {
+ if lit, ok := node.(*ast.BasicLit); ok && v.isSupported(lit.Kind) {
+ v.addString(lit.Value, lit.Pos(), CompositeLit)
+ return
+ }
+
+ kv, ok := node.(*ast.KeyValueExpr)
+ if !ok {
+ return
+ }
+
+ if keyLit, ok := kv.Key.(*ast.BasicLit); ok && v.isSupported(keyLit.Kind) {
+ v.addString(keyLit.Value, keyLit.Pos(), CompositeLit)
+ }
+
+ if valueLit, ok := kv.Value.(*ast.BasicLit); ok && v.isSupported(valueLit.Kind) {
+ v.addString(valueLit.Value, valueLit.Pos(), CompositeLit)
+ }
+}
+
+// shouldIgnoreCall returns true if the call expression matches a function
+// name in the ignoreFunctions set. Supports direct calls (e.g., "println")
+// and one-level qualified calls (e.g., "slog.Info").
+func (v *treeVisitor) shouldIgnoreCall(call *ast.CallExpr) bool {
+ if len(v.p.ignoreFunctions) == 0 {
+ return false
+ }
+ var name string
+ switch fn := call.Fun.(type) {
+ case *ast.Ident:
+ name = fn.Name
+ case *ast.SelectorExpr:
+ if ident, ok := fn.X.(*ast.Ident); ok {
+ name = ident.Name + "." + fn.Sel.Name
+ }
+ }
+ if name == "" {
+ return false
+ }
+ _, found := v.p.ignoreFunctions[name]
+ return found
+}
+
// addString adds a string in the map along with its position in the tree.
func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) {
// Early type exclusion check
@@ -153,7 +205,7 @@ func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) {
}
// Early length check
- if len(unquotedStr) == 0 || len(unquotedStr) < v.p.minLength {
+ if len(unquotedStr) == 0 || utf8.RuneCountInString(unquotedStr) < v.p.minLength {
return
}
@@ -175,29 +227,21 @@ func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) {
// Use interned string to reduce memory usage - identical strings share the same memory
internedStr := InternString(unquotedStr)
- // Update the count first, this is faster than appending to slices
- count := v.p.IncrementStringCount(internedStr)
-
- // Only continue if we're still adding the position to the map
- // or if count has reached threshold
- if count == 1 || count == v.p.minOccurrences {
- // Lock to safely update the shared map
- v.p.stringMutex.Lock()
- defer v.p.stringMutex.Unlock()
+ // Update the count for fast threshold checks in ProcessResults
+ v.p.IncrementStringCount(internedStr)
- _, exists := v.p.strs[internedStr]
- if !exists {
- v.p.strs[internedStr] = make([]ExtendedPos, 0, v.p.minOccurrences) // Preallocate with expected size
- }
+ // Record every occurrence so that position lists and display counts stay accurate
+ v.p.stringMutex.Lock()
+ defer v.p.stringMutex.Unlock()
- // Create an optimized position record
- newPos := ExtendedPos{
- packageName: InternString(v.packageName), // Intern the package name to reduce memory
- Position: v.fileSet.Position(pos),
- }
-
- v.p.strs[internedStr] = append(v.p.strs[internedStr], newPos)
+ if _, exists := v.p.strs[internedStr]; !exists {
+ v.p.strs[internedStr] = make([]ExtendedPos, 0, v.p.minOccurrences)
}
+
+ v.p.strs[internedStr] = append(v.p.strs[internedStr], ExtendedPos{
+ packageName: InternString(v.packageName),
+ Position: v.fileSet.Position(pos),
+ })
}
// addConst adds a const in the map along with its position in the tree.
@@ -224,7 +268,7 @@ func (v *treeVisitor) addConst(name string, val string, pos token.Pos) {
}
// Skip constants with values that would be filtered anyway
- if len(unquotedVal) < v.p.minLength {
+ if utf8.RuneCountInString(unquotedVal) < v.p.minLength {
return
}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
index 84f9c7b2c7d..3879f14aa94 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
@@ -6,8 +6,38 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
The format of this file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
but only releases after v1.0.3 properly adhere to it.
+## [Unreleased]
+
+## [1.4.0] - 2026-03-28
+### Added
+- Constructors, decomposers, and blend functions for the CSS Color Level 4 wide-gamut RGB color spaces `DisplayP3`, `A98Rgb`, `ProPhotoRgb`, and `Rec2020` (#81)
+- `XyzD50`, `Color.XyzD50`, `D50ToD65`, and `D65ToD50` for working with D50-based color spaces (#81)
+- `HexColor` now implements `fmt.Stringer`
+
+## [1.3.0] - 2025-09-08
+### Added
+- `BlendLinearRgb` (#50)
+- `DistanceRiemersma` (#52)
+- Introduce a function for sorting colors (#57)
+- YAML marshal/unmarshal support (#63)
+- Add support for OkLab and OkLch (#66)
+- Functions that use randomness now support specifying a custom source (#73)
+- Functions BlendOkLab and BlendOkLch (#70)
+
+## Changed
+- `Hex()` parsing is much faster (#78). However, it doesn't tolerate hex codes with alpha anymore (previously ignoring the alpha was unintentional).
+
+### Fixed
+- Fix bug when doing HSV/HCL blending between a gray color and non-gray color (#60)
+- Docs for HSV/HSL were updated to note that hue 360 is not allowed (#71)
+
+### Deprecated
+- `DistanceLinearRGB` is deprecated for the name `DistanceLinearRgb` which is more in-line with the rest of the library
+
## [1.2.0] - 2021-01-27
+This is the same as the v1.1.0 tag.
+
### Added
- HSLuv and HPLuv color spaces (#41, #51)
- CIE LCh(uv) color space, called `LuvLCh` in code (#51)
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/README.md b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/README.md
index 8b9bd499913..1da19f703b4 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/README.md
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/README.md
@@ -1,6 +1,7 @@
go-colorful
===========
+[](https://pkg.go.dev/github.com/lucasb-eyer/go-colorful)
[](https://goreportcard.com/report/github.com/lucasb-eyer/go-colorful)
A library for playing with colors in Go. Supports Go 1.13 onwards.
@@ -29,10 +30,12 @@ Go-Colorful stores colors in RGB and provides methods from converting these to v
- **CIE-xyY:** encodes chromacity in x and y and luminance in Y, all in [0..1]
- **CIE-L\*a\*b\*:** A *perceptually uniform* color space, i.e. distances are meaningful. L\* in [0..1] and a\*, b\* almost in [-1..1].
- **CIE-L\*u\*v\*:** Very similar to CIE-L\*a\*b\*, there is [no consensus](http://en.wikipedia.org/wiki/CIELUV#Historical_background) on which one is "better".
-- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*a\*b\*.
-- **CIE LCh(uv):** Called `LuvLCh` in code, this is a cylindrical transformation of the CIE-L\*u\*v\* color space. Like HCL above: H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*u\*v\*.
+- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [0..1] and L\* as in CIE-L\*a\*b\*.
+- **CIE LCh(uv):** Called `LuvLCh` in code, this is a cylindrical transformation of the CIE-L\*u\*v\* color space. Like HCL above: H° is in [0..360], C\* almost in [0..1] and L\* as in CIE-L\*u\*v\*.
- **HSLuv:** The better alternative to HSL, see [here](https://www.hsluv.org/) and [here](https://www.kuon.ch/post/2020-03-08-hsluv/). Hue in [0..360], Saturation and Luminance in [0..1].
-- **HPLuv:** A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv beccause it's not pastel.
+- **HPLuv:** A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv because it's not pastel.
+- **Oklab:** A perceptual color space by Björn Ottosson that improves on CIE-L\*a\*b\* with better perceptual uniformity, especially for blue hues. L in [0..1], a and b roughly in [-0.5..0.5]. See [Oklab](https://bottosson.github.io/posts/oklab/).
+- **Oklch:** The cylindrical (polar) representation of Oklab, similar to HCL. L in [0..1], C roughly in [0..0.5], h° in [0..360].
For the colorspaces where it makes sense (XYZ, Lab, Luv, HCl), the
[D65](http://en.wikipedia.org/wiki/Illuminant_D65) is used as reference white
@@ -52,14 +55,6 @@ Nice, but what's it useful for?
- Generating random colors under some constraints (e.g. colors of the same shade, or shades of one color.)
- Generating gorgeous random palettes with distinct colors of a same temperature.
-What not (yet)?
-===============
-There are a few features which are currently missing and might be useful.
-I just haven't implemented them yet because I didn't have the need for it.
-Pull requests welcome.
-
-- Sorting colors (potentially using above mentioned distances)
-
So which colorspace should I use?
=================================
It depends on what you want to do. I think the folks from *I want hue* are
@@ -103,6 +98,8 @@ c = colorful.Xyy(0.219895, 0.221839, 0.190837)
c = colorful.Lab(0.507850, 0.040585,-0.370945)
c = colorful.Luv(0.507849,-0.194172,-0.567924)
c = colorful.Hcl(276.2440, 0.373160, 0.507849)
+c = colorful.OkLab(0.577227, -0.021391, -0.104541)
+c = colorful.OkLch(0.577227, 0.106707, 258.435657)
fmt.Printf("RGB values: %v, %v, %v", c.R, c.G, c.B)
```
@@ -116,6 +113,8 @@ x, y, Y := c.Xyy()
l, a, b := c.Lab()
l, u, v := c.Luv()
h, c, l := c.Hcl()
+l, a, b = c.OkLab()
+l, c, h = c.OkLch()
```
Note that, because of Go's unfortunate choice of requiring an initial uppercase,
@@ -139,7 +138,7 @@ alpha colors, this means the RGB values are lost (set to 0) and it's impossible
to recover them. In such a case `MakeColor` will return `false` as its second value.
### Comparing colors
-In the RGB color space, the Euclidian distance between colors *doesn't* correspond
+In the RGB color space, the Euclidean distance between colors *doesn't* correspond
to visual/perceptual distance. This means that two pairs of colors which have the
same distance in RGB space can look much further apart. This is fixed by the
CIE-L\*a\*b\*, CIE-L\*u\*v\* and CIE-L\*C\*h° color spaces.
@@ -197,7 +196,7 @@ it only if you really know what you're doing. It will eat your cat.
Blending is highly connected to distance, since it basically "walks through" the
colorspace thus, if the colorspace maps distances well, the walk is "smooth".
-Colorful comes with blending functions in RGB, HSV and any of the LAB spaces.
+Colorful comes with blending functions in RGB, HSV, Oklab, Oklch, and any of the CIE-LAB spaces.
Of course, you'd rather want to use the blending functions of the LAB spaces since
these spaces map distances well but, just in case, here is an example showing
you how the blendings (`#fdffcc` to `#242a42`) are done in the various spaces:
@@ -208,7 +207,7 @@ What you see is that HSV is really bad: it adds some green, which is not present
in the original colors at all! RGB is much better, but it stays light a little
too long. LUV and LAB both hit the right lightness but LAB has a little more
color. HCL works in the same vein as HSV (both cylindrical interpolations) but
-it does it right in that there is no green appearing and the lighthness changes
+it does it right in that there is no green appearing and the lightness changes
in a linear manner.
While this seems all good, you need to know one thing: When interpolating in any
@@ -316,11 +315,11 @@ generating this picture in `doc/colorgens/colorgens.go`.
### Getting random palettes
As soon as you need to generate more than one random color, you probably want
-them to be distinguishible. Playing against an opponent which has almost the
+them to be distinguishable. Playing against an opponent which has almost the
same blue as I do is not fun. This is where random palettes can help.
These palettes are generated using an algorithm which ensures that all colors
-on the palette are as distinguishible as possible. Again, there is a `Fast`
+on the palette are as distinguishable as possible. Again, there is a `Fast`
method which works in HSV and is less perceptually uniform and a non-`Fast`
method which works in CIE spaces. For more theory on `SoftPalette`, check out
[I want hue](http://tools.medialab.sciences-po.fr/iwanthue/theory.php). Yet
@@ -372,10 +371,18 @@ from top to bottom: `Warm`, `FastWarm`, `Happy`, `FastHappy`, `Soft`,
Again, the code used for generating the above image is available as [doc/palettegens/palettegens.go](https://github.com/lucasb-eyer/go-colorful/blob/master/doc/palettegens/palettegens.go).
### Sorting colors
-TODO: Sort using dist fn.
+
+Sorting colors is not a well-defined operation. For example, {dark blue, dark red, light blue, light red} is already sorted if darker colors should precede lighter colors but would need to be re-sorted as {dark red, light red, dark blue, light blue} if longer-wavelength colors should precede shorter-wavelength colors.
+
+Go-Colorful's `Sorted` function orders a list of colors so as to minimize the average distance between adjacent colors, including between the last and the first. (`Sorted` does not necessarily find the true minimum, only a reasonably close approximation.) The following picture, drawn by [doc/colorsort/colorsort.go](https://github.com/lucasb-eyer/go-colorful/blob/master/doc/colorsort/colorsort.go), illustrates `Sorted`'s behavior:
+
+
+
+The first row represents the input: a slice of 512 randomly chosen colors. The second row shows the colors sorted in CIE-L\*C\*h° space, ordered first by lightness (L), then by hue angle (h), and finally by chroma (C). Note that distracting pinstripes permeate the colors. Sorting using *any* color space and *any* ordering of the channels yields a similar pinstriped pattern. The third row of the image was sorted using Go-Colorful's `Sorted` function. Although the colors do not appear to be in any particular order, the sequence at least appears smoother than the one sorted by channel.
+
### Using linear RGB for computations
-There are two methods for transforming RGB<->Linear RGB: a fast and almost precise one,
+There are two methods for transforming RGB⟷Linear RGB: a fast and almost precise one,
and a slow and precise one.
```go
@@ -471,11 +478,12 @@ section above.
Who?
====
-This library was developed by Lucas Beyer with contributions from
-Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli).
-
-It is now maintained by makeworld (@makeworld-the-better-one).
+This library was originally developed by Lucas Beyer, with notable
+contributions from Bastien Dejean (@baskerville), Phil Kulak (@pkulak),
+Christian Muehlhaeuser (@muesli), Scott Pakin (@spakin), and many others.
+See the [contributors list](https://github.com/lucasb-eyer/go-colorful/graphs/contributors) for the full roster.
+It is currently maintained by makeworld (@makew0rld).
## License
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go
index 2e2e49e19fc..ac697d65582 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go
@@ -2,28 +2,32 @@
package colorful
-import (
- "math/rand"
-)
-
// Creates a random dark, "warm" color through a restricted HSV space.
-func FastWarmColor() Color {
+func FastWarmColorWithRand(rand RandInterface) Color {
return Hsv(
rand.Float64()*360.0,
0.5+rand.Float64()*0.3,
0.3+rand.Float64()*0.3)
}
+func FastWarmColor() Color {
+ return FastWarmColorWithRand(getDefaultGlobalRand())
+}
+
// Creates a random dark, "warm" color through restricted HCL space.
// This is slower than FastWarmColor but will likely give you colors which have
// the same "warmness" if you run it many times.
-func WarmColor() (c Color) {
- for c = randomWarm(); !c.IsValid(); c = randomWarm() {
+func WarmColorWithRand(rand RandInterface) (c Color) {
+ for c = randomWarmWithRand(rand); !c.IsValid(); c = randomWarmWithRand(rand) {
}
return
}
-func randomWarm() Color {
+func WarmColor() (c Color) {
+ return WarmColorWithRand(getDefaultGlobalRand())
+}
+
+func randomWarmWithRand(rand RandInterface) Color {
return Hcl(
rand.Float64()*360.0,
0.1+rand.Float64()*0.3,
@@ -31,23 +35,31 @@ func randomWarm() Color {
}
// Creates a random bright, "pimpy" color through a restricted HSV space.
-func FastHappyColor() Color {
+func FastHappyColorWithRand(rand RandInterface) Color {
return Hsv(
rand.Float64()*360.0,
0.7+rand.Float64()*0.3,
0.6+rand.Float64()*0.3)
}
+func FastHappyColor() Color {
+ return FastHappyColorWithRand(getDefaultGlobalRand())
+}
+
// Creates a random bright, "pimpy" color through restricted HCL space.
// This is slower than FastHappyColor but will likely give you colors which
// have the same "brightness" if you run it many times.
-func HappyColor() (c Color) {
- for c = randomPimp(); !c.IsValid(); c = randomPimp() {
+func HappyColorWithRand(rand RandInterface) (c Color) {
+ for c = randomPimpWithRand(rand); !c.IsValid(); c = randomPimpWithRand(rand) {
}
return
}
-func randomPimp() Color {
+func HappyColor() (c Color) {
+ return HappyColorWithRand(getDefaultGlobalRand())
+}
+
+func randomPimpWithRand(rand RandInterface) Color {
return Hcl(
rand.Float64()*360.0,
0.5+rand.Float64()*0.3,
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colors.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colors.go
index 0d5bffe5db3..17441a8c613 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colors.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/colors.go
@@ -5,6 +5,7 @@ import (
"fmt"
"image/color"
"math"
+ "strconv"
)
// A color is stored internally using sRGB (standard RGB) values in the range 0-1
@@ -94,15 +95,39 @@ func (c1 Color) DistanceRgb(c2 Color) float64 {
return math.Sqrt(sq(c1.R-c2.R) + sq(c1.G-c2.G) + sq(c1.B-c2.B))
}
-// DistanceLinearRGB computes the distance between two colors in linear RGB
+// DistanceLinearRgb computes the distance between two colors in linear RGB
// space. This is not useful for measuring how humans perceive color, but
// might be useful for other things, like dithering.
-func (c1 Color) DistanceLinearRGB(c2 Color) float64 {
+func (c1 Color) DistanceLinearRgb(c2 Color) float64 {
r1, g1, b1 := c1.LinearRgb()
r2, g2, b2 := c2.LinearRgb()
return math.Sqrt(sq(r1-r2) + sq(g1-g2) + sq(b1-b2))
}
+// DistanceLinearRGB is deprecated in favour of DistanceLinearRgb.
+// They do the exact same thing.
+func (c1 Color) DistanceLinearRGB(c2 Color) float64 {
+ return c1.DistanceLinearRgb(c2)
+}
+
+// DistanceRiemersma is a color distance algorithm developed by Thiadmer Riemersma.
+// It uses RGB coordinates, but he claims it has similar results to CIELUV.
+// This makes it both fast and accurate.
+//
+// Sources:
+//
+// https://www.compuphase.com/cmetric.htm
+// https://github.com/lucasb-eyer/go-colorful/issues/52
+func (c1 Color) DistanceRiemersma(c2 Color) float64 {
+ rAvg := (c1.R + c2.R) / 2.0
+ // Deltas
+ dR := c1.R - c2.R
+ dG := c1.G - c2.G
+ dB := c1.B - c2.B
+
+ return math.Sqrt((2+rAvg)*dR*dR + 4*dG*dG + (2+(1-rAvg))*dB*dB)
+}
+
// Check for equality between colors within the tolerance Delta (1/255).
func (c1 Color) AlmostEqualRgb(c2 Color) bool {
return math.Abs(c1.R-c2.R)+
@@ -112,9 +137,11 @@ func (c1 Color) AlmostEqualRgb(c2 Color) bool {
// You don't really want to use this, do you? Go for BlendLab, BlendLuv or BlendHcl.
func (c1 Color) BlendRgb(c2 Color, t float64) Color {
- return Color{c1.R + t*(c2.R-c1.R),
+ return Color{
+ c1.R + t*(c2.R-c1.R),
c1.G + t*(c2.G-c1.G),
- c1.B + t*(c2.B-c1.B)}
+ c1.B + t*(c2.B-c1.B),
+ }
}
// Utility used by Hxx color-spaces for interpolating between two angles in [0,360].
@@ -128,9 +155,9 @@ func interp_angle(a0, a1, t float64) float64 {
/// HSV ///
///////////
// From http://en.wikipedia.org/wiki/HSL_and_HSV
-// Note that h is in [0..360] and s,v in [0..1]
+// Note that h is in [0..359] and s,v in [0..1]
-// Hsv returns the Hue [0..360], Saturation and Value [0..1] of the color.
+// Hsv returns the Hue [0..359], Saturation and Value [0..1] of the color.
func (col Color) Hsv() (h, s, v float64) {
min := math.Min(math.Min(col.R, col.G), col.B)
v = math.Max(math.Max(col.R, col.G), col.B)
@@ -160,7 +187,7 @@ func (col Color) Hsv() (h, s, v float64) {
return
}
-// Hsv creates a new Color given a Hue in [0..360], a Saturation and a Value in [0..1]
+// Hsv creates a new Color given a Hue in [0..359], a Saturation and a Value in [0..1]
func Hsv(H, S, V float64) Color {
Hp := H / 60.0
C := V * S
@@ -198,6 +225,13 @@ func (c1 Color) BlendHsv(c2 Color, t float64) Color {
h1, s1, v1 := c1.Hsv()
h2, s2, v2 := c2.Hsv()
+ // https://github.com/lucasb-eyer/go-colorful/pull/60
+ if s1 == 0 && s2 != 0 {
+ h1 = h2
+ } else if s2 == 0 && s1 != 0 {
+ h2 = h1
+ }
+
// We know that h are both in [0..360]
return Hsv(interp_angle(h1, h2, t), s1+t*(s2-s1), v1+t*(v2-v1))
}
@@ -205,7 +239,7 @@ func (c1 Color) BlendHsv(c2 Color, t float64) Color {
/// HSL ///
///////////
-// Hsl returns the Hue [0..360], Saturation [0..1], and Luminance (lightness) [0..1] of the color.
+// Hsl returns the Hue [0..359], Saturation [0..1], and Luminance (lightness) [0..1] of the color.
func (col Color) Hsl() (h, s, l float64) {
min := math.Min(math.Min(col.R, col.G), col.B)
max := math.Max(math.Max(col.R, col.G), col.B)
@@ -240,7 +274,7 @@ func (col Color) Hsl() (h, s, l float64) {
return
}
-// Hsl creates a new Color given a Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1]
+// Hsl creates a new Color given a Hue in [0..359], a Saturation [0..1], and a Luminance (lightness) in [0..1]
func Hsl(h, s, l float64) Color {
if s == 0 {
return Color{l, l, l}
@@ -331,23 +365,46 @@ func (col Color) Hex() string {
// Hex parses a "html" hex color-string, either in the 3 "#f0c" or 6 "#ff1034" digits form.
func Hex(scol string) (Color, error) {
- format := "#%02x%02x%02x"
- factor := 1.0 / 255.0
- if len(scol) == 4 {
- format = "#%1x%1x%1x"
- factor = 1.0 / 15.0
+ if scol == "" || scol[0] != '#' {
+ return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
+ }
+ var c Color
+ var err error
+ switch len(scol) {
+ case 4:
+ c, err = parseHexColor(scol[1:2], scol[2:3], scol[3:4], 4, 1.0/15.0)
+ case 7:
+ c, err = parseHexColor(scol[1:3], scol[3:5], scol[5:7], 8, 1.0/255.0)
+ default:
+ return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
}
-
- var r, g, b uint8
- n, err := fmt.Sscanf(scol, format, &r, &g, &b)
if err != nil {
+ return Color{}, fmt.Errorf("color: %v is not a hex-color: %w", scol, err)
+ }
+ return c, nil
+}
+
+func parseHexColor(r, g, b string, bits int, factor float64) (Color, error) {
+ var c Color
+ var v uint64
+ var err error
+
+ if v, err = strconv.ParseUint(r, 16, bits); err != nil {
return Color{}, err
}
- if n != 3 {
- return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
+ c.R = float64(v) * factor
+
+ if v, err = strconv.ParseUint(g, 16, bits); err != nil {
+ return Color{}, err
}
+ c.G = float64(v) * factor
- return Color{float64(r) * factor, float64(g) * factor, float64(b) * factor}, nil
+ if v, err = strconv.ParseUint(b, 16, bits); err != nil {
+ return Color{}, err
+ }
+ c.B = float64(v) * factor
+
+ return c, err
}
/// Linear ///
@@ -377,7 +434,7 @@ func linearize_fast(v float64) float64 {
v2 := v1 * v1
v3 := v2 * v1
v4 := v2 * v2
- //v5 := v3*v2
+ // v5 := v3*v2
return -0.248750514614486 + 0.925583310193438*v + 1.16740237321695*v2 + 0.280457026598666*v3 - 0.0757991963780179*v4 //+ 0.0437040411548932*v5
}
@@ -450,6 +507,19 @@ func LinearRgbToXyz(r, g, b float64) (x, y, z float64) {
return
}
+// BlendLinearRgb blends two colors in the Linear RGB color-space.
+// Unlike BlendRgb, this will not produce dark color around the center.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendLinearRgb(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.LinearRgb()
+ r2, g2, b2 := c2.LinearRgb()
+ return LinearRgb(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1),
+ )
+}
+
/// XYZ ///
///////////
// http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/
@@ -784,7 +854,7 @@ func LuvToXyz(l, u, v float64) (x, y, z float64) {
}
func LuvToXyzWhiteRef(l, u, v float64, wref [3]float64) (x, y, z float64) {
- //y = wref[1] * lab_finv((l + 0.16) / 1.16)
+ // y = wref[1] * lab_finv((l + 0.16) / 1.16)
if l <= 0.08 {
y = wref[1] * l * 100.0 * 3.0 / 29.0 * 3.0 / 29.0 * 3.0 / 29.0
} else {
@@ -913,6 +983,13 @@ func (col1 Color) BlendHcl(col2 Color, t float64) Color {
h1, c1, l1 := col1.Hcl()
h2, c2, l2 := col2.Hcl()
+ // https://github.com/lucasb-eyer/go-colorful/pull/60
+ if c1 <= 0.00015 && c2 >= 0.00015 {
+ h1 = h2
+ } else if c2 <= 0.00015 && c1 >= 0.00015 {
+ h2 = h1
+ }
+
// We know that h are both in [0..360]
return Hcl(interp_angle(h1, h2, t), c1+t*(c2-c1), l1+t*(l2-l1)).Clamped()
}
@@ -977,3 +1054,103 @@ func (col1 Color) BlendLuvLCh(col2 Color, t float64) Color {
// We know that h are both in [0..360]
return LuvLCh(l1+t*(l2-l1), c1+t*(c2-c1), interp_angle(h1, h2, t))
}
+
+/// OkLab ///
+///////////
+
+func (col Color) OkLab() (l, a, b float64) {
+ return XyzToOkLab(col.Xyz())
+}
+
+func OkLab(l, a, b float64) Color {
+ return Xyz(OkLabToXyz(l, a, b))
+}
+
+func XyzToOkLab(x, y, z float64) (l, a, b float64) {
+ l_ := math.Cbrt(0.8189330101*x + 0.3618667424*y - 0.1288597137*z)
+ m_ := math.Cbrt(0.0329845436*x + 0.9293118715*y + 0.0361456387*z)
+ s_ := math.Cbrt(0.0482003018*x + 0.2643662691*y + 0.6338517070*z)
+ l = 0.2104542553*l_ + 0.7936177850*m_ - 0.0040720468*s_
+ a = 1.9779984951*l_ - 2.4285922050*m_ + 0.4505937099*s_
+ b = 0.0259040371*l_ + 0.7827717662*m_ - 0.8086757660*s_
+ return
+}
+
+func OkLabToXyz(l, a, b float64) (x, y, z float64) {
+ l_ := 0.9999999984505196*l + 0.39633779217376774*a + 0.2158037580607588*b
+ m_ := 1.0000000088817607*l - 0.10556134232365633*a - 0.0638541747717059*b
+ s_ := 1.0000000546724108*l - 0.08948418209496574*a - 1.2914855378640917*b
+
+ ll := math.Pow(l_, 3)
+ m := math.Pow(m_, 3)
+ s := math.Pow(s_, 3)
+
+ x = 1.2268798733741557*ll - 0.5578149965554813*m + 0.28139105017721594*s
+ y = -0.04057576262431372*ll + 1.1122868293970594*m - 0.07171106666151696*s
+ z = -0.07637294974672142*ll - 0.4214933239627916*m + 1.5869240244272422*s
+
+ return
+}
+
+// BlendOkLab blends two colors in the OkLab color-space, which should result in a better blend (even compared to BlendLab).
+func (c1 Color) BlendOkLab(c2 Color, t float64) Color {
+ l1, a1, b1 := c1.OkLab()
+ l2, a2, b2 := c2.OkLab()
+ return OkLab(l1+t*(l2-l1),
+ a1+t*(a2-a1),
+ b1+t*(b2-b1))
+}
+
+/// OkLch ///
+///////////
+
+func (col Color) OkLch() (l, c, h float64) {
+ return OkLabToOkLch(col.OkLab())
+}
+
+func OkLch(l, c, h float64) Color {
+ return Xyz(OkLchToXyz(l, c, h))
+}
+
+func XyzToOkLch(x, y, z float64) (float64, float64, float64) {
+ l, c, h := OkLabToOkLch(XyzToOkLab(x, y, z))
+ return l, c, h
+}
+
+func OkLchToXyz(l, c, h float64) (float64, float64, float64) {
+ x, y, z := OkLabToXyz(OkLchToOkLab(l, c, h))
+ return x, y, z
+}
+
+func OkLabToOkLch(l, a, b float64) (float64, float64, float64) {
+ c := math.Sqrt((a * a) + (b * b))
+ h := math.Atan2(b, a)
+ if h < 0 {
+ h += 2 * math.Pi
+ }
+
+ return l, c, h * 180 / math.Pi
+}
+
+func OkLchToOkLab(l, c, h float64) (float64, float64, float64) {
+ h *= math.Pi / 180
+ a := c * math.Cos(h)
+ b := c * math.Sin(h)
+ return l, a, b
+}
+
+// BlendOkLch blends two colors in the OkLch color-space, which should result in a better blend (even compared to BlendHcl).
+func (col1 Color) BlendOkLch(col2 Color, t float64) Color {
+ l1, c1, h1 := col1.OkLch()
+ l2, c2, h2 := col2.OkLch()
+
+ // https://github.com/lucasb-eyer/go-colorful/pull/60
+ if c1 <= 0.00015 && c2 >= 0.00015 {
+ h1 = h2
+ } else if c2 <= 0.00015 && c1 >= 0.00015 {
+ h2 = h1
+ }
+
+ // We know that h are both in [0..360]
+ return OkLch(l1+t*(l2-l1), c1+t*(c2-c1), interp_angle(h1, h2, t)).Clamped()
+}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go
index bb66dfa4f9f..0cb9286cb14 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go
@@ -1,13 +1,9 @@
package colorful
-import (
- "math/rand"
-)
-
// Uses the HSV color space to generate colors with similar S,V but distributed
// evenly along their Hue. This is fast but not always pretty.
// If you've got time to spare, use Lab (the non-fast below).
-func FastHappyPalette(colorsCount int) (colors []Color) {
+func FastHappyPaletteWithRand(colorsCount int, rand RandInterface) (colors []Color) {
colors = make([]Color, colorsCount)
for i := 0; i < colorsCount; i++ {
@@ -16,10 +12,18 @@ func FastHappyPalette(colorsCount int) (colors []Color) {
return
}
-func HappyPalette(colorsCount int) ([]Color, error) {
+func FastHappyPalette(colorsCount int) (colors []Color) {
+ return FastHappyPaletteWithRand(colorsCount, getDefaultGlobalRand())
+}
+
+func HappyPaletteWithRand(colorsCount int, rand RandInterface) ([]Color, error) {
pimpy := func(l, a, b float64) bool {
_, c, _ := LabToHcl(l, a, b)
return 0.3 <= c && 0.4 <= l && l <= 0.8
}
- return SoftPaletteEx(colorsCount, SoftPaletteSettings{pimpy, 50, true})
+ return SoftPaletteExWithRand(colorsCount, SoftPaletteSettings{pimpy, 50, true}, rand)
+}
+
+func HappyPalette(colorsCount int) ([]Color, error) {
+ return HappyPaletteWithRand(colorsCount, getDefaultGlobalRand())
}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
index 76f31d8f9f2..26f35730436 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
@@ -34,6 +34,10 @@ func (hc *HexColor) Value() (driver.Value, error) {
return Color(*hc).Hex(), nil
}
+func (hc HexColor) String() string {
+ return Color(hc).Hex()
+}
+
func (e errUnsupportedType) Error() string {
return fmt.Sprintf("unsupported type: got %v, want a %s", e.got, e.want)
}
@@ -65,3 +69,23 @@ func (hc *HexColor) Decode(hexCode string) error {
*hc = HexColor(col)
return nil
}
+
+func (hc HexColor) MarshalYAML() (interface{}, error) {
+ return Color(hc).Hex(), nil
+}
+
+func (hc *HexColor) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var hexCode string
+ if err := unmarshal(&hexCode); err != nil {
+ return err
+ }
+
+ var col, err = Hex(hexCode)
+ if err != nil {
+ return err
+ }
+
+ *hc = HexColor(col)
+
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
index d19fb6443d0..cc514882288 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
@@ -11,7 +11,8 @@ import "math"
// comparing to the test values, this modified white reference is used internally.
//
// See this GitHub thread for details on these values:
-// https://github.com/hsluv/hsluv/issues/79
+//
+// https://github.com/hsluv/hsluv/issues/79
var hSLuvD65 = [3]float64{0.95045592705167, 1.0, 1.089057750759878}
func LuvLChToHSLuv(l, c, h float64) (float64, float64, float64) {
@@ -115,7 +116,7 @@ func (col Color) HPLuv() (h, s, l float64) {
return LuvLChToHPLuv(col.LuvLChWhiteRef(hSLuvD65))
}
-// DistanceHSLuv calculates Euclidan distance in the HSLuv colorspace. No idea
+// DistanceHSLuv calculates Euclidean distance in the HSLuv colorspace. No idea
// how useful this is.
//
// The Hue value is divided by 100 before the calculation, so that H, S, and L
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/rand.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/rand.go
new file mode 100644
index 00000000000..d3a2d5b50ba
--- /dev/null
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/rand.go
@@ -0,0 +1,22 @@
+package colorful
+
+import "math/rand"
+
+type RandInterface interface {
+ Float64() float64
+ Intn(n int) int
+}
+
+type defaultGlobalRand struct{}
+
+func (df defaultGlobalRand) Float64() float64 {
+ return rand.Float64()
+}
+
+func (df defaultGlobalRand) Intn(n int) int {
+ return rand.Intn(n)
+}
+
+func getDefaultGlobalRand() RandInterface {
+ return defaultGlobalRand{}
+}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
index 9f7bf6f7c70..6d8aa137e29 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
@@ -6,7 +6,6 @@ package colorful
import (
"fmt"
"math"
- "math/rand"
)
// The algorithm works in L*a*b* color space and converts to RGB in the end.
@@ -32,7 +31,7 @@ type SoftPaletteSettings struct {
// as a new palette of distinctive colors. Falls back to K-medoid if the mean
// happens to fall outside of the color-space, which can only happen if you
// specify a CheckColor function.
-func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, error) {
+func SoftPaletteExWithRand(colorsCount int, settings SoftPaletteSettings, rand RandInterface) ([]Color, error) {
// Checks whether it's a valid RGB and also fulfills the potentially provided constraint.
check := func(col lab_t) bool {
@@ -79,7 +78,7 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
// The actual k-means/medoid iterations
for i := 0; i < settings.Iterations; i++ {
- // Reassing the samples to clusters, i.e. to their closest mean.
+ // Reassigning the samples to clusters, i.e. to their closest mean.
// By the way, also check if any sample is used as a medoid and if so, mark that.
for isample, sample := range samples {
samples_used[isample] = false
@@ -100,7 +99,7 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
// Compute new means according to the samples.
for imean := range means {
- // The new mean is the average of all samples belonging to it..
+ // The new mean is the average of all samples belonging to it.
nsamples := 0
newmean := lab_t{0.0, 0.0, 0.0}
for isample, sample := range samples {
@@ -148,9 +147,17 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
return labs2cols(means), nil
}
+func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, error) {
+ return SoftPaletteExWithRand(colorsCount, settings, getDefaultGlobalRand())
+}
+
// A wrapper which uses common parameters.
+func SoftPaletteWithRand(colorsCount int, rand RandInterface) ([]Color, error) {
+ return SoftPaletteExWithRand(colorsCount, SoftPaletteSettings{nil, 50, false}, rand)
+}
+
func SoftPalette(colorsCount int) ([]Color, error) {
- return SoftPaletteEx(colorsCount, SoftPaletteSettings{nil, 50, false})
+ return SoftPaletteWithRand(colorsCount, getDefaultGlobalRand())
}
func in(haystack []lab_t, upto int, needle lab_t) bool {
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/sort.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/sort.go
new file mode 100644
index 00000000000..b1c1b6813dd
--- /dev/null
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/sort.go
@@ -0,0 +1,191 @@
+// This file provides functions for sorting colors.
+
+package colorful
+
+import (
+ "math"
+ "sort"
+)
+
+// An element represents a single element of a set. It is used to
+// implement a disjoint-set forest.
+type element struct {
+ parent *element // Parent element
+ rank int // Rank (approximate depth) of the subtree with this element as root
+}
+
+// newElement creates a singleton set and returns its sole element.
+func newElement() *element {
+ s := &element{}
+ s.parent = s
+ return s
+}
+
+// find returns an arbitrary element of a set when invoked on any element of
+// the set, The important feature is that it returns the same value when
+// invoked on any element of the set. Consequently, it can be used to test if
+// two elements belong to the same set.
+func (e *element) find() *element {
+ for e.parent != e {
+ e.parent = e.parent.parent
+ e = e.parent
+ }
+ return e
+}
+
+// union establishes the union of two sets when given an element from each set.
+// Afterwards, the original sets no longer exist as separate entities.
+func union(e1, e2 *element) {
+ // Ensure the two elements aren't already part of the same union.
+ e1Root := e1.find()
+ e2Root := e2.find()
+ if e1Root == e2Root {
+ return
+ }
+
+ // Create a union by making the shorter tree point to the root of the
+ // larger tree.
+ switch {
+ case e1Root.rank < e2Root.rank:
+ e1Root.parent = e2Root
+ case e1Root.rank > e2Root.rank:
+ e2Root.parent = e1Root
+ default:
+ e2Root.parent = e1Root
+ e1Root.rank++
+ }
+}
+
+// An edgeIdxs describes an edge in a graph or tree. The vertices in the edge
+// are indexes into a list of Color values.
+type edgeIdxs [2]int
+
+// An edgeDistance is a map from an edge (pair of indices) to a distance
+// between the two vertices.
+type edgeDistance map[edgeIdxs]float64
+
+// allToAllDistancesCIEDE2000 computes the CIEDE2000 distance between each pair of
+// colors. It returns a map from a pair of indices (u, v) with u < v to a
+// distance.
+func allToAllDistancesCIEDE2000(cs []Color) edgeDistance {
+ nc := len(cs)
+ m := make(edgeDistance, nc*nc)
+ for u := 0; u < nc-1; u++ {
+ for v := u + 1; v < nc; v++ {
+ m[edgeIdxs{u, v}] = cs[u].DistanceCIEDE2000(cs[v])
+ }
+ }
+ return m
+}
+
+// sortEdges sorts all edges in a distance map by increasing vertex distance.
+func sortEdges(m edgeDistance) []edgeIdxs {
+ es := make([]edgeIdxs, 0, len(m))
+ for uv := range m {
+ es = append(es, uv)
+ }
+ sort.Slice(es, func(i, j int) bool {
+ return m[es[i]] < m[es[j]]
+ })
+ return es
+}
+
+// minSpanTree computes a minimum spanning tree from a vertex count and a
+// distance-sorted edge list. It returns the subset of edges that belong to
+// the tree, including both (u, v) and (v, u) for each edge.
+func minSpanTree(nc int, es []edgeIdxs) map[edgeIdxs]struct{} {
+ // Start with each vertex in its own set.
+ elts := make([]*element, nc)
+ for i := range elts {
+ elts[i] = newElement()
+ }
+
+ // Run Kruskal's algorithm to construct a minimal spanning tree.
+ mst := make(map[edgeIdxs]struct{}, nc)
+ for _, uv := range es {
+ u, v := uv[0], uv[1]
+ if elts[u].find() == elts[v].find() {
+ continue // Same set: edge would introduce a cycle.
+ }
+ mst[uv] = struct{}{}
+ mst[edgeIdxs{v, u}] = struct{}{}
+ union(elts[u], elts[v])
+ }
+ return mst
+}
+
+// traverseMST walks a minimum spanning tree in prefix order.
+func traverseMST(mst map[edgeIdxs]struct{}, root int) []int {
+ // Compute a list of neighbors for each vertex.
+ neighs := make(map[int][]int, len(mst))
+ for uv := range mst {
+ u, v := uv[0], uv[1]
+ neighs[u] = append(neighs[u], v)
+ }
+ for u, vs := range neighs {
+ sort.Ints(vs)
+ copy(neighs[u], vs)
+ }
+
+ // Walk the tree from a given vertex.
+ order := make([]int, 0, len(neighs))
+ visited := make(map[int]bool, len(neighs))
+ var walkFrom func(int)
+ walkFrom = func(r int) {
+ // Visit the starting vertex.
+ order = append(order, r)
+ visited[r] = true
+
+ // Recursively visit each child in turn.
+ for _, c := range neighs[r] {
+ if !visited[c] {
+ walkFrom(c)
+ }
+ }
+ }
+ walkFrom(root)
+ return order
+}
+
+// Sorted sorts a list of Color values. Sorting is not a well-defined operation
+// for colors so the intention here primarily is to order colors so that the
+// transition from one to the next is fairly smooth.
+func Sorted(cs []Color) []Color {
+ // Do nothing in trivial cases.
+ newCs := make([]Color, len(cs))
+ if len(cs) < 2 {
+ copy(newCs, cs)
+ return newCs
+ }
+
+ // Compute the distance from each color to every other color.
+ dists := allToAllDistancesCIEDE2000(cs)
+
+ // Produce a list of edges in increasing order of the distance between
+ // their vertices.
+ edges := sortEdges(dists)
+
+ // Construct a minimum spanning tree from the list of edges.
+ mst := minSpanTree(len(cs), edges)
+
+ // Find the darkest color in the list.
+ var black Color
+ var dIdx int // Index of darkest color
+ light := math.MaxFloat64 // Lightness of darkest color (distance from black)
+ for i, c := range cs {
+ d := black.DistanceCIEDE2000(c)
+ if d < light {
+ dIdx = i
+ light = d
+ }
+ }
+
+ // Traverse the tree starting from the darkest color.
+ idxs := traverseMST(mst, dIdx)
+
+ // Convert the index list to a list of colors, overwriting the input.
+ for i, idx := range idxs {
+ newCs[i] = cs[idx]
+ }
+ return newCs
+}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go
index 00f42a5cc7c..d294fb41585 100644
--- a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go
@@ -1,13 +1,9 @@
package colorful
-import (
- "math/rand"
-)
-
// Uses the HSV color space to generate colors with similar S,V but distributed
// evenly along their Hue. This is fast but not always pretty.
// If you've got time to spare, use Lab (the non-fast below).
-func FastWarmPalette(colorsCount int) (colors []Color) {
+func FastWarmPaletteWithRand(colorsCount int, rand RandInterface) (colors []Color) {
colors = make([]Color, colorsCount)
for i := 0; i < colorsCount; i++ {
@@ -16,10 +12,18 @@ func FastWarmPalette(colorsCount int) (colors []Color) {
return
}
-func WarmPalette(colorsCount int) ([]Color, error) {
+func FastWarmPalette(colorsCount int) (colors []Color) {
+ return FastWarmPaletteWithRand(colorsCount, getDefaultGlobalRand())
+}
+
+func WarmPaletteWithRand(colorsCount int, rand RandInterface) ([]Color, error) {
warmy := func(l, a, b float64) bool {
_, c, _ := LabToHcl(l, a, b)
return 0.1 <= c && c <= 0.4 && 0.2 <= l && l <= 0.5
}
- return SoftPaletteEx(colorsCount, SoftPaletteSettings{warmy, 50, true})
+ return SoftPaletteExWithRand(colorsCount, SoftPaletteSettings{warmy, 50, true}, rand)
+}
+
+func WarmPalette(colorsCount int) ([]Color, error) {
+ return WarmPaletteWithRand(colorsCount, getDefaultGlobalRand())
}
diff --git a/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/widegamut.go b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/widegamut.go
new file mode 100644
index 00000000000..6805a2b96f5
--- /dev/null
+++ b/hack/tools/vendor/github.com/lucasb-eyer/go-colorful/widegamut.go
@@ -0,0 +1,290 @@
+package colorful
+
+import "math"
+
+// Wide-gamut RGB color spaces from CSS Color Level 4.
+// https://www.w3.org/TR/css-color-4/#color-conversion-code
+
+/// Bradford ///
+////////////////
+// Bradford chromatic adaptation between D50 and D65 illuminants.
+
+func D50ToD65(x, y, z float64) (xo, yo, zo float64) {
+ xo = 0.9555766*x - 0.0230393*y + 0.0631636*z
+ yo = -0.0282895*x + 1.0099416*y + 0.0210077*z
+ zo = 0.0122982*x - 0.0204830*y + 1.3299098*z
+ return
+}
+
+func D65ToD50(x, y, z float64) (xo, yo, zo float64) {
+ xo = 1.0479298208405488*x + 0.022946793341019088*y - 0.05019222954313557*z
+ yo = 0.029627815688159344*x + 0.990434484573249*y - 0.01707382502938514*z
+ zo = -0.009243058152591178*x + 0.015055144896577895*y + 0.7518742899580008*z
+ return
+}
+
+/// XYZ D50 ///
+///////////////
+
+func XyzD50(x, y, z float64) Color {
+ return Xyz(D50ToD65(x, y, z))
+}
+
+func (col Color) XyzD50() (x, y, z float64) {
+ return D65ToD50(col.Xyz())
+}
+
+/// Display P3 ///
+//////////////////
+// Uses the sRGB transfer function with DCI-P3 primaries.
+
+func DisplayP3ToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearize(r)
+ gl = linearize(g)
+ bl = linearize(b)
+ return
+}
+
+func LinearDisplayP3ToXyz(r, g, b float64) (x, y, z float64) {
+ x = 0.4865709486482162*r + 0.26566769316909306*g + 0.1982172852343625*b
+ y = 0.2289745640697488*r + 0.6917385218365064*g + 0.079286914093745*b
+ z = 0.04511338185890264*g + 1.043944368900976*b
+ return
+}
+
+func XyzToLinearDisplayP3(x, y, z float64) (r, g, b float64) {
+ r = 2.493496911941425*x - 0.9313836179191239*y - 0.40271078445071684*z
+ g = -0.8294889695615747*x + 1.7626640603183463*y + 0.023624685841943577*z
+ b = 0.035845830243784335*x - 0.07617238926804182*y + 0.9568845240076872*z
+ return
+}
+
+func DisplayP3(r, g, b float64) Color {
+ rl, gl, bl := DisplayP3ToLinearRgb(r, g, b)
+ x, y, z := LinearDisplayP3ToXyz(rl, gl, bl)
+ return Xyz(x, y, z)
+}
+
+func (col Color) DisplayP3() (r, g, b float64) {
+ x, y, z := col.Xyz()
+ rl, gl, bl := XyzToLinearDisplayP3(x, y, z)
+ r = delinearize(rl)
+ g = delinearize(gl)
+ b = delinearize(bl)
+ return
+}
+
+// BlendDisplayP3 blends two colors in the Display P3 color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendDisplayP3(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.DisplayP3()
+ r2, g2, b2 := c2.DisplayP3()
+ return DisplayP3(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
+
+/// A98 RGB ///
+///////////////
+// Adobe RGB (1998) color space.
+
+func linearizeA98(v float64) float64 {
+ sign := 1.0
+ if v < 0 {
+ sign = -1.0
+ v = -v
+ }
+ return sign * math.Pow(v, 563.0/256.0)
+}
+
+func delinearizeA98(v float64) float64 {
+ sign := 1.0
+ if v < 0 {
+ sign = -1.0
+ v = -v
+ }
+ return sign * math.Pow(v, 256.0/563.0)
+}
+
+func A98RgbToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearizeA98(r)
+ gl = linearizeA98(g)
+ bl = linearizeA98(b)
+ return
+}
+
+func LinearA98RgbToXyz(r, g, b float64) (x, y, z float64) {
+ x = 0.5766690429101305*r + 0.1855582379065463*g + 0.1882286462349947*b
+ y = 0.29734497525053605*r + 0.6273635662554661*g + 0.07529145849399788*b
+ z = 0.02703136138641234*r + 0.07068885253582723*g + 0.9913375368376388*b
+ return
+}
+
+func XyzToLinearA98Rgb(x, y, z float64) (r, g, b float64) {
+ r = 2.0415879038107327*x - 0.5650069742788597*y - 0.34473135077832956*z
+ g = -0.9692436362808795*x + 1.8759675015077202*y + 0.04155505740717559*z
+ b = 0.013444280632031142*x - 0.11836239223101838*y + 1.0151749943912054*z
+ return
+}
+
+func A98Rgb(r, g, b float64) Color {
+ rl, gl, bl := A98RgbToLinearRgb(r, g, b)
+ x, y, z := LinearA98RgbToXyz(rl, gl, bl)
+ return Xyz(x, y, z)
+}
+
+func (col Color) A98Rgb() (r, g, b float64) {
+ x, y, z := col.Xyz()
+ rl, gl, bl := XyzToLinearA98Rgb(x, y, z)
+ r = delinearizeA98(rl)
+ g = delinearizeA98(gl)
+ b = delinearizeA98(bl)
+ return
+}
+
+// BlendA98Rgb blends two colors in the A98 RGB color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendA98Rgb(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.A98Rgb()
+ r2, g2, b2 := c2.A98Rgb()
+ return A98Rgb(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
+
+/// ProPhoto RGB ///
+////////////////////
+// ProPhoto RGB (ROMM RGB) uses D50 illuminant.
+
+func linearizeProPhoto(v float64) float64 {
+ if v <= 16.0/512.0 {
+ return v / 16.0
+ }
+ return math.Pow(v, 1.8)
+}
+
+func delinearizeProPhoto(v float64) float64 {
+ if v < 1.0/512.0 {
+ return 16.0 * v
+ }
+ return math.Pow(v, 1.0/1.8)
+}
+
+func ProPhotoRgbToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearizeProPhoto(r)
+ gl = linearizeProPhoto(g)
+ bl = linearizeProPhoto(b)
+ return
+}
+
+func LinearProPhotoRgbToXyzD50(r, g, b float64) (x, y, z float64) {
+ x = 0.7977604896723027*r + 0.13518583717574031*g + 0.0313493495815248*b
+ y = 0.2880711282292934*r + 0.7118432178101014*g + 0.00008565396060525902*b
+ z = 0.8251046025104602 * b
+ return
+}
+
+func XyzD50ToLinearProPhotoRgb(x, y, z float64) (r, g, b float64) {
+ r = 1.3457989731028281*x - 0.25558010007997534*y - 0.05110628506753401*z
+ g = -0.5446224939028347*x + 1.5082327413132781*y + 0.02053603239147973*z
+ b = 1.2119675456389454 * z
+ return
+}
+
+func ProPhotoRgb(r, g, b float64) Color {
+ rl, gl, bl := ProPhotoRgbToLinearRgb(r, g, b)
+ x, y, z := LinearProPhotoRgbToXyzD50(rl, gl, bl)
+ return XyzD50(x, y, z)
+}
+
+func (col Color) ProPhotoRgb() (r, g, b float64) {
+ x, y, z := col.XyzD50()
+ rl, gl, bl := XyzD50ToLinearProPhotoRgb(x, y, z)
+ r = delinearizeProPhoto(rl)
+ g = delinearizeProPhoto(gl)
+ b = delinearizeProPhoto(bl)
+ return
+}
+
+// BlendProPhotoRgb blends two colors in the ProPhoto RGB color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendProPhotoRgb(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.ProPhotoRgb()
+ r2, g2, b2 := c2.ProPhotoRgb()
+ return ProPhotoRgb(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
+
+/// Rec. 2020 ///
+/////////////////
+// ITU-R BT.2020 color space.
+
+const (
+ rec2020Alpha = 1.09929682680944
+ rec2020Beta = 0.018053968510807
+)
+
+func linearizeRec2020(v float64) float64 {
+ if v < rec2020Beta*4.5 {
+ return v / 4.5
+ }
+ return math.Pow((v+rec2020Alpha-1)/rec2020Alpha, 1.0/0.45)
+}
+
+func delinearizeRec2020(v float64) float64 {
+ if v < rec2020Beta {
+ return 4.5 * v
+ }
+ return rec2020Alpha*math.Pow(v, 0.45) - (rec2020Alpha - 1)
+}
+
+func Rec2020ToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearizeRec2020(r)
+ gl = linearizeRec2020(g)
+ bl = linearizeRec2020(b)
+ return
+}
+
+func LinearRec2020ToXyz(r, g, b float64) (x, y, z float64) {
+ x = 0.6369580483012914*r + 0.14461690358620832*g + 0.1688809751641721*b
+ y = 0.2627002120112671*r + 0.6779980715188708*g + 0.05930171646986196*b
+ z = 0.028072693049087428*g + 1.0609850577107909*b
+ return
+}
+
+func XyzToLinearRec2020(x, y, z float64) (r, g, b float64) {
+ r = 1.7166511879712674*x - 0.35567078377639233*y - 0.25336628137365974*z
+ g = -0.666684351832489*x + 1.616481236634939*y + 0.0157685458139402*z
+ b = 0.017639857445310783*x - 0.042770613257808524*y + 0.9421031212354738*z
+ return
+}
+
+func Rec2020(r, g, b float64) Color {
+ rl, gl, bl := Rec2020ToLinearRgb(r, g, b)
+ x, y, z := LinearRec2020ToXyz(rl, gl, bl)
+ return Xyz(x, y, z)
+}
+
+func (col Color) Rec2020() (r, g, b float64) {
+ x, y, z := col.Xyz()
+ rl, gl, bl := XyzToLinearRec2020(x, y, z)
+ r = delinearizeRec2020(rl)
+ g = delinearizeRec2020(gl)
+ b = delinearizeRec2020(bl)
+ return
+}
+
+// BlendRec2020 blends two colors in the Rec. 2020 color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendRec2020(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.Rec2020()
+ r2, g2, b2 := c2.Rec2020()
+ return Rec2020(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
diff --git a/hack/tools/vendor/github.com/magiconair/properties/CHANGELOG.md b/hack/tools/vendor/github.com/magiconair/properties/CHANGELOG.md
deleted file mode 100644
index 842e8e24fb9..00000000000
--- a/hack/tools/vendor/github.com/magiconair/properties/CHANGELOG.md
+++ /dev/null
@@ -1,205 +0,0 @@
-## Changelog
-
-### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022
-
- * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge
-
- Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch.
-
- * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions
-
-### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022
-
- * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error
-
- Thanks to [@ellie](https://github.com/ellie) for the patch.
-
- * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible
-
- This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the
- author happy until it affects real users.
-
- Thanks to [@maage](https://github.com/maage) for the patch.
-
-### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021
-
- * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments
-
- When reading comments \ are loaded correctly, but when writing they are then
- replaced by \\. This leads to wrong comments when writing and reading multiple times.
-
- Thanks to [@doxsch](https://github.com/doxsch) for the patch.
-
-### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020
-
- * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references
-
- Thanks to [@sriv](https://github.com/sriv) for the patch.
-
-### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020
-
- * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference
-
- The change is include the key in the error message which is causing the circular
- reference when parsing/loading the properties files.
-
- Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch.
-
-### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020
-
- * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write
-
- This patch ensures that backslashes are escaped on write. Existing applications which
- rely on the old behavior may need to be updated.
-
- Thanks to [@apesternikov](https://github.com/apesternikov) for the patch.
-
- * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL()
-
- Thanks to [@aliras1](https://github.com/aliras1) for the patch.
-
- * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write()
-
- Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
- * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys
-
- Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
-### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019
-
- * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request
-
- This patch ensures that in `LoadURL` the response body is always closed.
-
- Thanks to [@liubog2008](https://github.com/liubog2008) for the patch.
-
-### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
-
- * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
-
- This adds the option to disable property expansion during loading.
-
- Thanks to [@kmala](https://github.com/kmala) for the patch.
-
-### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018
-
- * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases.
-
- See PR for an example.
-
- Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018
-
- * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value
-
- Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail
- with a `circular reference error`.
-
- Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
-
- * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
-
- * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
-
- Thanks to [@mgurov](https://github.com/mgurov) for the fix.
-
-### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
-
- * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
- * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
-
-### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
-
- * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
- * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
-
-### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
-
- * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
- * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
- * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
- * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
-
-### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
-
- * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
- * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
- * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
-
-### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
-
- * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
-
-### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
-
- * Vendored in gopkg.in/check.v1
-
-### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
-
- * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
-
-### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
-
- * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
-
-### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
-
- * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
-
-### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
-
- * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
- * Add clickable links to README
-
-### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
-
- * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
- [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
-
-### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
-
- * Added support for single and multi-line comments (reading, writing and updating)
- * The order of keys is now preserved
- * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry
- * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
- * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
-
-### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
-
- * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
-
-### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
-
- * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
-
-### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
-
- * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
- * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
-
-### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
-
-* Added support for time.Duration
-* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
-* Changed default of MustXXX() failure from panic to log.Fatal
-
-### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
-
-* Added MustGet... functions
-* Added support for int and uint with range checks on 32 bit platforms
-
-### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
-
-* Renamed from goproperties to properties
-* Added support for expansion of environment vars in
- filenames and value expressions
-* Fixed bug where value expressions were not at the
- start of the string
-
-### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
-
-* Initial release
diff --git a/hack/tools/vendor/github.com/magiconair/properties/README.md b/hack/tools/vendor/github.com/magiconair/properties/README.md
index e2edda025bd..4872685f468 100644
--- a/hack/tools/vendor/github.com/magiconair/properties/README.md
+++ b/hack/tools/vendor/github.com/magiconair/properties/README.md
@@ -1,12 +1,9 @@
[](https://github.com/magiconair/properties/releases)
-[](https://travis-ci.org/magiconair/properties)
[](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
[](http://godoc.org/github.com/magiconair/properties)
# Overview
-#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why.
-
properties is a Go library for reading and writing properties files.
It supports reading from multiple files or URLs and Spring style recursive
@@ -99,30 +96,3 @@ $ go get -u github.com/magiconair/properties
## ToDo
* Dump contents with passwords and secrets obscured
-
-## Updated Git tags
-
-#### 13 Feb 2018
-
-I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags
-and I've only recently learned that this doesn't play well with `git describe` 😞
-
-I have replaced all lightweight tags with signed tags using this script which should
-retain the commit date, name and email address. Please run `git pull --tags` to update them.
-
-Worst case you have to reclone the repo.
-
-```shell
-#!/bin/bash
-tag=$1
-echo "Updating $tag"
-date=$(git show ${tag}^0 --format=%aD | head -1)
-email=$(git show ${tag}^0 --format=%aE | head -1)
-name=$(git show ${tag}^0 --format=%aN | head -1)
-GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag}
-```
-
-I apologize for the inconvenience.
-
-Frank
-
diff --git a/hack/tools/vendor/github.com/magiconair/properties/decode.go b/hack/tools/vendor/github.com/magiconair/properties/decode.go
index 8e6aa441d9b..f5e252f8d91 100644
--- a/hack/tools/vendor/github.com/magiconair/properties/decode.go
+++ b/hack/tools/vendor/github.com/magiconair/properties/decode.go
@@ -189,12 +189,12 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
fk, def, opts := keydef(t.Field(i))
- if !fv.CanSet() {
- return fmt.Errorf("cannot set %s", t.Field(i).Name)
- }
if fk == "-" {
continue
}
+ if !fv.CanSet() {
+ return fmt.Errorf("cannot set %s", t.Field(i).Name)
+ }
if key != "" {
fk = key + "." + fk
}
diff --git a/hack/tools/vendor/github.com/magiconair/properties/load.go b/hack/tools/vendor/github.com/magiconair/properties/load.go
index 635368dc8a4..6567e0c7199 100644
--- a/hack/tools/vendor/github.com/magiconair/properties/load.go
+++ b/hack/tools/vendor/github.com/magiconair/properties/load.go
@@ -6,7 +6,7 @@ package properties
import (
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"os"
"strings"
@@ -52,6 +52,15 @@ func (l *Loader) LoadBytes(buf []byte) (*Properties, error) {
return l.loadBytes(buf, l.Encoding)
}
+// LoadReader reads an io.Reader into a Properties struct.
+func (l *Loader) LoadReader(r io.Reader) (*Properties, error) {
+ if buf, err := io.ReadAll(r); err != nil {
+ return nil, err
+ } else {
+ return l.loadBytes(buf, l.Encoding)
+ }
+}
+
// LoadAll reads the content of multiple URLs or files in the given order into
// a Properties struct. If IgnoreMissing is true then a 404 status code or
// missing file will not be reported as error. Encoding sets the encoding for
@@ -91,7 +100,7 @@ func (l *Loader) LoadAll(names []string) (*Properties, error) {
// If IgnoreMissing is true then a missing file will not be
// reported as error.
func (l *Loader) LoadFile(filename string) (*Properties, error) {
- data, err := ioutil.ReadFile(filename)
+ data, err := os.ReadFile(filename)
if err != nil {
if l.IgnoreMissing && os.IsNotExist(err) {
LogPrintf("properties: %s not found. skipping", filename)
@@ -126,7 +135,7 @@ func (l *Loader) LoadURL(url string) (*Properties, error) {
return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
}
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
}
@@ -185,6 +194,12 @@ func LoadFile(filename string, enc Encoding) (*Properties, error) {
return l.LoadAll([]string{filename})
}
+// LoadReader reads an io.Reader into a Properties struct.
+func LoadReader(r io.Reader, enc Encoding) (*Properties, error) {
+ l := &Loader{Encoding: enc}
+ return l.LoadReader(r)
+}
+
// LoadFiles reads multiple files in the given order into
// a Properties struct. If 'ignoreMissing' is true then
// non-existent files will not be reported as error.
@@ -224,6 +239,12 @@ func MustLoadString(s string) *Properties {
return must(LoadString(s))
}
+// MustLoadSReader reads an io.Reader into a Properties struct and
+// panics on error.
+func MustLoadReader(r io.Reader, enc Encoding) *Properties {
+ return must(LoadReader(r, enc))
+}
+
// MustLoadFile reads a file into a Properties struct and
// panics on error.
func MustLoadFile(filename string, enc Encoding) *Properties {
diff --git a/hack/tools/vendor/github.com/magiconair/properties/properties.go b/hack/tools/vendor/github.com/magiconair/properties/properties.go
index fb2f7b4048c..58297611d2c 100644
--- a/hack/tools/vendor/github.com/magiconair/properties/properties.go
+++ b/hack/tools/vendor/github.com/magiconair/properties/properties.go
@@ -18,6 +18,7 @@ import (
"strconv"
"strings"
"time"
+ "unicode"
"unicode/utf8"
)
@@ -306,6 +307,40 @@ func (p *Properties) getFloat64(key string) (value float64, err error) {
// ----------------------------------------------------------------------------
+// GetFloat32 parses the expanded value as a float32 if the key exists.
+// If key does not exist or the value cannot be parsed the default
+// value is returned.
+func (p *Properties) GetFloat32(key string, def float32) float32 {
+ v, err := p.getFloat32(key)
+ if err != nil {
+ return def
+ }
+ return v
+}
+
+// MustGetFloat32 parses the expanded value as a float32 if the key exists.
+// If key does not exist or the value cannot be parsed the function panics.
+func (p *Properties) MustGetFloat32(key string) float32 {
+ v, err := p.getFloat32(key)
+ if err != nil {
+ ErrorHandler(err)
+ }
+ return v
+}
+
+func (p *Properties) getFloat32(key string) (value float32, err error) {
+ if v, ok := p.Get(key); ok {
+ n, err := strconv.ParseFloat(v, 32)
+ if err != nil {
+ return 0, err
+ }
+ return float32(n), nil
+ }
+ return 0, invalidKeyError(key)
+}
+
+// ----------------------------------------------------------------------------
+
// GetInt parses the expanded value as an int if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned. If the value does not fit into an int the
@@ -366,6 +401,40 @@ func (p *Properties) getInt64(key string) (value int64, err error) {
// ----------------------------------------------------------------------------
+// GetInt32 parses the expanded value as an int32 if the key exists.
+// If key does not exist or the value cannot be parsed the default
+// value is returned.
+func (p *Properties) GetInt32(key string, def int32) int32 {
+ v, err := p.getInt32(key)
+ if err != nil {
+ return def
+ }
+ return v
+}
+
+// MustGetInt32 parses the expanded value as an int if the key exists.
+// If key does not exist or the value cannot be parsed the function panics.
+func (p *Properties) MustGetInt32(key string) int32 {
+ v, err := p.getInt32(key)
+ if err != nil {
+ ErrorHandler(err)
+ }
+ return v
+}
+
+func (p *Properties) getInt32(key string) (value int32, err error) {
+ if v, ok := p.Get(key); ok {
+ n, err := strconv.ParseInt(v, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return int32(n), nil
+ }
+ return 0, invalidKeyError(key)
+}
+
+// ----------------------------------------------------------------------------
+
// GetUint parses the expanded value as an uint if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned. If the value does not fit into an int the
@@ -426,6 +495,40 @@ func (p *Properties) getUint64(key string) (value uint64, err error) {
// ----------------------------------------------------------------------------
+// GetUint32 parses the expanded value as an uint32 if the key exists.
+// If key does not exist or the value cannot be parsed the default
+// value is returned.
+func (p *Properties) GetUint32(key string, def uint32) uint32 {
+ v, err := p.getUint32(key)
+ if err != nil {
+ return def
+ }
+ return v
+}
+
+// MustGetUint32 parses the expanded value as an int if the key exists.
+// If key does not exist or the value cannot be parsed the function panics.
+func (p *Properties) MustGetUint32(key string) uint32 {
+ v, err := p.getUint32(key)
+ if err != nil {
+ ErrorHandler(err)
+ }
+ return v
+}
+
+func (p *Properties) getUint32(key string) (value uint32, err error) {
+ if v, ok := p.Get(key); ok {
+ n, err := strconv.ParseUint(v, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return uint32(n), nil
+ }
+ return 0, invalidKeyError(key)
+}
+
+// ----------------------------------------------------------------------------
+
// GetString returns the expanded value for the given key if exists or
// the default value otherwise.
func (p *Properties) GetString(key, def string) string {
@@ -799,8 +902,13 @@ func encodeUtf8(s string, special string) string {
v := ""
for pos := 0; pos < len(s); {
r, w := utf8.DecodeRuneInString(s[pos:])
+ switch {
+ case pos == 0 && unicode.IsSpace(r): // escape leading whitespace
+ v += escape(r, " ")
+ default:
+ v += escape(r, special) // escape special chars only
+ }
pos += w
- v += escape(r, special)
}
return v
}
@@ -811,6 +919,8 @@ func encodeIso(s string, special string) string {
var v string
for pos := 0; pos < len(s); {
switch r, w = utf8.DecodeRuneInString(s[pos:]); {
+ case pos == 0 && unicode.IsSpace(r): // escape leading whitespace
+ v += escape(r, " ")
case r < 1<<8: // single byte rune -> escape special chars only
v += escape(r, special)
case r < 1<<16: // two byte rune -> unicode literal
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go b/hack/tools/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go
index c3112107dd1..1e439175cf3 100644
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go
+++ b/hack/tools/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go
@@ -14,6 +14,7 @@ const (
ConstructorCheckName = "constructor"
StructMethodCheckName = "struct-method"
AlphabeticalCheckName = "alphabetical"
+ FunctionCheckName = "function"
)
func NewAnalyzer() *analysis.Analyzer {
@@ -33,6 +34,8 @@ func NewAnalyzer() *analysis.Analyzer {
"Checks if the exported methods of a structure are placed before the unexported ones.")
a.Flags.BoolVar(&f.alphabeticalCheck, AlphabeticalCheckName, false,
"Checks if the constructors and/or structure methods are sorted alphabetically.")
+ a.Flags.BoolVar(&f.functionCheck, FunctionCheckName, false,
+ "Checks that exported functions are placed before unexported functions.")
return a
}
@@ -41,9 +44,16 @@ type funcorder struct {
constructorCheck bool
structMethodCheck bool
alphabeticalCheck bool
+ functionCheck bool
}
func (f *funcorder) run(pass *analysis.Pass) (any, error) {
+ insp, found := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+ if !found {
+ //nolint:nilnil // impossible case.
+ return nil, nil
+ }
+
var enabledCheckers internal.Feature
if f.constructorCheck {
enabledCheckers.Enable(internal.ConstructorCheck)
@@ -57,14 +67,12 @@ func (f *funcorder) run(pass *analysis.Pass) (any, error) {
enabledCheckers.Enable(internal.AlphabeticalCheck)
}
- fp := internal.NewFileProcessor(pass.Fset, enabledCheckers)
-
- insp, found := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- if !found {
- //nolint:nilnil // impossible case.
- return nil, nil
+ if f.functionCheck {
+ enabledCheckers.Enable(internal.FunctionCheck)
}
+ fp := internal.NewFileProcessor(enabledCheckers)
+
nodeFilter := []ast.Node{
(*ast.File)(nil),
(*ast.FuncDecl)(nil),
@@ -74,23 +82,18 @@ func (f *funcorder) run(pass *analysis.Pass) (any, error) {
insp.Preorder(nodeFilter, func(n ast.Node) {
switch node := n.(type) {
case *ast.File:
- for _, report := range fp.Analyze() {
- pass.Report(report)
- }
-
- fp.NewFileNode(node)
+ fp.Analyze(pass)
+ fp.ResetStructs()
case *ast.FuncDecl:
- fp.NewFuncDecl(node)
+ fp.AddFuncDecl(node)
case *ast.TypeSpec:
- fp.NewTypeSpec(node)
+ fp.AddTypeSpec(node)
}
})
- for _, report := range fp.Analyze() {
- pass.Report(report)
- }
+ fp.Analyze(pass)
//nolint:nilnil //any, error
return nil, nil
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/astutils.go b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/astutils.go
deleted file mode 100644
index af7fa8c81db..00000000000
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/astutils.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package internal
-
-import (
- "bytes"
- "go/ast"
- "go/format"
- "go/token"
- "strings"
-)
-
-func FuncCanBeConstructor(n *ast.FuncDecl) bool {
- if !n.Name.IsExported() || n.Recv != nil {
- return false
- }
-
- if n.Type.Results == nil || len(n.Type.Results.List) == 0 {
- return false
- }
-
- for _, prefix := range []string{"new", "must"} {
- if strings.HasPrefix(strings.ToLower(n.Name.Name), prefix) &&
- len(n.Name.Name) > len(prefix) { // TODO(ldez): bug if the name is just `New`.
- return true
- }
- }
-
- return false
-}
-
-func FuncIsMethod(n *ast.FuncDecl) (*ast.Ident, bool) {
- if n.Recv == nil {
- return nil, false
- }
-
- if len(n.Recv.List) != 1 {
- return nil, false
- }
-
- if recv, ok := GetIdent(n.Recv.List[0].Type); ok {
- return recv, true
- }
-
- return nil, false
-}
-
-func GetIdent(expr ast.Expr) (*ast.Ident, bool) {
- switch exp := expr.(type) {
- case *ast.StarExpr:
- return GetIdent(exp.X)
-
- case *ast.Ident:
- return exp, true
-
- default:
- return nil, false
- }
-}
-
-// GetStartingPos returns the token starting position of the function
-// taking into account if there are comments.
-func GetStartingPos(function *ast.FuncDecl) token.Pos {
- startingPos := function.Pos()
- if function.Doc != nil {
- startingPos = function.Doc.Pos()
- }
-
- return startingPos
-}
-
-// NodeToBytes convert the ast.Node in bytes.
-func NodeToBytes(fset *token.FileSet, node ast.Node) ([]byte, error) {
- var buf bytes.Buffer
- if err := format.Node(&buf, fset, node); err != nil {
- return nil, err
- }
-
- return buf.Bytes(), nil
-}
-
-// SplitExportedUnexported split functions/methods based on whether they are exported or not.
-//
-//nolint:nonamedreturns // names serve as documentation
-func SplitExportedUnexported(funcDecls []*ast.FuncDecl) (exported, unexported []*ast.FuncDecl) {
- for _, f := range funcDecls {
- if f.Name.IsExported() {
- exported = append(exported, f)
- } else {
- unexported = append(unexported, f)
- }
- }
-
- return exported, unexported
-}
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/features.go b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/features.go
index 55d5caba3bf..7012a6880c5 100644
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/features.go
+++ b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/features.go
@@ -4,6 +4,7 @@ const (
ConstructorCheck Feature = 1 << iota
StructMethodCheck
AlphabeticalCheck
+ FunctionCheck
)
type Feature uint8
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/file_processor.go b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/file_processor.go
index 88ae00f2e63..9276c4a064e 100644
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/file_processor.go
+++ b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/file_processor.go
@@ -2,69 +2,102 @@ package internal
import (
"go/ast"
- "go/token"
"golang.org/x/tools/go/analysis"
)
// FileProcessor Holder to store all the functions that are potential to be constructors and all the structs.
type FileProcessor struct {
- fset *token.FileSet
- structs map[string]*StructHolder
- features Feature
+ structs map[string]*StructHolder
+ features Feature
+ topLevelFuncs []*ast.FuncDecl
}
// NewFileProcessor creates a new file processor.
-func NewFileProcessor(fset *token.FileSet, checkers Feature) *FileProcessor {
+func NewFileProcessor(checkers Feature) *FileProcessor {
return &FileProcessor{
- fset: fset,
structs: make(map[string]*StructHolder),
features: checkers,
}
}
// Analyze check whether the order of the methods in the constructor is correct.
-func (fp *FileProcessor) Analyze() []analysis.Diagnostic {
- var reports []analysis.Diagnostic
-
+func (fp *FileProcessor) Analyze(pass *analysis.Pass) {
for _, sh := range fp.structs {
// filter out structs that are not declared inside that file
if sh.Struct != nil {
- reports = append(reports, sh.Analyze()...)
+ sh.Analyze(pass)
}
}
- return reports
+ if fp.features.IsEnabled(FunctionCheck) {
+ fp.analyzeFunctions(pass)
+ }
}
-func (fp *FileProcessor) NewFileNode(_ *ast.File) {
+func (fp *FileProcessor) ResetStructs() {
fp.structs = make(map[string]*StructHolder)
+ fp.topLevelFuncs = nil
}
-func (fp *FileProcessor) NewFuncDecl(n *ast.FuncDecl) {
- if sc, ok := NewStructConstructor(n); ok {
- fp.addConstructor(sc)
+func (fp *FileProcessor) AddFuncDecl(n *ast.FuncDecl) {
+ if fp.features.IsEnabled(FunctionCheck) && n.Recv == nil {
+ fp.topLevelFuncs = append(fp.topLevelFuncs, n)
+ }
+
+ if sc := NewStructConstructor(n); sc != nil {
+ sh := fp.getOrCreate(sc.StructReturn.Name)
+ sh.Constructors = append(sh.Constructors, sc.Constructor)
+
return
}
- if st, ok := FuncIsMethod(n); ok {
- fp.addMethod(st.Name, n)
+ if st := funcIsMethod(n); st != nil {
+ sh := fp.getOrCreate(st.Name)
+ sh.StructMethods = append(sh.StructMethods, n)
}
}
-func (fp *FileProcessor) NewTypeSpec(n *ast.TypeSpec) {
+func (fp *FileProcessor) AddTypeSpec(n *ast.TypeSpec) {
sh := fp.getOrCreate(n.Name.Name)
sh.Struct = n
}
-func (fp *FileProcessor) addConstructor(sc StructConstructor) {
- sh := fp.getOrCreate(sc.GetStructReturn().Name)
- sh.AddConstructor(sc.GetConstructor())
-}
+// analyzeFunctions reports every unexported top-level function that appears
+// before the last exported top-level function in source order.
+// The `init` function is excluded from this check.
+func (fp *FileProcessor) analyzeFunctions(pass *analysis.Pass) {
+ var lastExported *ast.FuncDecl
+
+ for _, fn := range fp.topLevelFuncs {
+ if fn.Name.Name == "init" {
+ continue
+ }
+
+ if !fn.Name.IsExported() {
+ continue
+ }
+
+ if lastExported == nil || fn.Pos() > lastExported.Pos() {
+ lastExported = fn
+ }
+ }
+
+ if lastExported == nil {
+ return
+ }
-func (fp *FileProcessor) addMethod(st string, n *ast.FuncDecl) {
- sh := fp.getOrCreate(st)
- sh.AddMethod(n)
+ for _, fn := range fp.topLevelFuncs {
+ if fn.Name.Name == "init" {
+ continue
+ }
+
+ if fn.Name.IsExported() || fn.Pos() >= lastExported.Pos() {
+ continue
+ }
+
+ reportUnexportedFuncBeforeExportedFunc(pass, fn, lastExported)
+ }
}
func (fp *FileProcessor) getOrCreate(structName string) *StructHolder {
@@ -73,10 +106,34 @@ func (fp *FileProcessor) getOrCreate(structName string) *StructHolder {
}
created := &StructHolder{
- Fset: fp.fset,
Features: fp.features,
}
fp.structs[structName] = created
return created
}
+
+func funcIsMethod(n *ast.FuncDecl) *ast.Ident {
+ if n.Recv == nil {
+ return nil
+ }
+
+ if len(n.Recv.List) != 1 {
+ return nil
+ }
+
+ return getIdent(n.Recv.List[0].Type)
+}
+
+func getIdent(expr ast.Expr) *ast.Ident {
+ switch exp := expr.(type) {
+ case *ast.StarExpr:
+ return getIdent(exp.X)
+
+ case *ast.Ident:
+ return exp
+
+ default:
+ return nil
+ }
+}
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/diag.go b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/reports.go
similarity index 58%
rename from hack/tools/vendor/github.com/manuelarte/funcorder/internal/diag.go
rename to hack/tools/vendor/github.com/manuelarte/funcorder/internal/reports.go
index faf2ffdd169..350ac05eb47 100644
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/diag.go
+++ b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/reports.go
@@ -7,63 +7,72 @@ import (
"golang.org/x/tools/go/analysis"
)
-func NewConstructorNotAfterStructType(structSpec *ast.TypeSpec, constructor *ast.FuncDecl) analysis.Diagnostic {
- return analysis.Diagnostic{
+func reportConstructorNotAfterStructType(pass *analysis.Pass, structSpec *ast.TypeSpec, constructor *ast.FuncDecl) {
+ pass.Report(analysis.Diagnostic{
Pos: constructor.Pos(),
Message: fmt.Sprintf("constructor %q for struct %q should be placed after the struct declaration",
constructor.Name, structSpec.Name),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructors-functions-are-placed-after-struct-declaration", //nolint:lll // url
- }
+ })
}
-func NewConstructorNotBeforeStructMethod(
+func reportConstructorNotBeforeStructMethod(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- constructor *ast.FuncDecl,
- method *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ constructor, method *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: constructor.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructors-functions-are-placed-after-struct-declaration", //nolint:lll // url
Message: fmt.Sprintf("constructor %q for struct %q should be placed before struct method %q",
constructor.Name, structSpec.Name, method.Name),
- }
+ })
}
-func NewAdjacentConstructorsNotSortedAlphabetically(
+func reportAdjacentConstructorsNotSortedAlphabetically(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- constructorNotSorted *ast.FuncDecl,
- otherConstructorNotSorted *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ constructorNotSorted, otherConstructorNotSorted *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: otherConstructorNotSorted.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructorsmethods-are-sorted-alphabetically",
Message: fmt.Sprintf("constructor %q for struct %q should be placed before constructor %q",
otherConstructorNotSorted.Name, structSpec.Name, constructorNotSorted.Name),
- }
+ })
}
-func NewUnexportedMethodBeforeExportedForStruct(
+func reportUnexportedMethodBeforeExportedForStruct(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- privateMethod *ast.FuncDecl,
- publicMethod *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ privateMethod, publicMethod *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: privateMethod.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-exported-methods-are-placed-before-unexported-methods", //nolint:lll // url
Message: fmt.Sprintf("unexported method %q for struct %q should be placed after the exported method %q",
privateMethod.Name, structSpec.Name, publicMethod.Name),
- }
+ })
}
-func NewAdjacentStructMethodsNotSortedAlphabetically(
+func reportAdjacentStructMethodsNotSortedAlphabetically(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- method *ast.FuncDecl,
- otherMethod *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ method, otherMethod *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: otherMethod.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructorsmethods-are-sorted-alphabetically",
Message: fmt.Sprintf("method %q for struct %q should be placed before method %q",
otherMethod.Name, structSpec.Name, method.Name),
- }
+ })
+}
+
+func reportUnexportedFuncBeforeExportedFunc(pass *analysis.Pass, unexportedFunc, exportedFunc *ast.FuncDecl) {
+ pass.Report(analysis.Diagnostic{
+ Pos: unexportedFunc.Pos(),
+ URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-exported-functions-are-placed-before-unexported-functions", //nolint:lll // url
+ Message: fmt.Sprintf("unexported function %q should be placed after the exported function %q",
+ unexportedFunc.Name, exportedFunc.Name),
+ })
}
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go
index fc4b252dfea..c036fc1381a 100644
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go
+++ b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go
@@ -2,36 +2,47 @@ package internal
import (
"go/ast"
+ "strings"
)
type StructConstructor struct {
- constructor *ast.FuncDecl
- structReturn *ast.Ident
+ Constructor *ast.FuncDecl
+ StructReturn *ast.Ident
}
-func NewStructConstructor(funcDec *ast.FuncDecl) (StructConstructor, bool) {
- if !FuncCanBeConstructor(funcDec) {
- return StructConstructor{}, false
+func NewStructConstructor(funcDec *ast.FuncDecl) *StructConstructor {
+ if !funcCanBeConstructor(funcDec) {
+ return nil
}
expr := funcDec.Type.Results.List[0].Type
- returnType, ok := GetIdent(expr)
- if !ok {
- return StructConstructor{}, false
+ returnType := getIdent(expr)
+ if returnType == nil {
+ return nil
}
- return StructConstructor{
- constructor: funcDec,
- structReturn: returnType,
- }, true
+ return &StructConstructor{
+ Constructor: funcDec,
+ StructReturn: returnType,
+ }
}
-// GetStructReturn Return the struct linked to this "constructor".
-func (sc StructConstructor) GetStructReturn() *ast.Ident {
- return sc.structReturn
-}
+func funcCanBeConstructor(n *ast.FuncDecl) bool {
+ if !n.Name.IsExported() || n.Recv != nil {
+ return false
+ }
+
+ if n.Type.Results == nil || len(n.Type.Results.List) == 0 {
+ return false
+ }
+
+ for _, prefix := range []string{"new", "must"} {
+ if strings.HasPrefix(strings.ToLower(n.Name.Name), prefix) &&
+ len(n.Name.Name) > len(prefix) { // TODO(ldez): bug if the name is just `New`.
+ return true
+ }
+ }
-func (sc StructConstructor) GetConstructor() *ast.FuncDecl {
- return sc.constructor
+ return false
}
diff --git a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/structholder.go b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/structholder.go
index 424b2ddd712..30042211561 100644
--- a/hack/tools/vendor/github.com/manuelarte/funcorder/internal/structholder.go
+++ b/hack/tools/vendor/github.com/manuelarte/funcorder/internal/structholder.go
@@ -3,21 +3,13 @@ package internal
import (
"cmp"
"go/ast"
- "go/token"
"slices"
"golang.org/x/tools/go/analysis"
)
-type (
- ExportedMethods []*ast.FuncDecl
- UnexportedMethods []*ast.FuncDecl
-)
-
// StructHolder contains all the information around a Go struct.
type StructHolder struct {
- // The fileset
- Fset *token.FileSet
// The features to be analyzed
Features Feature
@@ -31,59 +23,42 @@ type StructHolder struct {
StructMethods []*ast.FuncDecl
}
-func (sh *StructHolder) AddConstructor(fn *ast.FuncDecl) {
- sh.Constructors = append(sh.Constructors, fn)
-}
-
-func (sh *StructHolder) AddMethod(fn *ast.FuncDecl) {
- sh.StructMethods = append(sh.StructMethods, fn)
-}
-
// Analyze applies the linter to the struct holder.
-func (sh *StructHolder) Analyze() []analysis.Diagnostic {
+func (sh *StructHolder) Analyze(pass *analysis.Pass) {
// TODO maybe sort constructors and then report also, like NewXXX before MustXXX
slices.SortFunc(sh.StructMethods, func(a, b *ast.FuncDecl) int {
return cmp.Compare(a.Pos(), b.Pos())
})
- var reports []analysis.Diagnostic
+ // TODO also check that the methods are declared after the struct
if sh.Features.IsEnabled(ConstructorCheck) {
- reports = append(reports, sh.analyzeConstructor()...)
+ sh.analyzeConstructor(pass)
}
if sh.Features.IsEnabled(StructMethodCheck) {
- reports = append(reports, sh.analyzeStructMethod()...)
+ sh.analyzeStructMethod(pass)
}
-
- // TODO also check that the methods are declared after the struct
- return reports
}
-func (sh *StructHolder) analyzeConstructor() []analysis.Diagnostic {
- var reports []analysis.Diagnostic
-
+func (sh *StructHolder) analyzeConstructor(pass *analysis.Pass) {
for i, constructor := range sh.Constructors {
if constructor.Pos() < sh.Struct.Pos() {
- reports = append(reports, NewConstructorNotAfterStructType(sh.Struct, constructor))
+ reportConstructorNotAfterStructType(pass, sh.Struct, constructor)
}
if len(sh.StructMethods) > 0 && constructor.Pos() > sh.StructMethods[0].Pos() {
- reports = append(reports, NewConstructorNotBeforeStructMethod(sh.Struct, constructor, sh.StructMethods[0]))
+ reportConstructorNotBeforeStructMethod(pass, sh.Struct, constructor, sh.StructMethods[0])
}
if sh.Features.IsEnabled(AlphabeticalCheck) &&
i < len(sh.Constructors)-1 && sh.Constructors[i].Name.Name > sh.Constructors[i+1].Name.Name {
- reports = append(reports,
- NewAdjacentConstructorsNotSortedAlphabetically(sh.Struct, sh.Constructors[i], sh.Constructors[i+1]),
- )
+ reportAdjacentConstructorsNotSortedAlphabetically(pass, sh.Struct, sh.Constructors[i], sh.Constructors[i+1])
}
}
-
- return reports
}
-func (sh *StructHolder) analyzeStructMethod() []analysis.Diagnostic {
+func (sh *StructHolder) analyzeStructMethod(pass *analysis.Pass) {
var lastExportedMethod *ast.FuncDecl
for _, m := range sh.StructMethods {
@@ -100,42 +75,46 @@ func (sh *StructHolder) analyzeStructMethod() []analysis.Diagnostic {
}
}
- var reports []analysis.Diagnostic
-
if lastExportedMethod != nil {
for _, m := range sh.StructMethods {
if m.Name.IsExported() || m.Pos() >= lastExportedMethod.Pos() {
continue
}
- reports = append(reports, NewUnexportedMethodBeforeExportedForStruct(sh.Struct, m, lastExportedMethod))
+ reportUnexportedMethodBeforeExportedForStruct(pass, sh.Struct, m, lastExportedMethod)
}
}
if sh.Features.IsEnabled(AlphabeticalCheck) {
- exported, unexported := SplitExportedUnexported(sh.StructMethods)
- reports = slices.Concat(reports,
- sortDiagnostics(sh.Struct, exported),
- sortDiagnostics(sh.Struct, unexported),
- )
+ exported, unexported := splitExportedUnexported(sh.StructMethods)
+ sh.sortDiagnostics(pass, exported)
+ sh.sortDiagnostics(pass, unexported)
}
-
- return reports
}
-func sortDiagnostics(typeSpec *ast.TypeSpec, funcDecls []*ast.FuncDecl) []analysis.Diagnostic {
- var reports []analysis.Diagnostic
-
+func (sh *StructHolder) sortDiagnostics(pass *analysis.Pass, funcDecls []*ast.FuncDecl) {
for i := range funcDecls {
if i >= len(funcDecls)-1 {
continue
}
if funcDecls[i].Name.Name > funcDecls[i+1].Name.Name {
- reports = append(reports,
- NewAdjacentStructMethodsNotSortedAlphabetically(typeSpec, funcDecls[i], funcDecls[i+1]))
+ reportAdjacentStructMethodsNotSortedAlphabetically(pass, sh.Struct, funcDecls[i], funcDecls[i+1])
+ }
+ }
+}
+
+// splitExportedUnexported split functions/methods based on whether they are exported or not.
+//
+//nolint:nonamedreturns // names serve as documentation
+func splitExportedUnexported(funcDecls []*ast.FuncDecl) (exported, unexported []*ast.FuncDecl) {
+ for _, f := range funcDecls {
+ if f.Name.IsExported() {
+ exported = append(exported, f)
+ } else {
+ unexported = append(unexported, f)
}
}
- return reports
+ return exported, unexported
}
diff --git a/hack/tools/vendor/github.com/mattn/go-runewidth/benchstat.txt b/hack/tools/vendor/github.com/mattn/go-runewidth/benchstat.txt
new file mode 100644
index 00000000000..a9efdbde37f
--- /dev/null
+++ b/hack/tools/vendor/github.com/mattn/go-runewidth/benchstat.txt
@@ -0,0 +1,43 @@
+goos: darwin
+goarch: arm64
+pkg: github.com/mattn/go-runewidth
+cpu: Apple M2
+ │ old.txt │ new.txt │
+ │ sec/op │ sec/op vs base │
+String1WidthAll/regular-8 108.92m ± 0% 35.09m ± 3% -67.78% (p=0.002 n=6)
+String1WidthAll/lut-8 93.97m ± 0% 18.70m ± 0% -80.10% (p=0.002 n=6)
+String1Width768/regular-8 60.62µ ± 1% 11.54µ ± 0% -80.97% (p=0.002 n=6)
+String1Width768/lut-8 60.66µ ± 1% 11.43µ ± 0% -81.16% (p=0.002 n=6)
+String1WidthAllEastAsian/regular-8 115.13m ± 1% 40.79m ± 8% -64.57% (p=0.002 n=6)
+String1WidthAllEastAsian/lut-8 93.65m ± 0% 18.70m ± 2% -80.03% (p=0.002 n=6)
+String1Width768EastAsian/regular-8 75.32µ ± 0% 23.49µ ± 0% -68.82% (p=0.002 n=6)
+String1Width768EastAsian/lut-8 60.76µ ± 0% 11.50µ ± 0% -81.07% (p=0.002 n=6)
+geomean 2.562m 604.5µ -76.41%
+
+ │ old.txt │ new.txt │
+ │ B/op │ B/op vs base │
+String1WidthAll/regular-8 106.3Mi ± 0% 0.0Mi ± 0% -100.00% (p=0.002 n=6)
+String1WidthAll/lut-8 106.3Mi ± 0% 0.0Mi ± 0% -100.00% (p=0.002 n=6)
+String1Width768/regular-8 75.00Ki ± 0% 0.00Ki ± 0% -100.00% (p=0.002 n=6)
+String1Width768/lut-8 75.00Ki ± 0% 0.00Ki ± 0% -100.00% (p=0.002 n=6)
+String1WidthAllEastAsian/regular-8 106.3Mi ± 0% 0.0Mi ± 0% -100.00% (p=0.002 n=6)
+String1WidthAllEastAsian/lut-8 106.3Mi ± 0% 0.0Mi ± 0% -100.00% (p=0.002 n=6)
+String1Width768EastAsian/regular-8 75.00Ki ± 0% 0.00Ki ± 0% -100.00% (p=0.002 n=6)
+String1Width768EastAsian/lut-8 75.00Ki ± 0% 0.00Ki ± 0% -100.00% (p=0.002 n=6)
+geomean 2.790Mi ? ¹ ²
+¹ summaries must be >0 to compute geomean
+² ratios must be >0 to compute geomean
+
+ │ old.txt │ new.txt │
+ │ allocs/op │ allocs/op vs base │
+String1WidthAll/regular-8 3.342M ± 0% 0.000M ± 0% -100.00% (p=0.002 n=6)
+String1WidthAll/lut-8 3.342M ± 0% 0.000M ± 0% -100.00% (p=0.002 n=6)
+String1Width768/regular-8 2.304k ± 0% 0.000k ± 0% -100.00% (p=0.002 n=6)
+String1Width768/lut-8 2.304k ± 0% 0.000k ± 0% -100.00% (p=0.002 n=6)
+String1WidthAllEastAsian/regular-8 3.342M ± 0% 0.000M ± 0% -100.00% (p=0.002 n=6)
+String1WidthAllEastAsian/lut-8 3.342M ± 0% 0.000M ± 0% -100.00% (p=0.002 n=6)
+String1Width768EastAsian/regular-8 2.304k ± 0% 0.000k ± 0% -100.00% (p=0.002 n=6)
+String1Width768EastAsian/lut-8 2.304k ± 0% 0.000k ± 0% -100.00% (p=0.002 n=6)
+geomean 87.75k ? ¹ ²
+¹ summaries must be >0 to compute geomean
+² ratios must be >0 to compute geomean
diff --git a/hack/tools/vendor/github.com/mattn/go-runewidth/new.txt b/hack/tools/vendor/github.com/mattn/go-runewidth/new.txt
new file mode 100644
index 00000000000..8890712562f
--- /dev/null
+++ b/hack/tools/vendor/github.com/mattn/go-runewidth/new.txt
@@ -0,0 +1,54 @@
+goos: darwin
+goarch: arm64
+pkg: github.com/mattn/go-runewidth
+cpu: Apple M2
+BenchmarkString1WidthAll/regular-8 33 35033923 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/regular-8 33 34965112 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/regular-8 33 36307234 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/regular-8 33 35007705 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/regular-8 33 35154182 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/regular-8 34 35155400 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/lut-8 63 18688500 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/lut-8 63 18712474 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/lut-8 63 18700211 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/lut-8 62 18694179 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/lut-8 62 18708392 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAll/lut-8 63 18770608 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/regular-8 104137 11526 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/regular-8 103986 11540 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/regular-8 104079 11552 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/regular-8 103963 11530 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/regular-8 103714 11538 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/regular-8 104181 11537 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/lut-8 105150 11420 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/lut-8 104778 11423 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/lut-8 105069 11422 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/lut-8 105127 11475 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/lut-8 104742 11433 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768/lut-8 105163 11432 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 28 40723347 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 28 40790299 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 28 40801338 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 28 40798216 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 28 44135253 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 28 40779546 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 62 18694165 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 62 18685047 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 62 18689273 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 62 19150346 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 63 19126154 ns/op 0 B/op 0 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 62 18712619 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 50775 23595 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 51061 23563 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 51057 23492 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 51138 23445 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 51195 23469 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 51087 23482 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 104559 11549 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 104508 11483 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 104296 11503 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 104606 11485 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 104588 11495 ns/op 0 B/op 0 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 104602 11518 ns/op 0 B/op 0 allocs/op
+PASS
+ok github.com/mattn/go-runewidth 64.455s
diff --git a/hack/tools/vendor/github.com/mattn/go-runewidth/old.txt b/hack/tools/vendor/github.com/mattn/go-runewidth/old.txt
new file mode 100644
index 00000000000..5b9ac164683
--- /dev/null
+++ b/hack/tools/vendor/github.com/mattn/go-runewidth/old.txt
@@ -0,0 +1,54 @@
+goos: darwin
+goarch: arm64
+pkg: github.com/mattn/go-runewidth
+cpu: Apple M2
+BenchmarkString1WidthAll/regular-8 10 108559258 ns/op 111412145 B/op 3342342 allocs/op
+BenchmarkString1WidthAll/regular-8 10 108968079 ns/op 111412364 B/op 3342343 allocs/op
+BenchmarkString1WidthAll/regular-8 10 108890338 ns/op 111412388 B/op 3342344 allocs/op
+BenchmarkString1WidthAll/regular-8 10 108940704 ns/op 111412584 B/op 3342346 allocs/op
+BenchmarkString1WidthAll/regular-8 10 108632796 ns/op 111412348 B/op 3342343 allocs/op
+BenchmarkString1WidthAll/regular-8 10 109354546 ns/op 111412777 B/op 3342343 allocs/op
+BenchmarkString1WidthAll/lut-8 12 93844406 ns/op 111412569 B/op 3342345 allocs/op
+BenchmarkString1WidthAll/lut-8 12 93991080 ns/op 111412512 B/op 3342344 allocs/op
+BenchmarkString1WidthAll/lut-8 12 93980632 ns/op 111412413 B/op 3342343 allocs/op
+BenchmarkString1WidthAll/lut-8 12 94004083 ns/op 111412396 B/op 3342343 allocs/op
+BenchmarkString1WidthAll/lut-8 12 93959795 ns/op 111412445 B/op 3342343 allocs/op
+BenchmarkString1WidthAll/lut-8 12 93846198 ns/op 111412556 B/op 3342345 allocs/op
+BenchmarkString1Width768/regular-8 19785 60696 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/regular-8 19824 60520 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/regular-8 19832 60547 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/regular-8 19778 60543 ns/op 76800 B/op 2304 allocs/op
+BenchmarkString1Width768/regular-8 19842 61142 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/regular-8 19780 60696 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/lut-8 19598 61161 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/lut-8 19731 60707 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/lut-8 19738 60626 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/lut-8 19764 60670 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/lut-8 19797 60642 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768/lut-8 19738 60608 ns/op 76800 B/op 2304 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 9 115080431 ns/op 111412458 B/op 3342345 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 9 114908880 ns/op 111412476 B/op 3342345 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 9 115077134 ns/op 111412540 B/op 3342345 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 9 115175292 ns/op 111412467 B/op 3342345 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 9 115792653 ns/op 111412362 B/op 3342344 allocs/op
+BenchmarkString1WidthAllEastAsian/regular-8 9 115255417 ns/op 111412572 B/op 3342346 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 12 93761542 ns/op 111412538 B/op 3342345 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 12 94089990 ns/op 111412440 B/op 3342343 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 12 93721410 ns/op 111412514 B/op 3342344 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 12 93572951 ns/op 111412329 B/op 3342342 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 12 93536052 ns/op 111412206 B/op 3342341 allocs/op
+BenchmarkString1WidthAllEastAsian/lut-8 12 93532365 ns/op 111412412 B/op 3342343 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 15904 75401 ns/op 76800 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 15932 75449 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 15944 75181 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 15963 75311 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 15879 75292 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/regular-8 15955 75334 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 19692 60692 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 19712 60699 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 19741 60819 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 19771 60653 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 19737 61027 ns/op 76801 B/op 2304 allocs/op
+BenchmarkString1Width768EastAsian/lut-8 19657 60820 ns/op 76801 B/op 2304 allocs/op
+PASS
+ok github.com/mattn/go-runewidth 76.165s
diff --git a/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth.go b/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth.go
index 7dfbb3be91d..f6c0058222b 100644
--- a/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth.go
+++ b/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth.go
@@ -3,8 +3,9 @@ package runewidth
import (
"os"
"strings"
+ "unicode/utf8"
- "github.com/rivo/uniseg"
+ "github.com/clipperhouse/uax29/v2/graphemes"
)
//go:generate go run script/generate.go
@@ -23,10 +24,48 @@ var (
}
)
+var (
+ zerowidth table // combining + nonprint merged for faster zero-width lookup
+ widewidth table // ambiguous + doublewidth merged for EA path
+)
+
func init() {
+ zerowidth = mergeIntervals(combining, nonprint)
+ widewidth = mergeIntervals(ambiguous, doublewidth)
handleEnv()
}
+func mergeIntervals(t1, t2 table) table {
+ merged := make(table, 0, len(t1)+len(t2))
+ i, j := 0, 0
+ for i < len(t1) && j < len(t2) {
+ if t1[i].first <= t2[j].first {
+ merged = append(merged, t1[i])
+ i++
+ } else {
+ merged = append(merged, t2[j])
+ j++
+ }
+ }
+ merged = append(merged, t1[i:]...)
+ merged = append(merged, t2[j:]...)
+ if len(merged) == 0 {
+ return merged
+ }
+ result := merged[:1]
+ for _, iv := range merged[1:] {
+ last := &result[len(result)-1]
+ if iv.first <= last.last+1 {
+ if iv.last > last.last {
+ last.last = iv.last
+ }
+ } else {
+ result = append(result, iv)
+ }
+ }
+ return result
+}
+
func handleEnv() {
env := os.Getenv("RUNEWIDTH_EASTASIAN")
if env == "" {
@@ -51,19 +90,13 @@ type interval struct {
type table []interval
-func inTables(r rune, ts ...table) bool {
- for _, t := range ts {
- if inTable(r, t) {
- return true
- }
- }
- return false
-}
-
func inTable(r rune, t table) bool {
if r < t[0].first {
return false
}
+ if r > t[len(t)-1].last {
+ return false
+ }
bot := 0
top := len(t) - 1
@@ -127,9 +160,7 @@ func (c *Condition) RuneWidth(r rune) int {
return 0
case r < 0x300:
return 1
- case inTable(r, narrow):
- return 1
- case inTables(r, nonprint, combining):
+ case inTable(r, zerowidth):
return 0
case inTable(r, doublewidth):
return 2
@@ -138,13 +169,13 @@ func (c *Condition) RuneWidth(r rune) int {
}
} else {
switch {
- case inTables(r, nonprint, combining):
+ case inTable(r, zerowidth):
return 0
case inTable(r, narrow):
return 1
- case inTables(r, ambiguous, doublewidth):
+ case inTable(r, widewidth):
return 2
- case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
+ case !c.StrictEmojiNeutral && inTable(r, emoji):
return 2
default:
return 1
@@ -175,10 +206,26 @@ func (c *Condition) CreateLUT() {
// StringWidth return width as you can see
func (c *Condition) StringWidth(s string) (width int) {
- g := uniseg.NewGraphemes(s)
+ if len(s) > 0 && len(s) <= utf8.UTFMax {
+ r, size := utf8.DecodeRuneInString(s)
+ if size == len(s) {
+ return c.RuneWidth(r)
+ }
+ }
+ // ASCII fast path: no grapheme clustering needed for pure ASCII
+ if isAllASCII(s) {
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if b >= 0x20 && b != 0x7F {
+ width++
+ }
+ }
+ return
+ }
+ g := graphemes.FromString(s)
for g.Next() {
var chWidth int
- for _, r := range g.Runes() {
+ for _, r := range g.Value() {
chWidth = c.RuneWidth(r)
if chWidth > 0 {
break // Our best guess at this point is to use the width of the first non-zero-width rune.
@@ -189,6 +236,15 @@ func (c *Condition) StringWidth(s string) (width int) {
return
}
+func isAllASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= 0x80 {
+ return false
+ }
+ }
+ return true
+}
+
// Truncate return string truncated with w cells
func (c *Condition) Truncate(s string, w int, tail string) string {
if c.StringWidth(s) <= w {
@@ -197,17 +253,17 @@ func (c *Condition) Truncate(s string, w int, tail string) string {
w -= c.StringWidth(tail)
var width int
pos := len(s)
- g := uniseg.NewGraphemes(s)
+ g := graphemes.FromString(s)
for g.Next() {
var chWidth int
- for _, r := range g.Runes() {
+ for _, r := range g.Value() {
chWidth = c.RuneWidth(r)
if chWidth > 0 {
break // See StringWidth() for details.
}
}
if width+chWidth > w {
- pos, _ = g.Positions()
+ pos = g.Start()
break
}
width += chWidth
@@ -224,10 +280,10 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
var width int
pos := len(s)
- g := uniseg.NewGraphemes(s)
+ g := graphemes.FromString(s)
for g.Next() {
var chWidth int
- for _, r := range g.Runes() {
+ for _, r := range g.Value() {
chWidth = c.RuneWidth(r)
if chWidth > 0 {
break // See StringWidth() for details.
@@ -236,10 +292,10 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
if width+chWidth > w {
if width < w {
- _, pos = g.Positions()
+ pos = g.End()
prefix += strings.Repeat(" ", width+chWidth-w)
} else {
- pos, _ = g.Positions()
+ pos = g.Start()
}
break
@@ -254,24 +310,25 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
// Wrap return string wrapped with w cells
func (c *Condition) Wrap(s string, w int) string {
width := 0
- out := ""
+ var out strings.Builder
+ out.Grow(len(s) + len(s)/w + 1)
for _, r := range s {
cw := c.RuneWidth(r)
if r == '\n' {
- out += string(r)
+ out.WriteRune(r)
width = 0
continue
} else if width+cw > w {
- out += "\n"
+ out.WriteByte('\n')
width = 0
- out += string(r)
+ out.WriteRune(r)
width += cw
continue
}
- out += string(r)
+ out.WriteRune(r)
width += cw
}
- return out
+ return out.String()
}
// FillLeft return string filled in left by spaces in w cells
@@ -310,7 +367,12 @@ func RuneWidth(r rune) int {
// IsAmbiguousWidth returns whether is ambiguous width or not.
func IsAmbiguousWidth(r rune) bool {
- return inTables(r, private, ambiguous)
+ return inTable(r, private) || inTable(r, ambiguous)
+}
+
+// IsCombiningWidth returns whether is combining width or not.
+func IsCombiningWidth(r rune) bool {
+ return inTable(r, combining)
}
// IsNeutralWidth returns whether is neutral width or not.
diff --git a/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_table.go b/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_table.go
index ad025ad5296..cdd003e646c 100644
--- a/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_table.go
+++ b/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_table.go
@@ -5,47 +5,50 @@ package runewidth
var combining = table{
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0CF3, 0x0CF3},
- {0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x1A7F, 0x1A7F},
- {0x1AB0, 0x1ACE}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF},
+ {0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x180B, 0x180D},
+ {0x180F, 0x180F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1ADD},
+ {0x1AE0, 0x1AEB}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF},
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF},
{0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D},
{0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1},
- {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A},
- {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x10F82, 0x10F85},
- {0x11300, 0x11301}, {0x1133B, 0x1133C}, {0x11366, 0x1136C},
- {0x11370, 0x11374}, {0x16AF0, 0x16AF4}, {0x1CF00, 0x1CF2D},
- {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172},
- {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
- {0x1D242, 0x1D244}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018},
- {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A},
- {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6},
+ {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD},
+ {0x10376, 0x1037A}, {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50},
+ {0x10F82, 0x10F85}, {0x11300, 0x11301}, {0x1133B, 0x1133C},
+ {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x16AF0, 0x16AF4},
+ {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169},
+ {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B},
+ {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1E000, 0x1E006},
+ {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
+ {0x1E026, 0x1E02A}, {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6},
+ {0xE0100, 0xE01EF},
}
var doublewidth = table{
{0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A},
{0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3},
- {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653},
- {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1},
- {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
- {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA},
- {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA},
- {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B},
- {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E},
- {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797},
- {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C},
- {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99},
- {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x303E},
- {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312F},
- {0x3131, 0x318E}, {0x3190, 0x31E3}, {0x31EF, 0x321E},
- {0x3220, 0x3247}, {0x3250, 0x4DBF}, {0x4E00, 0xA48C},
- {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3},
- {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52},
- {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60},
- {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4}, {0x16FF0, 0x16FF1},
- {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08},
- {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1AFFD, 0x1AFFE},
- {0x1B000, 0x1B122}, {0x1B132, 0x1B132}, {0x1B150, 0x1B152},
- {0x1B155, 0x1B155}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB},
+ {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2630, 0x2637},
+ {0x2648, 0x2653}, {0x267F, 0x267F}, {0x268A, 0x268F},
+ {0x2693, 0x2693}, {0x26A1, 0x26A1}, {0x26AA, 0x26AB},
+ {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, {0x26CE, 0x26CE},
+ {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, {0x26F2, 0x26F3},
+ {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, {0x26FD, 0x26FD},
+ {0x2705, 0x2705}, {0x270A, 0x270B}, {0x2728, 0x2728},
+ {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
+ {0x2757, 0x2757}, {0x2795, 0x2797}, {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, {0x2B50, 0x2B50},
+ {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3},
+ {0x2F00, 0x2FD5}, {0x2FF0, 0x303E}, {0x3041, 0x3096},
+ {0x3099, 0x30FF}, {0x3105, 0x312F}, {0x3131, 0x318E},
+ {0x3190, 0x31E5}, {0x31EF, 0x321E}, {0x3220, 0x3247},
+ {0x3250, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C},
+ {0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19},
+ {0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
+ {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4},
+ {0x16FF0, 0x16FF6}, {0x17000, 0x18CD5}, {0x18CFF, 0x18D1E},
+ {0x18D80, 0x18DF2}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB},
+ {0x1AFFD, 0x1AFFE}, {0x1B000, 0x1B122}, {0x1B132, 0x1B132},
+ {0x1B150, 0x1B152}, {0x1B155, 0x1B155}, {0x1B164, 0x1B167},
+ {0x1B170, 0x1B2FB}, {0x1D300, 0x1D356}, {0x1D360, 0x1D376},
{0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E},
{0x1F191, 0x1F19A}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23B},
{0x1F240, 0x1F248}, {0x1F250, 0x1F251}, {0x1F260, 0x1F265},
@@ -56,12 +59,12 @@ var doublewidth = table{
{0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, {0x1F57A, 0x1F57A},
{0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F},
{0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2},
- {0x1F6D5, 0x1F6D7}, {0x1F6DC, 0x1F6DF}, {0x1F6EB, 0x1F6EC},
+ {0x1F6D5, 0x1F6D8}, {0x1F6DC, 0x1F6DF}, {0x1F6EB, 0x1F6EC},
{0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB}, {0x1F7F0, 0x1F7F0},
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F9FF},
- {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA88}, {0x1FA90, 0x1FABD},
- {0x1FABF, 0x1FAC5}, {0x1FACE, 0x1FADB}, {0x1FAE0, 0x1FAE8},
- {0x1FAF0, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
+ {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA8A}, {0x1FA8E, 0x1FAC6},
+ {0x1FAC8, 0x1FAC8}, {0x1FACD, 0x1FADC}, {0x1FADF, 0x1FAEA},
+ {0x1FAEF, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
}
var ambiguous = table{
@@ -121,10 +124,9 @@ var ambiguous = table{
{0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC},
{0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F},
{0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF},
- {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A},
- {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D},
- {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF},
- {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
+ {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, {0x1F110, 0x1F12D},
+ {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, {0x1F18F, 0x1F190},
+ {0x1F19B, 0x1F1AC}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
}
var narrow = table{
{0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6},
@@ -159,115 +161,116 @@ var neutral = table{
{0x0600, 0x070D}, {0x070F, 0x074A}, {0x074D, 0x07B1},
{0x07C0, 0x07FA}, {0x07FD, 0x082D}, {0x0830, 0x083E},
{0x0840, 0x085B}, {0x085E, 0x085E}, {0x0860, 0x086A},
- {0x0870, 0x088E}, {0x0890, 0x0891}, {0x0898, 0x0983},
- {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8},
- {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9},
- {0x09BC, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CE},
- {0x09D7, 0x09D7}, {0x09DC, 0x09DD}, {0x09DF, 0x09E3},
- {0x09E6, 0x09FE}, {0x0A01, 0x0A03}, {0x0A05, 0x0A0A},
- {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30},
- {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39},
- {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, {0x0A47, 0x0A48},
- {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, {0x0A59, 0x0A5C},
- {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76}, {0x0A81, 0x0A83},
- {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8},
- {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9},
- {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD},
- {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1},
- {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03}, {0x0B05, 0x0B0C},
- {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, {0x0B2A, 0x0B30},
- {0x0B32, 0x0B33}, {0x0B35, 0x0B39}, {0x0B3C, 0x0B44},
- {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57},
- {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63}, {0x0B66, 0x0B77},
- {0x0B82, 0x0B83}, {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90},
- {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C},
- {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA},
- {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8},
- {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7},
- {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C}, {0x0C0E, 0x0C10},
- {0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, {0x0C3C, 0x0C44},
- {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
- {0x0C58, 0x0C5A}, {0x0C5D, 0x0C5D}, {0x0C60, 0x0C63},
- {0x0C66, 0x0C6F}, {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90},
- {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
- {0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD},
- {0x0CD5, 0x0CD6}, {0x0CDD, 0x0CDE}, {0x0CE0, 0x0CE3},
- {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF3}, {0x0D00, 0x0D0C},
- {0x0D0E, 0x0D10}, {0x0D12, 0x0D44}, {0x0D46, 0x0D48},
- {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63}, {0x0D66, 0x0D7F},
- {0x0D81, 0x0D83}, {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1},
- {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6},
- {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6},
- {0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4},
- {0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82},
- {0x0E84, 0x0E84}, {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3},
- {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4},
- {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECE}, {0x0ED0, 0x0ED9},
- {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C},
- {0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC},
- {0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7},
- {0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248},
- {0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258},
- {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
- {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
- {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6},
- {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
- {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5},
- {0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8},
- {0x1700, 0x1715}, {0x171F, 0x1736}, {0x1740, 0x1753},
- {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1772, 0x1773},
- {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9},
- {0x1800, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA},
- {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B},
- {0x1930, 0x193B}, {0x1940, 0x1940}, {0x1944, 0x196D},
- {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
- {0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E},
- {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89}, {0x1A90, 0x1A99},
- {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ACE}, {0x1B00, 0x1B4C},
- {0x1B50, 0x1B7E}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37},
- {0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA},
- {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1F15},
- {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D},
- {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
- {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4},
- {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB},
- {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE},
- {0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017},
- {0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023},
- {0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034},
- {0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064},
- {0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080},
- {0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8},
- {0x20AA, 0x20AB}, {0x20AD, 0x20C0}, {0x20D0, 0x20F0},
- {0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108},
- {0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120},
- {0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152},
- {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F},
- {0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7},
- {0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6},
- {0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206},
- {0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210},
- {0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C},
- {0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226},
- {0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B},
- {0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251},
- {0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269},
- {0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285},
- {0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4},
- {0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319},
- {0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF},
- {0x23F1, 0x23F2}, {0x23F4, 0x2426}, {0x2440, 0x244A},
- {0x24EA, 0x24EA}, {0x254C, 0x254F}, {0x2574, 0x257F},
- {0x2590, 0x2591}, {0x2596, 0x259F}, {0x25A2, 0x25A2},
- {0x25AA, 0x25B1}, {0x25B4, 0x25B5}, {0x25B8, 0x25BB},
- {0x25BE, 0x25BF}, {0x25C2, 0x25C5}, {0x25C9, 0x25CA},
- {0x25CC, 0x25CD}, {0x25D2, 0x25E1}, {0x25E6, 0x25EE},
- {0x25F0, 0x25FC}, {0x25FF, 0x2604}, {0x2607, 0x2608},
- {0x260A, 0x260D}, {0x2610, 0x2613}, {0x2616, 0x261B},
- {0x261D, 0x261D}, {0x261F, 0x263F}, {0x2641, 0x2641},
- {0x2643, 0x2647}, {0x2654, 0x265F}, {0x2662, 0x2662},
- {0x2666, 0x2666}, {0x266B, 0x266B}, {0x266E, 0x266E},
- {0x2670, 0x267E}, {0x2680, 0x2692}, {0x2694, 0x269D},
+ {0x0870, 0x0891}, {0x0897, 0x0983}, {0x0985, 0x098C},
+ {0x098F, 0x0990}, {0x0993, 0x09A8}, {0x09AA, 0x09B0},
+ {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, {0x09BC, 0x09C4},
+ {0x09C7, 0x09C8}, {0x09CB, 0x09CE}, {0x09D7, 0x09D7},
+ {0x09DC, 0x09DD}, {0x09DF, 0x09E3}, {0x09E6, 0x09FE},
+ {0x0A01, 0x0A03}, {0x0A05, 0x0A0A}, {0x0A0F, 0x0A10},
+ {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, {0x0A32, 0x0A33},
+ {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A3C, 0x0A3C},
+ {0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
+ {0x0A51, 0x0A51}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E},
+ {0x0A66, 0x0A76}, {0x0A81, 0x0A83}, {0x0A85, 0x0A8D},
+ {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0},
+ {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5},
+ {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0},
+ {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1}, {0x0AF9, 0x0AFF},
+ {0x0B01, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10},
+ {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33},
+ {0x0B35, 0x0B39}, {0x0B3C, 0x0B44}, {0x0B47, 0x0B48},
+ {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57}, {0x0B5C, 0x0B5D},
+ {0x0B5F, 0x0B63}, {0x0B66, 0x0B77}, {0x0B82, 0x0B83},
+ {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95},
+ {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F},
+ {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9},
+ {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD},
+ {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA},
+ {0x0C00, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28},
+ {0x0C2A, 0x0C39}, {0x0C3C, 0x0C44}, {0x0C46, 0x0C48},
+ {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0C58, 0x0C5A},
+ {0x0C5C, 0x0C5D}, {0x0C60, 0x0C63}, {0x0C66, 0x0C6F},
+ {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8},
+ {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, {0x0CBC, 0x0CC4},
+ {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6},
+ {0x0CDC, 0x0CDE}, {0x0CE0, 0x0CE3}, {0x0CE6, 0x0CEF},
+ {0x0CF1, 0x0CF3}, {0x0D00, 0x0D0C}, {0x0D0E, 0x0D10},
+ {0x0D12, 0x0D44}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4F},
+ {0x0D54, 0x0D63}, {0x0D66, 0x0D7F}, {0x0D81, 0x0D83},
+ {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB},
+ {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA},
+ {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF},
+ {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4}, {0x0E01, 0x0E3A},
+ {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82}, {0x0E84, 0x0E84},
+ {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3}, {0x0EA5, 0x0EA5},
+ {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6},
+ {0x0EC8, 0x0ECE}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF},
+ {0x0F00, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F97},
+ {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC}, {0x0FCE, 0x0FDA},
+ {0x1000, 0x10C5}, {0x10C7, 0x10C7}, {0x10CD, 0x10CD},
+ {0x10D0, 0x10FF}, {0x1160, 0x1248}, {0x124A, 0x124D},
+ {0x1250, 0x1256}, {0x1258, 0x1258}, {0x125A, 0x125D},
+ {0x1260, 0x1288}, {0x128A, 0x128D}, {0x1290, 0x12B0},
+ {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C0, 0x12C0},
+ {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310},
+ {0x1312, 0x1315}, {0x1318, 0x135A}, {0x135D, 0x137C},
+ {0x1380, 0x1399}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD},
+ {0x1400, 0x169C}, {0x16A0, 0x16F8}, {0x1700, 0x1715},
+ {0x171F, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C},
+ {0x176E, 0x1770}, {0x1772, 0x1773}, {0x1780, 0x17DD},
+ {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x180A},
+ {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1878},
+ {0x1880, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E},
+ {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1940, 0x1940},
+ {0x1944, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB},
+ {0x19B0, 0x19C9}, {0x19D0, 0x19DA}, {0x19DE, 0x1A1B},
+ {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89},
+ {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ADD},
+ {0x1AE0, 0x1AEB}, {0x1B00, 0x1B4C}, {0x1B4E, 0x1BF3},
+ {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49}, {0x1C4D, 0x1C8A},
+ {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA},
+ {0x1D00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45},
+ {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59},
+ {0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D},
+ {0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3},
+ {0x1FD6, 0x1FDB}, {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4},
+ {0x1FF6, 0x1FFE}, {0x2000, 0x200F}, {0x2011, 0x2012},
+ {0x2017, 0x2017}, {0x201A, 0x201B}, {0x201E, 0x201F},
+ {0x2023, 0x2023}, {0x2028, 0x202F}, {0x2031, 0x2031},
+ {0x2034, 0x2034}, {0x2036, 0x203A}, {0x203C, 0x203D},
+ {0x203F, 0x2064}, {0x2066, 0x2071}, {0x2075, 0x207E},
+ {0x2080, 0x2080}, {0x2085, 0x208E}, {0x2090, 0x209C},
+ {0x20A0, 0x20A8}, {0x20AA, 0x20AB}, {0x20AD, 0x20C1},
+ {0x20D0, 0x20F0}, {0x2100, 0x2102}, {0x2104, 0x2104},
+ {0x2106, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2115},
+ {0x2117, 0x2120}, {0x2123, 0x2125}, {0x2127, 0x212A},
+ {0x212C, 0x2152}, {0x2155, 0x215A}, {0x215F, 0x215F},
+ {0x216C, 0x216F}, {0x217A, 0x2188}, {0x218A, 0x218B},
+ {0x219A, 0x21B7}, {0x21BA, 0x21D1}, {0x21D3, 0x21D3},
+ {0x21D5, 0x21E6}, {0x21E8, 0x21FF}, {0x2201, 0x2201},
+ {0x2204, 0x2206}, {0x2209, 0x220A}, {0x220C, 0x220E},
+ {0x2210, 0x2210}, {0x2212, 0x2214}, {0x2216, 0x2219},
+ {0x221B, 0x221C}, {0x2221, 0x2222}, {0x2224, 0x2224},
+ {0x2226, 0x2226}, {0x222D, 0x222D}, {0x222F, 0x2233},
+ {0x2238, 0x223B}, {0x223E, 0x2247}, {0x2249, 0x224B},
+ {0x224D, 0x2251}, {0x2253, 0x225F}, {0x2262, 0x2263},
+ {0x2268, 0x2269}, {0x226C, 0x226D}, {0x2270, 0x2281},
+ {0x2284, 0x2285}, {0x2288, 0x2294}, {0x2296, 0x2298},
+ {0x229A, 0x22A4}, {0x22A6, 0x22BE}, {0x22C0, 0x2311},
+ {0x2313, 0x2319}, {0x231C, 0x2328}, {0x232B, 0x23E8},
+ {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x2429},
+ {0x2440, 0x244A}, {0x24EA, 0x24EA}, {0x254C, 0x254F},
+ {0x2574, 0x257F}, {0x2590, 0x2591}, {0x2596, 0x259F},
+ {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, {0x25B4, 0x25B5},
+ {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, {0x25C2, 0x25C5},
+ {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, {0x25D2, 0x25E1},
+ {0x25E6, 0x25EE}, {0x25F0, 0x25FC}, {0x25FF, 0x2604},
+ {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613},
+ {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x262F},
+ {0x2638, 0x263F}, {0x2641, 0x2641}, {0x2643, 0x2647},
+ {0x2654, 0x265F}, {0x2662, 0x2662}, {0x2666, 0x2666},
+ {0x266B, 0x266B}, {0x266E, 0x266E}, {0x2670, 0x267E},
+ {0x2680, 0x2689}, {0x2690, 0x2692}, {0x2694, 0x269D},
{0x26A0, 0x26A0}, {0x26A2, 0x26A9}, {0x26AC, 0x26BC},
{0x26C0, 0x26C3}, {0x26E2, 0x26E2}, {0x26E4, 0x26E7},
{0x2700, 0x2704}, {0x2706, 0x2709}, {0x270C, 0x2727},
@@ -276,175 +279,210 @@ var neutral = table{
{0x2780, 0x2794}, {0x2798, 0x27AF}, {0x27B1, 0x27BE},
{0x27C0, 0x27E5}, {0x27EE, 0x2984}, {0x2987, 0x2B1A},
{0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73},
- {0x2B76, 0x2B95}, {0x2B97, 0x2CF3}, {0x2CF9, 0x2D25},
- {0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67},
- {0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6},
- {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
- {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6},
- {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E5D}, {0x303F, 0x303F},
- {0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
- {0xA700, 0xA7CA}, {0xA7D0, 0xA7D1}, {0xA7D3, 0xA7D3},
- {0xA7D5, 0xA7D9}, {0xA7F2, 0xA82C}, {0xA830, 0xA839},
- {0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9},
- {0xA8E0, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD},
- {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36},
- {0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2},
- {0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
- {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E},
- {0xAB30, 0xAB6B}, {0xAB70, 0xABED}, {0xABF0, 0xABF9},
- {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF},
- {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36},
- {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41},
- {0xFB43, 0xFB44}, {0xFB46, 0xFBC2}, {0xFBD3, 0xFD8F},
- {0xFD92, 0xFDC7}, {0xFDCF, 0xFDCF}, {0xFDF0, 0xFDFF},
- {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC},
- {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B},
- {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D},
- {0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA},
- {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E},
- {0x10190, 0x1019C}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD},
- {0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB},
- {0x10300, 0x10323}, {0x1032D, 0x1034A}, {0x10350, 0x1037A},
- {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
- {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3},
- {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
- {0x1056F, 0x1057A}, {0x1057C, 0x1058A}, {0x1058C, 0x10592},
- {0x10594, 0x10595}, {0x10597, 0x105A1}, {0x105A3, 0x105B1},
- {0x105B3, 0x105B9}, {0x105BB, 0x105BC}, {0x10600, 0x10736},
- {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785},
- {0x10787, 0x107B0}, {0x107B2, 0x107BA}, {0x10800, 0x10805},
- {0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838},
- {0x1083C, 0x1083C}, {0x1083F, 0x10855}, {0x10857, 0x1089E},
- {0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108F4, 0x108F5},
- {0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x1093F, 0x1093F},
- {0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03},
- {0x10A05, 0x10A06}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17},
- {0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48},
- {0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6},
- {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55},
- {0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C},
- {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2},
- {0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39},
- {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD},
- {0x10EB0, 0x10EB1}, {0x10EFD, 0x10F27}, {0x10F30, 0x10F59},
- {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB}, {0x10FE0, 0x10FF6},
- {0x11000, 0x1104D}, {0x11052, 0x11075}, {0x1107F, 0x110C2},
- {0x110CD, 0x110CD}, {0x110D0, 0x110E8}, {0x110F0, 0x110F9},
- {0x11100, 0x11134}, {0x11136, 0x11147}, {0x11150, 0x11176},
- {0x11180, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211},
- {0x11213, 0x11241}, {0x11280, 0x11286}, {0x11288, 0x11288},
- {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A9},
- {0x112B0, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11303},
- {0x11305, 0x1130C}, {0x1130F, 0x11310}, {0x11313, 0x11328},
- {0x1132A, 0x11330}, {0x11332, 0x11333}, {0x11335, 0x11339},
- {0x1133B, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D},
- {0x11350, 0x11350}, {0x11357, 0x11357}, {0x1135D, 0x11363},
- {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x1145B},
+ {0x2B76, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D27, 0x2D27},
+ {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D70},
+ {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE},
+ {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6},
+ {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
+ {0x2DE0, 0x2E5D}, {0x303F, 0x303F}, {0xA4D0, 0xA62B},
+ {0xA640, 0xA6F7}, {0xA700, 0xA7DC}, {0xA7F1, 0xA82C},
+ {0xA830, 0xA839}, {0xA840, 0xA877}, {0xA880, 0xA8C5},
+ {0xA8CE, 0xA8D9}, {0xA8E0, 0xA953}, {0xA95F, 0xA95F},
+ {0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE},
+ {0xAA00, 0xAA36}, {0xAA40, 0xAA4D}, {0xAA50, 0xAA59},
+ {0xAA5C, 0xAAC2}, {0xAADB, 0xAAF6}, {0xAB01, 0xAB06},
+ {0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, {0xAB20, 0xAB26},
+ {0xAB28, 0xAB2E}, {0xAB30, 0xAB6B}, {0xAB70, 0xABED},
+ {0xABF0, 0xABF9}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB},
+ {0xD800, 0xDFFF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17},
+ {0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E},
+ {0xFB40, 0xFB41}, {0xFB43, 0xFB44}, {0xFB46, 0xFDCF},
+ {0xFDF0, 0xFDFF}, {0xFE20, 0xFE2F}, {0xFE70, 0xFE74},
+ {0xFE76, 0xFEFC}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC},
+ {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A},
+ {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D},
+ {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133},
+ {0x10137, 0x1018E}, {0x10190, 0x1019C}, {0x101A0, 0x101A0},
+ {0x101D0, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0},
+ {0x102E0, 0x102FB}, {0x10300, 0x10323}, {0x1032D, 0x1034A},
+ {0x10350, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x103C3},
+ {0x103C8, 0x103D5}, {0x10400, 0x1049D}, {0x104A0, 0x104A9},
+ {0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527},
+ {0x10530, 0x10563}, {0x1056F, 0x1057A}, {0x1057C, 0x1058A},
+ {0x1058C, 0x10592}, {0x10594, 0x10595}, {0x10597, 0x105A1},
+ {0x105A3, 0x105B1}, {0x105B3, 0x105B9}, {0x105BB, 0x105BC},
+ {0x105C0, 0x105F3}, {0x10600, 0x10736}, {0x10740, 0x10755},
+ {0x10760, 0x10767}, {0x10780, 0x10785}, {0x10787, 0x107B0},
+ {0x107B2, 0x107BA}, {0x10800, 0x10805}, {0x10808, 0x10808},
+ {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C},
+ {0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF},
+ {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B},
+ {0x1091F, 0x10939}, {0x1093F, 0x10959}, {0x10980, 0x109B7},
+ {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06},
+ {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35},
+ {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58},
+ {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6},
+ {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72},
+ {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF},
+ {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
+ {0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, {0x10D40, 0x10D65},
+ {0x10D69, 0x10D85}, {0x10D8E, 0x10D8F}, {0x10E60, 0x10E7E},
+ {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10EB0, 0x10EB1},
+ {0x10EC2, 0x10EC7}, {0x10ED0, 0x10ED8}, {0x10EFA, 0x10F27},
+ {0x10F30, 0x10F59}, {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB},
+ {0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x11075},
+ {0x1107F, 0x110C2}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8},
+ {0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11147},
+ {0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4},
+ {0x11200, 0x11211}, {0x11213, 0x11241}, {0x11280, 0x11286},
+ {0x11288, 0x11288}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D},
+ {0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9},
+ {0x11300, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310},
+ {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333},
+ {0x11335, 0x11339}, {0x1133B, 0x11344}, {0x11347, 0x11348},
+ {0x1134B, 0x1134D}, {0x11350, 0x11350}, {0x11357, 0x11357},
+ {0x1135D, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374},
+ {0x11380, 0x11389}, {0x1138B, 0x1138B}, {0x1138E, 0x1138E},
+ {0x11390, 0x113B5}, {0x113B7, 0x113C0}, {0x113C2, 0x113C2},
+ {0x113C5, 0x113C5}, {0x113C7, 0x113CA}, {0x113CC, 0x113D5},
+ {0x113D7, 0x113D8}, {0x113E1, 0x113E2}, {0x11400, 0x1145B},
{0x1145D, 0x11461}, {0x11480, 0x114C7}, {0x114D0, 0x114D9},
{0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B9},
- {0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B},
- {0x11730, 0x11746}, {0x11800, 0x1183B}, {0x118A0, 0x118F2},
- {0x118FF, 0x11906}, {0x11909, 0x11909}, {0x1190C, 0x11913},
- {0x11915, 0x11916}, {0x11918, 0x11935}, {0x11937, 0x11938},
- {0x1193B, 0x11946}, {0x11950, 0x11959}, {0x119A0, 0x119A7},
- {0x119AA, 0x119D7}, {0x119DA, 0x119E4}, {0x11A00, 0x11A47},
- {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09},
- {0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, {0x11C38, 0x11C45},
- {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7},
- {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D08, 0x11D09},
- {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D},
- {0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65},
- {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E}, {0x11D90, 0x11D91},
- {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8},
- {0x11F00, 0x11F10}, {0x11F12, 0x11F3A}, {0x11F3E, 0x11F59},
+ {0x116C0, 0x116C9}, {0x116D0, 0x116E3}, {0x11700, 0x1171A},
+ {0x1171D, 0x1172B}, {0x11730, 0x11746}, {0x11800, 0x1183B},
+ {0x118A0, 0x118F2}, {0x118FF, 0x11906}, {0x11909, 0x11909},
+ {0x1190C, 0x11913}, {0x11915, 0x11916}, {0x11918, 0x11935},
+ {0x11937, 0x11938}, {0x1193B, 0x11946}, {0x11950, 0x11959},
+ {0x119A0, 0x119A7}, {0x119AA, 0x119D7}, {0x119DA, 0x119E4},
+ {0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8},
+ {0x11B00, 0x11B09}, {0x11B60, 0x11B67}, {0x11BC0, 0x11BE1},
+ {0x11BF0, 0x11BF9}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
+ {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F},
+ {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06},
+ {0x11D08, 0x11D09}, {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A},
+ {0x11D3C, 0x11D3D}, {0x11D3F, 0x11D47}, {0x11D50, 0x11D59},
+ {0x11D60, 0x11D65}, {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E},
+ {0x11D90, 0x11D91}, {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9},
+ {0x11DB0, 0x11DDB}, {0x11DE0, 0x11DE9}, {0x11EE0, 0x11EF8},
+ {0x11F00, 0x11F10}, {0x11F12, 0x11F3A}, {0x11F3E, 0x11F5A},
{0x11FB0, 0x11FB0}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399},
{0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
- {0x12F90, 0x12FF2}, {0x13000, 0x13455}, {0x14400, 0x14646},
- {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69},
- {0x16A6E, 0x16ABE}, {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED},
- {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45}, {0x16B50, 0x16B59},
- {0x16B5B, 0x16B61}, {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F},
- {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87},
- {0x16F8F, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C},
- {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3},
+ {0x12F90, 0x12FF2}, {0x13000, 0x13455}, {0x13460, 0x143FA},
+ {0x14400, 0x14646}, {0x16100, 0x16139}, {0x16800, 0x16A38},
+ {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16ABE},
+ {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5},
+ {0x16B00, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61},
+ {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16D40, 0x16D79},
+ {0x16E40, 0x16E9A}, {0x16EA0, 0x16EB8}, {0x16EBB, 0x16ED3},
+ {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F},
+ {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88},
+ {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, {0x1CC00, 0x1CCFC},
+ {0x1CD00, 0x1CEB3}, {0x1CEBA, 0x1CED0}, {0x1CEE0, 0x1CEF0},
{0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1CF50, 0x1CFC3},
{0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D1EA},
{0x1D200, 0x1D245}, {0x1D2C0, 0x1D2D3}, {0x1D2E0, 0x1D2F3},
- {0x1D300, 0x1D356}, {0x1D360, 0x1D378}, {0x1D400, 0x1D454},
- {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2},
- {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9},
- {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505},
- {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C},
- {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544},
- {0x1D546, 0x1D546}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5},
- {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F},
- {0x1DAA1, 0x1DAAF}, {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A},
- {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021},
- {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D},
- {0x1E08F, 0x1E08F}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D},
- {0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E290, 0x1E2AE},
- {0x1E2C0, 0x1E2F9}, {0x1E2FF, 0x1E2FF}, {0x1E4D0, 0x1E4F9},
- {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB}, {0x1E7ED, 0x1E7EE},
- {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6},
- {0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F},
- {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03},
- {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24},
- {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37},
- {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, {0x1EE42, 0x1EE42},
- {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, {0x1EE4B, 0x1EE4B},
- {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, {0x1EE54, 0x1EE54},
- {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, {0x1EE5B, 0x1EE5B},
- {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, {0x1EE61, 0x1EE62},
- {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
- {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE7E, 0x1EE7E},
- {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3},
- {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1EEF0, 0x1EEF1},
- {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, {0x1F030, 0x1F093},
- {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CE},
- {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F}, {0x1F12E, 0x1F12F},
- {0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD}, {0x1F1E6, 0x1F1FF},
- {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D},
- {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF},
- {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F},
- {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A},
- {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594},
- {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F},
- {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4},
- {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F776},
- {0x1F77B, 0x1F7D9}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
+ {0x1D377, 0x1D378}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C},
+ {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6},
+ {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB},
+ {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A},
+ {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539},
+ {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546},
+ {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB},
+ {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF},
+ {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A}, {0x1E000, 0x1E006},
+ {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
+ {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D}, {0x1E08F, 0x1E08F},
+ {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D}, {0x1E140, 0x1E149},
+ {0x1E14E, 0x1E14F}, {0x1E290, 0x1E2AE}, {0x1E2C0, 0x1E2F9},
+ {0x1E2FF, 0x1E2FF}, {0x1E4D0, 0x1E4F9}, {0x1E5D0, 0x1E5FA},
+ {0x1E5FF, 0x1E5FF}, {0x1E6C0, 0x1E6DE}, {0x1E6E0, 0x1E6F5},
+ {0x1E6FE, 0x1E6FF}, {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB},
+ {0x1E7ED, 0x1E7EE}, {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4},
+ {0x1E8C7, 0x1E8D6}, {0x1E900, 0x1E94B}, {0x1E950, 0x1E959},
+ {0x1E95E, 0x1E95F}, {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D},
+ {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22},
+ {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32},
+ {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B},
+ {0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49},
+ {0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52},
+ {0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59},
+ {0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F},
+ {0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A},
+ {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C},
+ {0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B},
+ {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB},
+ {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B},
+ {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF},
+ {0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F},
+ {0x1F12E, 0x1F12F}, {0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD},
+ {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F32C}, {0x1F336, 0x1F336},
+ {0x1F37D, 0x1F37D}, {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE},
+ {0x1F3D4, 0x1F3DF}, {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7},
+ {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE},
+ {0x1F53E, 0x1F54A}, {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579},
+ {0x1F57B, 0x1F594}, {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA},
+ {0x1F650, 0x1F67F}, {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF},
+ {0x1F6D3, 0x1F6D4}, {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3},
+ {0x1F700, 0x1F7D9}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
{0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD},
- {0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B},
- {0x1F946, 0x1F946}, {0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D},
- {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA}, {0x1FBF0, 0x1FBF9},
- {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
+ {0x1F8B0, 0x1F8BB}, {0x1F8C0, 0x1F8C1}, {0x1F8D0, 0x1F8D8},
+ {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B}, {0x1F946, 0x1F946},
+ {0x1FA00, 0x1FA57}, {0x1FA60, 0x1FA6D}, {0x1FB00, 0x1FB92},
+ {0x1FB94, 0x1FBFA}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
}
var emoji = table{
{0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122},
{0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA},
- {0x231A, 0x231B}, {0x2328, 0x2328}, {0x2388, 0x2388},
- {0x23CF, 0x23CF}, {0x23E9, 0x23F3}, {0x23F8, 0x23FA},
- {0x24C2, 0x24C2}, {0x25AA, 0x25AB}, {0x25B6, 0x25B6},
- {0x25C0, 0x25C0}, {0x25FB, 0x25FE}, {0x2600, 0x2605},
- {0x2607, 0x2612}, {0x2614, 0x2685}, {0x2690, 0x2705},
- {0x2708, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716},
- {0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728},
- {0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747},
- {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
- {0x2757, 0x2757}, {0x2763, 0x2767}, {0x2795, 0x2797},
- {0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
- {0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C},
- {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030},
- {0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299},
- {0x1F000, 0x1F0FF}, {0x1F10D, 0x1F10F}, {0x1F12F, 0x1F12F},
- {0x1F16C, 0x1F171}, {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E},
- {0x1F191, 0x1F19A}, {0x1F1AD, 0x1F1E5}, {0x1F201, 0x1F20F},
- {0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A},
- {0x1F23C, 0x1F23F}, {0x1F249, 0x1F3FA}, {0x1F400, 0x1F53D},
- {0x1F546, 0x1F64F}, {0x1F680, 0x1F6FF}, {0x1F774, 0x1F77F},
- {0x1F7D5, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F},
- {0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8FF},
- {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FAFF},
+ {0x231A, 0x231B}, {0x2328, 0x2328}, {0x23CF, 0x23CF},
+ {0x23E9, 0x23F3}, {0x23F8, 0x23FA}, {0x24C2, 0x24C2},
+ {0x25AA, 0x25AB}, {0x25B6, 0x25B6}, {0x25C0, 0x25C0},
+ {0x25FB, 0x25FE}, {0x2600, 0x2604}, {0x260E, 0x260E},
+ {0x2611, 0x2611}, {0x2614, 0x2615}, {0x2618, 0x2618},
+ {0x261D, 0x261D}, {0x2620, 0x2620}, {0x2622, 0x2623},
+ {0x2626, 0x2626}, {0x262A, 0x262A}, {0x262E, 0x262F},
+ {0x2638, 0x263A}, {0x2640, 0x2640}, {0x2642, 0x2642},
+ {0x2648, 0x2653}, {0x265F, 0x2660}, {0x2663, 0x2663},
+ {0x2665, 0x2666}, {0x2668, 0x2668}, {0x267B, 0x267B},
+ {0x267E, 0x267F}, {0x2692, 0x2697}, {0x2699, 0x2699},
+ {0x269B, 0x269C}, {0x26A0, 0x26A1}, {0x26A7, 0x26A7},
+ {0x26AA, 0x26AB}, {0x26B0, 0x26B1}, {0x26BD, 0x26BE},
+ {0x26C4, 0x26C5}, {0x26C8, 0x26C8}, {0x26CE, 0x26CF},
+ {0x26D1, 0x26D1}, {0x26D3, 0x26D4}, {0x26E9, 0x26EA},
+ {0x26F0, 0x26F5}, {0x26F7, 0x26FA}, {0x26FD, 0x26FD},
+ {0x2702, 0x2702}, {0x2705, 0x2705}, {0x2708, 0x270D},
+ {0x270F, 0x270F}, {0x2712, 0x2712}, {0x2714, 0x2714},
+ {0x2716, 0x2716}, {0x271D, 0x271D}, {0x2721, 0x2721},
+ {0x2728, 0x2728}, {0x2733, 0x2734}, {0x2744, 0x2744},
+ {0x2747, 0x2747}, {0x274C, 0x274C}, {0x274E, 0x274E},
+ {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2763, 0x2764},
+ {0x2795, 0x2797}, {0x27A1, 0x27A1}, {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF}, {0x2934, 0x2935}, {0x2B05, 0x2B07},
+ {0x2B1B, 0x2B1C}, {0x2B50, 0x2B50}, {0x2B55, 0x2B55},
+ {0x3030, 0x3030}, {0x303D, 0x303D}, {0x3297, 0x3297},
+ {0x3299, 0x3299}, {0x1F004, 0x1F004}, {0x1F02C, 0x1F02F},
+ {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0},
+ {0x1F0CF, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F170, 0x1F171},
+ {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
+ {0x1F1AE, 0x1F1E5}, {0x1F201, 0x1F20F}, {0x1F21A, 0x1F21A},
+ {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, {0x1F23C, 0x1F23F},
+ {0x1F249, 0x1F25F}, {0x1F266, 0x1F321}, {0x1F324, 0x1F393},
+ {0x1F396, 0x1F397}, {0x1F399, 0x1F39B}, {0x1F39E, 0x1F3F0},
+ {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3FA}, {0x1F400, 0x1F4FD},
+ {0x1F4FF, 0x1F53D}, {0x1F549, 0x1F54E}, {0x1F550, 0x1F567},
+ {0x1F56F, 0x1F570}, {0x1F573, 0x1F57A}, {0x1F587, 0x1F587},
+ {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, {0x1F595, 0x1F596},
+ {0x1F5A4, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2},
+ {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3},
+ {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3},
+ {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3},
+ {0x1F5FA, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CB, 0x1F6D2},
+ {0x1F6D5, 0x1F6E5}, {0x1F6E9, 0x1F6E9}, {0x1F6EB, 0x1F6F0},
+ {0x1F6F3, 0x1F6FF}, {0x1F7DA, 0x1F7FF}, {0x1F80C, 0x1F80F},
+ {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F},
+ {0x1F8AE, 0x1F8AF}, {0x1F8BC, 0x1F8BF}, {0x1F8C2, 0x1F8CF},
+ {0x1F8D9, 0x1F8FF}, {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945},
+ {0x1F947, 0x1F9FF}, {0x1FA58, 0x1FA5F}, {0x1FA6E, 0x1FAFF},
{0x1FC00, 0x1FFFD},
}
diff --git a/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_windows.go
index 5f987a310fe..951500a24d3 100644
--- a/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_windows.go
+++ b/hack/tools/vendor/github.com/mattn/go-runewidth/runewidth_windows.go
@@ -4,6 +4,7 @@
package runewidth
import (
+ "os"
"syscall"
)
@@ -14,6 +15,11 @@ var (
// IsEastAsian return true if the current locale is CJK
func IsEastAsian() bool {
+ if os.Getenv("WT_SESSION") != "" {
+ // Windows Terminal always not use East Asian Ambiguous Width(s).
+ return false
+ }
+
r1, _, _ := procGetConsoleOutputCP.Call()
if r1 == 0 {
return false
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/.gitignore b/hack/tools/vendor/github.com/mikefarah/yq/v4/.gitignore
index aef9fba229d..e310ad1dd3d 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/.gitignore
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/.gitignore
@@ -22,8 +22,10 @@ _cgo_gotypes.go
_cgo_export.*
_testmain.go
+cover.out
coverage.out
coverage.html
+coverage_sorted.txt
*.exe
*.test
*.prof
@@ -41,9 +43,13 @@ yq*.snap
test.yml
test*.yml
+test*.tf
test*.xml
test*.toml
test*.yaml
+*.kyaml
+test_dir1/
+test_dir2/
0.yml
1.yml
2.yml
@@ -64,3 +70,7 @@ debian/files
.vscode
yq3
+
+# Golang
+.gomodcache/
+.gocache/
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.bck.yml b/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.bck.yml
new file mode 100644
index 00000000000..c108f703d61
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.bck.yml
@@ -0,0 +1,38 @@
+run:
+ timeout: 5m
+linters:
+ enable:
+ - asciicheck
+ - depguard
+ - errorlint
+ - gci
+ - gochecknoinits
+ - gofmt
+ - goimports
+ - gosec
+ - gosimple
+ - staticcheck
+ - unused
+ - misspell
+ - nakedret
+ - nolintlint
+ - predeclared
+ - revive
+ - unconvert
+ - unparam
+linters-settings:
+ depguard:
+ rules:
+ prevent_unmaintained_packages:
+ list-mode: lax
+ files:
+ - $all
+ - "!$test"
+ deny:
+ - pkg: io/ioutil
+ desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil"
+issues:
+ exclude-rules:
+ - linters:
+ - revive
+ text: "var-naming"
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.yml b/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.yml
index c108f703d61..ffc9a52b0c6 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.yml
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/.golangci.yml
@@ -1,18 +1,11 @@
-run:
- timeout: 5m
+version: "2"
linters:
enable:
- asciicheck
- depguard
- errorlint
- - gci
- gochecknoinits
- - gofmt
- - goimports
- gosec
- - gosimple
- - staticcheck
- - unused
- misspell
- nakedret
- nolintlint
@@ -20,19 +13,45 @@ linters:
- revive
- unconvert
- unparam
-linters-settings:
- depguard:
+ settings:
+ misspell:
+ locale: UK
+ ignore-rules:
+ - color
+ - colors
+ depguard:
+ rules:
+ prevent_unmaintained_packages:
+ list-mode: lax
+ files:
+ - $all
+ - '!$test'
+ deny:
+ - pkg: io/ioutil
+ desc: 'replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil'
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
rules:
- prevent_unmaintained_packages:
- list-mode: lax
- files:
- - $all
- - "!$test"
- deny:
- - pkg: io/ioutil
- desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil"
-issues:
- exclude-rules:
- - linters:
- - revive
- text: "var-naming"
+ - linters:
+ - revive
+ text: var-naming
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gci
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/.goreleaser.yaml b/hack/tools/vendor/github.com/mikefarah/yq/v4/.goreleaser.yaml
index 5ce0161730e..1f758d2412e 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/.goreleaser.yaml
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/.goreleaser.yaml
@@ -23,6 +23,7 @@ builds:
- linux_amd64
- linux_arm
- linux_arm64
+ - linux_loong64
- linux_mips
- linux_mips64
- linux_mips64le
@@ -38,6 +39,7 @@ builds:
- openbsd_amd64
- windows_386
- windows_amd64
+ - windows_arm64
no_unique_dist_dir: true
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/CODE_OF_CONDUCT.md b/hack/tools/vendor/github.com/mikefarah/yq/v4/CODE_OF_CONDUCT.md
index d2a542d733d..2f3359b9557 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/CODE_OF_CONDUCT.md
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/CODE_OF_CONDUCT.md
@@ -11,7 +11,7 @@ appearance, race, religion, or sexual identity and orientation.
## Our Standards
-Examples of behavior that contributes to creating a positive environment
+Examples of behaviour that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
@@ -20,7 +20,7 @@ include:
* Focusing on what is best for the community
* Showing empathy towards other community members
-Examples of unacceptable behavior by participants include:
+Examples of unacceptable behaviour by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
@@ -34,13 +34,13 @@ Examples of unacceptable behavior by participants include:
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
+behaviour and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behaviour.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
+permanently any contributor for other behaviours that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
@@ -54,7 +54,7 @@ further defined and clarified by project maintainers.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
+Instances of abusive, harassing, or otherwise unacceptable behaviour may be
reported by contacting the project team at mikefarah@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/CONTRIBUTING.md b/hack/tools/vendor/github.com/mikefarah/yq/v4/CONTRIBUTING.md
index 94cd04c8479..9d058a56f1f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/CONTRIBUTING.md
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/CONTRIBUTING.md
@@ -1,42 +1,229 @@
-.# Development
+# Before you begin
+Not all new PRs will be merged in
-1. Install (Golang)[https://golang.org/]
-1. Run `scripts/devtools.sh` to install the required devtools
-2. Run `make [local] vendor` to install the vendor dependencies
-2. Run `make [local] test` to ensure you can run the existing tests
-3. Write unit tests - (see existing examples). Changes will not be accepted without corresponding unit tests.
-4. Make the code changes.
-5. `make [local] test` to lint code and run tests
-6. Profit! ok no profit, but raise a PR and get kudos :)
+It's recommended to check with the owner first (e.g. raise an issue) to discuss a new feature before developing, to ensure your hard efforts don't go to waste.
+PRs to fix bugs and issues are almost always welcome :pray: please ensure you write tests as well.
+
+The following types of PRs will _not_ be accepted:
+- **Significant refactors** take a lot of time to understand and can have all sorts of unintended side effects. If you think there's a better way to do things (that requires significant changes) raise an issue for discussion first :)
+- **Release pipeline PRs** are a security risk - it's too easy for a serious vulnerability to sneak in (either intended or not). If there is a new cool way of releasing things, raise an issue for discussion first - it will need to be gone over with a fine tooth comb.
+- **Version bumps** are handled by dependabot, the bot will auto-raise PRs and they will be regularly merged in.
+- **New release platforms** At this stage, yq is not going to maintain any other release platforms other than GitHub and Docker - that said, I'm more than happy to put in other community maintained methods in the README for visibility :heart:
+
+
+# Development
+
+## Initial Setup
+
+1. Install [Golang](https://golang.org/) (version 1.24.0 or later)
+2. Run `scripts/devtools.sh` to install required development tools:
+ - golangci-lint for code linting
+ - gosec for security analysis
+3. Run `make [local] vendor` to install vendor dependencies
+4. Run `make [local] test` to ensure you can run the existing tests
+
+## Development Workflow
+
+1. **Write unit tests first** - Changes will not be accepted without corresponding unit tests (see Testing section below)
+2. **Make your code changes**
+3. **Run tests and linting**: `make [local] test` (this runs formatting, linting, security checks, and tests)
+4. **Create your PR** and get kudos! :)
+
+## Make Commands
+
+- Use `make [local] ` for local development (runs in Docker container)
+- Use `make ` for CI/CD environments
+- Common commands:
+ - `make [local] vendor` - Install dependencies
+ - `make [local] test` - Run all checks and tests
+ - `make [local] build` - Build the yq binary
+ - `make [local] format` - Format code
+ - `make [local] check` - Run linting and security checks
+
+# Code Quality
+
+## Linting and Formatting
+
+The project uses strict linting rules defined in `.golangci.yml`. All code must pass:
+
+- **Code formatting**: gofmt, goimports, gci
+- **Linting**: revive, errorlint, gosec, misspell, and others
+- **Security checks**: gosec security analysis
+- **Spelling checks**: misspell detection
+
+Run `make [local] check` to verify your code meets all quality standards.
+
+## Code Style Guidelines
+
+- Follow standard Go conventions
+- Use meaningful variable names
+- Add comments for public functions and complex logic
+- Keep functions focused and reasonably sized
+- Use the project's existing patterns and conventions
+
+# Testing
+
+## Test Structure
+
+Tests in yq use the `expressionScenario` pattern. Each test scenario includes:
+- `expression`: The yq expression to test
+- `document`: Input YAML/JSON (optional)
+- `expected`: Expected output
+- `skipDoc`: Whether to skip documentation generation
+
+## Writing Tests
+
+1. **Find the appropriate test file** (e.g., `operator_add_test.go` for addition operations)
+2. **Add your test scenario** to the `*OperatorScenarios` slice
+3. **Run the specific test**: `go test -run TestAddOperatorScenarios` (replace with appropriate test name)
+4. **Verify documentation generation** (see Documentation section)
+
+## Test Examples
+
+```go
+var addOperatorScenarios = []expressionScenario{
+ {
+ skipDoc: true,
+ expression: `"foo" + "bar"`,
+ expected: []string{
+ "D0, P[], (!!str)::foobar\n",
+ },
+ },
+ {
+ document: "apples: 3",
+ expression: `.apples + 3`,
+ expected: []string{
+ "D0, P[apples], (!!int)::6\n",
+ },
+ },
+}
+```
+
+## Running Tests
+
+- **All tests**: `make [local] test`
+- **Specific test**: `go test -run TestName`
+- **With coverage**: `make [local] cover`
# Documentation
-The documentation is a bit of a mixed bag (sorry in advance, I do plan on simplifying it...) - with some parts automatically generated and stiched together and some statically defined.
+## Documentation Generation
+
+The project uses a documentation system that combines static headers with dynamically generated content from tests.
+
+### How It Works
+
+1. **Static headers** are defined in `pkg/yqlib/doc/operators/headers/*.md`
+2. **Dynamic content** is generated from test scenarios in `*_test.go` files
+3. **Generated docs** are created in `pkg/yqlib/doc/*.md` by concatenating headers with test-generated content
+4. **Documentation is synced** to the gitbook branch for the website
+
+### Updating Operator Documentation
+
+#### For Test-Generated Documentation
+
+Most operator documentation is generated from tests. To update:
+
+1. **Find the test file** (e.g., `operator_add_test.go`)
+2. **Update test scenarios** - each `expressionScenario` with `skipDoc: false` becomes documentation
+3. **Run the test** to regenerate docs:
+ ```bash
+ cd pkg/yqlib
+ go test -run TestAddOperatorScenarios
+ ```
+4. **Verify the generated documentation** in `pkg/yqlib/doc/add.md`
+5. **Create a PR** with your changes
+
+#### For Header-Only Documentation
+
+If documentation exists only in `headers/*.md` files:
+1. **Update the header file directly** (e.g., `pkg/yqlib/doc/operators/headers/add.md`)
+2. **Create a PR** with your changes
+
+### Updating Static Documentation
+
+For documentation not in the master branch:
+
+1. **Check the gitbook branch** for additional pages
+2. **Update the `*.md` files** directly
+3. **Create a PR** to the gitbook branch
+
+### Documentation Best Practices
+
+- **Write clear, concise examples** in test scenarios
+- **Use meaningful variable names** in examples
+- **Include edge cases** and error conditions
+- **Test your documentation changes** by running the specific test
+- **Verify generated output** matches expectations
+
+Note: PRs with small changes (e.g. minor typos) may not be merged (see https://joel.net/how-one-guy-ruined-hacktoberfest2020-drama).
+
+# Troubleshooting
+
+## Common Setup Issues
-Documentation is written in markdown, and is published in the 'gitbook' branch.
+### Docker/Podman Issues
+- **Problem**: `make` commands fail with Docker errors
+- **Solution**: Ensure Docker or Podman is running and accessible
+- **Alternative**: Use `make local ` to run in containers
-The various operator documentation (e.g. 'strings') are generated from the 'master' branch, and have a statically defined header (e.g. `pkg/yqlib/doc/operators/headers/add.md`) and the bulk of the docs are generated from the unit tests e.g. `pkg/yqlib/operator_add_test.go`.
+### Go Version Issues
+- **Problem**: Build fails with Go version errors
+- **Solution**: Ensure you have Go 1.24.0 or later installed
+- **Check**: Run `go version` to verify
-The pipeline will run the tests and automatically concatenate the files together, and put them under
-`pkg/qylib/doc/add.md`. These files are checked in the master branch (and are copied to the gitbook branch as part of the release process).
+### Vendor Dependencies
+- **Problem**: `make vendor` fails or dependencies are outdated
+- **Solution**:
+ ```bash
+ go mod tidy
+ make [local] vendor
+ ```
-## How to contribute
+### Linting Failures
+- **Problem**: `make check` fails with linting errors
+- **Solution**:
+ ```bash
+ make [local] format # Auto-fix formatting
+ # Manually fix remaining linting issues
+ make [local] check # Verify fixes
+ ```
-The first step is to find if what you want is automatically generated or not - start by looking in the master branch.
+### Test Failures
+- **Problem**: Tests fail locally but pass in CI
+- **Solution**:
+ ```bash
+ make [local] test # Run in Docker container
+ ```
-Note that PRs with small changes (e.g. minor typos) may not be merged (see https://joel.net/how-one-guy-ruined-hacktoberfest2020-drama).
+- **Problem**: Tests fail with a VCS error:
+ ```bash
+ error obtaining VCS status: exit status 128
+ Use -buildvcs=false to disable VCS stamping.
+ ```
+- **Solution**:
+ Git security mechanisms prevent Golang from detecting the Git details inside
+ the container; either build with the `local` option, or pass GOFLAGS to
+ disable Golang buildvcs behaviour.
+ ```bash
+ make local test
+ # OR
+ make test GOFLAGS='-buildvcs=true'
+ ```
-### Updating dynamic documentation from master
-- Search for the documentation you want to update. If you find matches in a `*_test.go` file - update that, as that will automatically update the matching `*.md` file
-- Assuming you are updating a `*_test.go` file, once updated, run the test to regenerated the docs. E.g. for the 'Add' test generated docs, from the pkg/yqlib folder run:
-`go test -run TestAddOperatorScenarios` which will run that test defined in the `operator_add_test.go` file.
-- Ensure the tests still pass, and check the generated documentation have your update.
-- Note: If the documentation is only in a `headers/*.md` file, then just update that directly
-- Raise a PR to merge the changes into master!
+### Documentation Generation Issues
+- **Problem**: Generated docs don't update after test changes
+- **Solution**:
+ ```bash
+ cd pkg/yqlib
+ go test -run TestSpecificOperatorScenarios
+ # Check if generated file updated in pkg/yqlib/doc/
+ ```
-### Updating static documentation from the gitbook branch
-If you haven't found what you want to update in the master branch, then check the gitbook branch directly as there are a few pages in there that are not in master.
+## Getting Help
-- Update the `*.md` files
-- Raise a PR to merge the changes into gitbook.
\ No newline at end of file
+- **Check existing issues**: Search GitHub issues for similar problems
+- **Create an issue**: If you can't find a solution, create a detailed issue
+- **Ask questions**: Use GitHub Discussions for general questions
+- **Join the community**: Check the project's community channels
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile b/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile
index 4204252fecb..003948a4b89 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.23.3 as builder
+FROM golang:1.26.2@sha256:2a2b4b5791cea8ae09caecba7bad0bd9631def96e5fe362e4a5e67009fe4ae61 AS builder
WORKDIR /go/src/mikefarah/yq
@@ -10,7 +10,7 @@ RUN ./scripts/acceptance.sh
# Choose alpine as a base image to make this useful for CI, as many
# CI tools expect an interactive shell inside the container
-FROM alpine:3 as production
+FROM alpine:3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 AS production
LABEL maintainer="Mike Farah "
COPY --from=builder /go/src/mikefarah/yq/yq /usr/bin/yq
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile.dev b/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile.dev
index 5dc23d941b3..d12597e3d9a 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile.dev
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/Dockerfile.dev
@@ -1,4 +1,4 @@
-FROM golang:1.23.3
+FROM golang:1.26.2@sha256:2a2b4b5791cea8ae09caecba7bad0bd9631def96e5fe362e4a5e67009fe4ae61
RUN apt-get update && \
apt-get install -y npm && \
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile b/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile
index e50cdd4870d..41083d4adb3 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile
@@ -35,6 +35,7 @@ clean:
## prefix before other make targets to run in your local dev environment
local: | quiet
@$(eval ENGINERUN= )
+ @$(eval GOFLAGS="$(GOFLAGS)" )
@mkdir -p tmp
@touch tmp/dev_image_id
quiet: # this is silly but shuts up 'Nothing to be done for `local`'
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile.variables b/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile.variables
index 110cea72606..2f73a66b0bc 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile.variables
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/Makefile.variables
@@ -4,6 +4,7 @@ IMPORT_PATH := github.com/mikefarah/${PROJECT}
export GIT_COMMIT = $(shell git rev-parse --short HEAD)
export GIT_DIRTY = $(shell test -n "$$(git status --porcelain)" && echo "+CHANGES" || true)
export GIT_DESCRIBE = $(shell git describe --tags --always)
+GOFLAGS :=
LDFLAGS :=
LDFLAGS += -X main.GitCommit=${GIT_COMMIT}${GIT_DIRTY}
LDFLAGS += -X main.GitDescribe=${GIT_DESCRIBE}
@@ -26,13 +27,15 @@ ifeq ($(CYG_CHECK),1)
else
# all non-windows environments
ROOT := $(shell pwd)
- SELINUX := $(shell which getenforce 2>&1 >/dev/null && echo :z)
+ # Deliberately use `command -v` instead of `which` to be POSIX compliant
+ SELINUX := $(shell command -v getenforce >/dev/null 2>&1 && echo :z)
endif
DEV_IMAGE := ${PROJECT}_dev
ENGINERUN := ${ENGINE} run --rm \
-e LDFLAGS="${LDFLAGS}" \
+ -e GOFLAGS="${GOFLAGS}" \
-e GITHUB_TOKEN="${GITHUB_TOKEN}" \
-v ${ROOT}/vendor:/go/src${SELINUX} \
-v ${ROOT}:/${PROJECT}/src/${IMPORT_PATH}${SELINUX} \
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/README.md b/hack/tools/vendor/github.com/mikefarah/yq/v4/README.md
index 582ab1556a1..25e4895f66f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/README.md
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/README.md
@@ -3,44 +3,46 @@
    
-a lightweight and portable command-line YAML, JSON and XML processor. `yq` uses [jq](https://github.com/stedolan/jq) like syntax but works with yaml files as well as json, xml, properties, csv and tsv. It doesn't yet support everything `jq` does - but it does support the most common operations and functions, and more is being added continuously.
+A lightweight and portable command-line YAML, JSON, INI and XML processor. `yq` uses [jq](https://github.com/stedolan/jq) (a popular JSON processor) like syntax but works with yaml files as well as json, kyaml, xml, ini, properties, csv and tsv. It doesn't yet support everything `jq` does - but it does support the most common operations and functions, and more is being added continuously.
-yq is written in go - so you can download a dependency free binary for your platform and you are good to go! If you prefer there are a variety of package managers that can be used as well as Docker and Podman, all listed below.
+yq is written in Go - so you can download a dependency free binary for your platform and you are good to go! If you prefer there are a variety of package managers that can be used as well as Docker and Podman, all listed below.
## Quick Usage Guide
-Read a value:
+### Basic Operations
+
+**Read a value:**
```bash
yq '.a.b[0].c' file.yaml
```
-Pipe from STDIN:
+**Pipe from STDIN:**
```bash
yq '.a.b[0].c' < file.yaml
```
-Update a yaml file, in place
+**Update a yaml file in place:**
```bash
yq -i '.a.b[0].c = "cool"' file.yaml
```
-Update using environment variables
+**Update using environment variables:**
```bash
NAME=mike yq -i '.a.b[0].c = strenv(NAME)' file.yaml
```
-Merge multiple files
+### Advanced Operations
+
+**Merge multiple files:**
```bash
# merge two files
yq -n 'load("file1.yaml") * load("file2.yaml")'
-# merge using globs:
-# note the use of `ea` to evaluate all the files at once
-# instead of in sequence
+# merge using globs (note: `ea` evaluates all files at once instead of in sequence)
yq ea '. as $item ireduce ({}; . * $item )' path/to/*.yml
```
-Multiple updates to a yaml file
+**Multiple updates to a yaml file:**
```bash
yq -i '
.a.b[0].c = "cool" |
@@ -49,14 +51,22 @@ yq -i '
' file.yaml
```
-Find and update an item in an array:
+**Find and update an item in an array:**
```bash
-yq '(.[] | select(.name == "foo") | .address) = "12 cat st"'
+# Note: requires input file - add your file at the end
+yq -i '(.[] | select(.name == "foo") | .address) = "12 cat st"' data.yaml
```
-Convert JSON to YAML
+**Convert between formats:**
```bash
+# Convert JSON to YAML (pretty print)
yq -Poy sample.json
+
+# Convert YAML to JSON
+yq -o json file.yaml
+
+# Convert XML to YAML
+yq -o yaml file.xml
```
See [recipes](https://mikefarah.gitbook.io/yq/recipes) for more examples and the [documentation](https://mikefarah.gitbook.io/yq/) for more information.
@@ -68,31 +78,31 @@ Take a look at the discussions for [common questions](https://github.com/mikefar
### [Download the latest binary](https://github.com/mikefarah/yq/releases/latest)
### wget
-Use wget to download, gzipped pre-compiled binaries:
+Use wget to download pre-compiled binaries. Choose your platform and architecture:
-
-For instance, VERSION=v4.2.0 and BINARY=yq_linux_amd64
-
-#### Compressed via tar.gz
+**For Linux (example):**
```bash
-wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY}.tar.gz -O - |\
- tar xz && mv ${BINARY} /usr/bin/yq
-```
+# Set your platform variables (adjust as needed)
+VERSION=v4.2.0
+PLATFORM=linux_amd64
-#### Plain binary
+# Download compressed binary
+wget https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_${PLATFORM}.tar.gz -O - |\
+ tar xz && sudo mv yq_${PLATFORM} /usr/local/bin/yq
-```bash
-wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY} -O /usr/bin/yq &&\
- chmod +x /usr/bin/yq
+# Or download plain binary
+wget https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_${PLATFORM} -O /usr/local/bin/yq &&\
+ chmod +x /usr/local/bin/yq
```
-#### Latest version
-
+**Latest version (Linux AMD64):**
```bash
-wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq &&\
- chmod +x /usr/bin/yq
+wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq &&\
+ chmod +x /usr/local/bin/yq
```
+**Available platforms:** `linux_amd64`, `linux_arm64`, `linux_arm`, `linux_386`, `darwin_amd64`, `darwin_arm64`, `windows_amd64`, `windows_386`, etc.
+
### MacOS / Linux via Homebrew:
Using [Homebrew](https://brew.sh/)
```
@@ -123,28 +133,31 @@ rm /etc/myfile.tmp
```
### Run with Docker or Podman
-#### Oneshot use:
+#### One-time use:
```bash
-docker run --rm -v "${PWD}":/workdir mikefarah/yq [command] [flags] [expression ]FILE...
-```
+# Docker - process files in current directory
+docker run --rm -v "${PWD}":/workdir mikefarah/yq '.a.b[0].c' file.yaml
-Note that you can run `yq` in docker without network access and other privileges if you desire,
-namely `--security-opt=no-new-privileges --cap-drop all --network none`.
+# Podman - same usage as Docker
+podman run --rm -v "${PWD}":/workdir mikefarah/yq '.a.b[0].c' file.yaml
+```
+**Security note:** You can run `yq` in Docker with restricted privileges:
```bash
-podman run --rm -v "${PWD}":/workdir mikefarah/yq [command] [flags] [expression ]FILE...
+docker run --rm --security-opt=no-new-privileges --cap-drop all --network none \
+ -v "${PWD}":/workdir mikefarah/yq '.a.b[0].c' file.yaml
```
-#### Pipe in via STDIN:
+#### Pipe data via STDIN:
-You'll need to pass the `-i\--interactive` flag to docker:
+You'll need to pass the `-i --interactive` flag to Docker/Podman:
```bash
+# Process piped data
docker run -i --rm mikefarah/yq '.this.thing' < myfile.yml
-```
-```bash
+# Same with Podman
podman run -i --rm mikefarah/yq '.this.thing' < myfile.yml
```
@@ -294,7 +307,7 @@ Using [winget](https://learn.microsoft.com/en-us/windows/package-manager/)
winget install --id MikeFarah.yq
```
-### Mac:
+### MacPorts:
Using [MacPorts](https://www.macports.org/)
```
sudo port selfupdate
@@ -324,15 +337,23 @@ Flox can be used to install yq on Linux, MacOS, and Windows through WSL.
flox install yq
```
+
+### MacOS / Linux via gah:
+Using [gah](https://github.com/marverix/gah)
+
+```
+gah install yq
+```
+
## Features
- [Detailed documentation with many examples](https://mikefarah.gitbook.io/yq/)
- Written in portable go, so you can download a lovely dependency free binary
-- Uses similar syntax as `jq` but works with YAML, [JSON](https://mikefarah.gitbook.io/yq/usage/convert) and [XML](https://mikefarah.gitbook.io/yq/usage/xml) files
+- Uses similar syntax as `jq` but works with YAML, INI, [JSON](https://mikefarah.gitbook.io/yq/usage/convert) and [XML](https://mikefarah.gitbook.io/yq/usage/xml) files
- Fully supports multi document yaml files
- Supports yaml [front matter](https://mikefarah.gitbook.io/yq/usage/front-matter) blocks (e.g. jekyll/assemble)
- Colorized yaml output
- [Date/Time manipulation and formatting with TZ](https://mikefarah.gitbook.io/yq/operators/datetime)
-- [Deeply data structures](https://mikefarah.gitbook.io/yq/operators/traverse-read)
+- [Deep data structures](https://mikefarah.gitbook.io/yq/operators/traverse-read)
- [Sort keys](https://mikefarah.gitbook.io/yq/operators/sort-keys)
- Manipulate yaml [comments](https://mikefarah.gitbook.io/yq/operators/comment-operators), [styling](https://mikefarah.gitbook.io/yq/operators/style), [tags](https://mikefarah.gitbook.io/yq/operators/tag) and [anchors and aliases](https://mikefarah.gitbook.io/yq/operators/anchor-and-alias-operators).
- [Update in place](https://mikefarah.gitbook.io/yq/v/v4.x/commands/evaluate#flags)
@@ -342,6 +363,8 @@ flox install yq
- [Load content from other files](https://mikefarah.gitbook.io/yq/operators/load)
- [Convert to/from json/ndjson](https://mikefarah.gitbook.io/yq/v/v4.x/usage/convert)
- [Convert to/from xml](https://mikefarah.gitbook.io/yq/v/v4.x/usage/xml)
+- [Convert to/from hcl (terraform)](https://mikefarah.gitbook.io/yq/v/v4.x/usage/hcl)
+- [Convert to/from toml](https://mikefarah.gitbook.io/yq/v/v4.x/usage/toml)
- [Convert to/from properties](https://mikefarah.gitbook.io/yq/v/v4.x/usage/properties)
- [Convert to/from csv/tsv](https://mikefarah.gitbook.io/yq/usage/csv-tsv)
- [General shell completion scripts (bash/zsh/fish/powershell)](https://mikefarah.gitbook.io/yq/v/v4.x/commands/shell-completion)
@@ -359,41 +382,96 @@ Usage:
Examples:
-# yq defaults to 'eval' command if no command is specified. See "yq eval --help" for more examples.
-yq '.stuff' < myfile.yml # outputs the data at the "stuff" node from "myfile.yml"
+# yq tries to auto-detect the file format based off the extension, and defaults to YAML if it's unknown (or piping through STDIN)
+# Use the '-p/--input-format' flag to specify a format type.
+cat file.xml | yq -p xml
-yq -i '.stuff = "foo"' myfile.yml # update myfile.yml in place
+# read the "stuff" node from "myfile.yml"
+yq '.stuff' < myfile.yml
+
+# update myfile.yml in place
+yq -i '.stuff = "foo"' myfile.yml
+
+# print contents of sample.json as idiomatic YAML
+yq -P -oy sample.json
Available Commands:
- completion Generate the autocompletion script for the specified shell
- eval (default) Apply the expression to each document in each yaml file in sequence
- eval-all Loads _all_ yaml documents of _all_ yaml files and runs expression once
- help Help about any command
+ completion Generate the autocompletion script for the specified shell
+ eval (default) Apply the expression to each document in each yaml file in sequence
+ eval-all Loads _all_ yaml documents of _all_ yaml files and runs expression once
+ help Help about any command
Flags:
- -C, --colors force print with colors
- -e, --exit-status set exit status if there are no matches or null or false is returned
- -f, --front-matter string (extract|process) first input as yaml front-matter. Extract will pull out the yaml content, process will run the expression against the yaml content, leaving the remaining data intact
- --header-preprocess Slurp any header comments and separators before processing expression. (default true)
- -h, --help help for yq
- -I, --indent int sets indent level for output (default 2)
- -i, --inplace update the file in place of first file given.
- -p, --input-format string [yaml|y|xml|x] parse format for input. Note that json is a subset of yaml. (default "yaml")
- -M, --no-colors force print with no colors
- -N, --no-doc Don't print document separators (---)
- -n, --null-input Don't read input, simply evaluate the expression given. Useful for creating docs from scratch.
- -o, --output-format string [yaml|y|json|j|props|p|xml|x] output format type. (default "yaml")
- -P, --prettyPrint pretty print, shorthand for '... style = ""'
- -s, --split-exp string print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter.
- --unwrapScalar unwrap scalar, print the value with no quotes, colors or comments (default true)
- -v, --verbose verbose mode
- -V, --version Print version information and quit
- --xml-attribute-prefix string prefix for xml attributes (default "+")
- --xml-content-name string name for xml content (if no attribute name is present). (default "+content")
+ -C, --colors force print with colors
+ --csv-auto-parse parse CSV YAML/JSON values (default true)
+ --csv-separator char CSV Separator character (default ,)
+ --debug-node-info debug node info
+ -e, --exit-status set exit status if there are no matches or null or false is returned
+ --expression string forcibly set the expression argument. Useful when yq argument detection thinks your expression is a file.
+ --from-file string Load expression from specified file.
+ -f, --front-matter string (extract|process) first input as yaml front-matter. Extract will pull out the yaml content, process will run the expression against the yaml content, leaving the remaining data intact
+ --header-preprocess Slurp any header comments and separators before processing expression. (default true)
+ -h, --help help for yq
+ -I, --indent int sets indent level for output (default 2)
+ -i, --inplace update the file in place of first file given.
+ -p, --input-format string [auto|a|yaml|y|json|j|kyaml|ky|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|hcl|h|lua|l|ini|i] parse format for input. (default "auto")
+ --lua-globals output keys as top-level global variables
+ --lua-prefix string prefix (default "return ")
+ --lua-suffix string suffix (default ";\n")
+ --lua-unquoted output unquoted string keys (e.g. {foo="bar"})
+ -M, --no-colors force print with no colors
+ -N, --no-doc Don't print document separators (---)
+ -0, --nul-output Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char.
+ -n, --null-input Don't read input, simply evaluate the expression given. Useful for creating docs from scratch.
+ -o, --output-format string [auto|a|yaml|y|json|j|kyaml|ky|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|hcl|h|shell|s|lua|l|ini|i] output format type. (default "auto")
+ -P, --prettyPrint pretty print, shorthand for '... style = ""'
+ --properties-array-brackets use [x] in array paths (e.g. for SpringBoot)
+ --properties-separator string separator to use between keys and values (default " = ")
+ --security-disable-env-ops Disable env related operations.
+ --security-disable-file-ops Disable file related operations (e.g. load)
+ --shell-key-separator string separator for shell variable key paths (default "_")
+ -s, --split-exp string print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter. The necessary directories will be created.
+ --split-exp-file string Use a file to specify the split-exp expression.
+ --string-interpolation Toggles strings interpolation of \(exp) (default true)
+ --tsv-auto-parse parse TSV YAML/JSON values (default true)
+ -r, --unwrapScalar unwrap scalar, print the value with no quotes, colors or comments. Defaults to true for yaml (default true)
+ -v, --verbose verbose mode
+ -V, --version Print version information and quit
+ --xml-attribute-prefix string prefix for xml attributes (default "+@")
+ --xml-content-name string name for xml content (if no attribute name is present). (default "+content")
+ --xml-directive-name string name for xml directives (e.g. ) (default "+directive")
+ --xml-keep-namespace enables keeping namespace after parsing attributes (default true)
+ --xml-proc-inst-prefix string prefix for xml processing instructions (e.g. ) (default "+p_")
+ --xml-raw-token enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details. (default true)
+ --xml-skip-directives skip over directives (e.g. )
+ --xml-skip-proc-inst skip over process instructions (e.g. )
+ --xml-strict-mode enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details.
+ --yaml-fix-merge-anchor-to-spec Fix merge anchor to match YAML spec. Will default to true in late 2025
Use "yq [command] --help" for more information about a command.
```
+
+## Troubleshooting
+
+### Common Issues
+
+**PowerShell quoting issues:**
+```powershell
+# Use single quotes for expressions
+yq '.a.b[0].c' file.yaml
+
+# Or escape double quotes
+yq ".a.b[0].c = \"value\"" file.yaml
+```
+
+### Getting Help
+
+- **Check existing issues**: [GitHub Issues](https://github.com/mikefarah/yq/issues)
+- **Ask questions**: [GitHub Discussions](https://github.com/mikefarah/yq/discussions)
+- **Documentation**: [Complete documentation](https://mikefarah.gitbook.io/yq/)
+- **Examples**: [Recipes and examples](https://mikefarah.gitbook.io/yq/recipes)
+
## Known Issues / Missing Features
- `yq` attempts to preserve comment positions and whitespace as much as possible, but it does not handle all scenarios (see https://github.com/go-yaml/yaml/tree/v3 for details)
- Powershell has its own...[opinions on quoting yq](https://mikefarah.gitbook.io/yq/usage/tips-and-tricks#quotes-in-windows-powershell)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/SECURITY.md b/hack/tools/vendor/github.com/mikefarah/yq/v4/SECURITY.md
new file mode 100644
index 00000000000..57f1de82469
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/SECURITY.md
@@ -0,0 +1,26 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+Please **do not** report security vulnerabilities through public GitHub issues.
+
+Instead, use GitHub's private vulnerability reporting feature:
+👉 https://github.com/mikefarah/yq/security
+
+This allows vulnerabilities to be triaged and addressed confidentially before any public disclosure.
+
+## Scope
+
+### HTTP / TLS / Network vulnerabilities
+
+yq is a command-line YAML/JSON/TOML processor that reads from files or standard input and writes to standard output. **yq does not include any HTTP or network libraries** and makes no network connections at runtime. CVEs related to HTTP, TLS, or networking are therefore **not applicable** to yq.
+
+### Dependency version bumps
+
+yq uses [Dependabot](https://docs.github.com/en/code-security/dependabot) to automatically raise pull requests for:
+
+- Go module dependencies
+- Go toolchain version
+- Docker base images
+
+Please **do not** raise pull requests or issues solely to bump dependency or Go versions — Dependabot handles this automatically and the maintainers merge those PRs regularly.
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/agents.md b/hack/tools/vendor/github.com/mikefarah/yq/v4/agents.md
new file mode 100644
index 00000000000..dd9534a7043
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/agents.md
@@ -0,0 +1,422 @@
+# General rules
+✅ **DO:**
+- You can use ./yq with the `--debug-node-info` flag to get a deeper understanding of the ast.
+- run ./scripts/format.sh to format the code; then ./scripts/check.sh lint and finally ./scripts/spelling.sh to check spelling.
+- Add comprehensive tests to cover the changes
+- Run test suite to ensure there is no regression
+- Use UK english spelling
+
+❌ **DON'T:**
+- Git add or commit
+- Add comments to functions that are self-explanatory
+
+
+
+# Adding a New Encoder/Decoder
+
+This guide explains how to add support for a new format (encoder/decoder) to yq without modifying `candidate_node.go`.
+
+## Overview
+
+The encoder/decoder architecture in yq is based on two main interfaces:
+
+- **Encoder**: Converts a `CandidateNode` to output in a specific format
+- **Decoder**: Reads input in a specific format and creates a `CandidateNode`
+
+Each format is registered in `pkg/yqlib/format.go` and made available through factory functions.
+
+## Architecture
+
+### Key Files
+
+- `pkg/yqlib/encoder.go` - Defines the `Encoder` interface
+- `pkg/yqlib/decoder.go` - Defines the `Decoder` interface
+- `pkg/yqlib/format.go` - Format registry and factory functions
+- `pkg/yqlib/operator_encoder_decoder.go` - Encode/decode operators
+- `pkg/yqlib/encoder_*.go` - Encoder implementations
+- `pkg/yqlib/decoder_*.go` - Decoder implementations
+
+### Interfaces
+
+**Encoder Interface:**
+```go
+type Encoder interface {
+ Encode(writer io.Writer, node *CandidateNode) error
+ PrintDocumentSeparator(writer io.Writer) error
+ PrintLeadingContent(writer io.Writer, content string) error
+ CanHandleAliases() bool
+}
+```
+
+**Decoder Interface:**
+```go
+type Decoder interface {
+ Init(reader io.Reader) error
+ Decode() (*CandidateNode, error)
+}
+```
+
+## Step-by-Step: Adding a New Encoder/Decoder
+
+### Step 1: Create the Encoder File
+
+Create `pkg/yqlib/encoder_.go` implementing the `Encoder` interface:
+- `Encode()` - Convert a `CandidateNode` to your format and write to the output writer
+- `PrintDocumentSeparator()` - Handle document separators if your format requires them
+- `PrintLeadingContent()` - Handle leading content/comments if supported
+- `CanHandleAliases()` - Return whether your format supports YAML aliases
+
+See `encoder_json.go` or `encoder_base64.go` for examples.
+
+### Step 2: Create the Decoder File
+
+Create `pkg/yqlib/decoder_.go` implementing the `Decoder` interface:
+- `Init()` - Initialize the decoder with the input reader and set up any needed state
+- `Decode()` - Decode one document from the input and return a `CandidateNode`, or `io.EOF` when finished
+
+See `decoder_json.go` or `decoder_base64.go` for examples.
+
+### Step 3: Create Tests (Mandatory)
+
+Create a test file `pkg/yqlib/_test.go` using the `formatScenario` pattern:
+- Define test scenarios as `formatScenario` structs with fields: `description`, `input`, `expected`, `scenarioType`
+- `scenarioType` can be `"decode"` (test decoding to YAML) or `"roundtrip"` (encode/decode preservation)
+- Create a helper function `testScenario()` that switches on `scenarioType`
+- Create main test function `TestFormatScenarios()` that iterates over scenarios
+- The main test function should use `documentScenarios` to ensure testcase documentation is generated.
+
+Test coverage must include:
+- Basic data types (scalars, arrays, objects/maps)
+- Nested structures
+- Edge cases (empty inputs, special characters, escape sequences)
+- Format-specific features or syntax
+- Round-trip tests: decode → encode → decode should preserve data
+
+See `hcl_test.go` for a complete example.
+
+### Step 4: Register the Format in format.go
+
+Edit `pkg/yqlib/format.go`:
+
+1. Add a new format variable:
+ - `""` is the formal name (e.g., "json", "yaml")
+ - `[]string{...}` contains short aliases (can be empty)
+ - The first function creates an encoder (can be nil for encode-only formats)
+ - The second function creates a decoder (can be nil for decode-only formats)
+
+2. Add the format to the `Formats` slice in the same file
+
+See existing formats in `format.go` for the exact structure.
+
+### Step 5: Handle Encoder Configuration (if needed)
+
+If your format has preferences/configuration options:
+
+1. Create a preferences struct with your configuration fields
+2. Update the encoder to accept preferences in its factory function
+3. Update `format.go` to pass the configured preferences
+4. Update `operator_encoder_decoder.go` if special indent handling is needed (see existing formats like JSON and YAML for the pattern)
+
+This pattern is optional and only needed if your format has user-configurable options.
+
+## Build Tags
+
+Use build tags to allow optional compilation of formats:
+- Add `//go:build !yq_no` at the top of your encoder and decoder files
+- Create a no-build version in `pkg/yqlib/no_.go` that returns nil for encoder/decoder factories
+
+This allows users to compile yq without certain formats using: `go build -tags yq_no`
+
+## Working with CandidateNode
+
+The `CandidateNode` struct represents a YAML node with:
+- `Kind`: The node type (ScalarNode, SequenceNode, MappingNode)
+- `Tag`: The YAML tag (e.g., "!!str", "!!int", "!!map")
+- `Value`: The scalar value (for ScalarNode only)
+- `Content`: Child nodes (for SequenceNode and MappingNode)
+
+Key methods:
+- `node.guessTagFromCustomType()` - Infer the tag from Go type
+- `node.AsList()` - Convert to a list for processing
+- `node.CreateReplacement()` - Create a new replacement node
+- `NewCandidate()` - Create a new CandidateNode
+
+## Key Points
+
+✅ **DO:**
+- Implement only the `Encoder` and `Decoder` interfaces
+- Register your format in `format.go` only
+- Keep format-specific logic in your encoder/decoder files
+- Use the candidate_node style attribute to store style information for round-trip. Ask if this needs to be updated with new styles.
+- Use build tags for optional compilation
+- Add comprehensive tests
+- Run the specific encoder/decoder test (e.g. _test.go) whenever you make ay changes to the encoder_ or decoder_
+- Handle errors gracefully
+- Add the no build directive, like the xml encoder and decoder, that enables a minimal yq builds. e.g. `//go:build !yq_`. Be sure to also update the build_small-yq.sh and build-tinygo-yq.sh to not include the new format.
+
+❌ **DON'T:**
+- Modify `candidate_node.go` to add format-specific logic
+- Add format-specific fields to `CandidateNode`
+- Create special cases in core navigation or evaluation logic
+- Bypass the encoder/decoder interfaces
+- Use candidate_node tag attribute for anything other than indicate the data type
+
+## Examples
+
+Refer to existing format implementations for patterns:
+
+- **Simple encoder/decoder**: `encoder_json.go`, `decoder_json.go`
+- **Complex with preferences**: `encoder_yaml.go`, `decoder_yaml.go`
+- **Encoder-only**: `encoder_sh.go` (ShFormat has nil decoder)
+- **String-only operations**: `encoder_base64.go`, `decoder_base64.go`
+
+## Testing Your Implementation (Mandatory)
+
+Tests must be implemented in `_test.go` following the `formatScenario` pattern:
+
+1. **Create test scenarios** using the `formatScenario` struct with fields:
+ - `description`: Brief description of what's being tested
+ - `input`: Sample input in your format
+ - `expected`: Expected output (typically in YAML for decode tests)
+ - `scenarioType`: Either `"decode"` or `"roundtrip"`
+
+2. **Test coverage must include:**
+ - Basic data types (scalars, arrays, objects/maps)
+ - Nested structures
+ - Edge cases (empty inputs, special characters, escape sequences)
+ - Format-specific features or syntax
+ - Round-trip tests: decode → encode → decode should preserve data
+
+3. **Test function pattern:**
+ - `testScenario()`: Helper function that switches on `scenarioType`
+ - `TestFormatScenarios()`: Main test function that iterates over scenarios
+
+4. **Example from existing formats:**
+ - See `hcl_test.go` for a complete example
+ - See `yaml_test.go` for YAML-specific patterns
+ - See `json_test.go` for more complex scenarios
+
+## Common Patterns
+
+### Format with Indentation
+Use preferences to control output formatting:
+```go
+type Preferences struct {
+ Indent int
+}
+
+func (prefs *Preferences) Copy() Preferences {
+ return *prefs
+}
+```
+
+### Multiple Documents
+Decoders should support reading multiple documents:
+```go
+func (dec *Decoder) Decode() (*CandidateNode, error) {
+ if dec.finished {
+ return nil, io.EOF
+ }
+ // ... decode next document ...
+ if noMoreDocuments {
+ dec.finished = true
+ }
+ return candidate, nil
+}
+```
+
+---
+
+# Adding a New Operator
+
+This guide explains how to add a new operator to yq. Operators are the core of yq's expression language and process `CandidateNode` objects without requiring modifications to `candidate_node.go` itself.
+
+## Overview
+
+Operators transform data by implementing a handler function that processes a `Context` containing `CandidateNode` objects. Each operator is:
+
+1. Defined as an `operationType` in `operation.go`
+2. Registered in the lexer in `lexer_participle.go`
+3. Implemented in its own `operator_.go` file
+4. Tested in `operator__test.go`
+5. Documented in `pkg/yqlib/doc/operators/headers/.md`
+
+## Architecture
+
+### Key Files
+
+- `pkg/yqlib/operation.go` - Defines `operationType` and operator registry
+- `pkg/yqlib/lexer_participle.go` - Registers operators with their syntax patterns
+- `pkg/yqlib/operator_.go` - Operator implementation
+- `pkg/yqlib/operator__test.go` - Operator tests using `expressionScenario`
+- `pkg/yqlib/doc/operators/headers/.md` - Documentation header
+
+### Core Types
+
+**operationType:**
+```go
+type operationType struct {
+ Type string // Unique operator name (e.g., "REVERSE")
+ NumArgs uint // Number of arguments (0 for no args)
+ Precedence uint // Operator precedence (higher = higher precedence)
+ Handler operatorHandler // The function that executes the operator
+ CheckForPostTraverse bool // Whether to apply post-traversal logic
+ ToString func(*Operation) string // Custom string representation
+}
+```
+
+**operatorHandler signature:**
+```go
+type operatorHandler func(*dataTreeNavigator, Context, *ExpressionNode) (Context, error)
+```
+
+**expressionScenario for tests:**
+```go
+type expressionScenario struct {
+ description string
+ subdescription string
+ document string
+ expression string
+ expected []string
+ skipDoc bool
+ expectedError string
+}
+```
+
+## Step-by-Step: Adding a New Operator
+
+### Step 1: Create the Operator Implementation File
+
+Create `pkg/yqlib/operator_.go` implementing the operator handler function:
+- Implement the `operatorHandler` function signature
+- Process nodes from `context.MatchingNodes`
+- Return a new `Context` with results using `context.ChildContext()`
+- Use `candidate.CreateReplacement()` or `candidate.CreateReplacementWithComments()` to create new nodes
+- Handle errors gracefully with meaningful error messages
+
+See `operator_reverse.go` or `operator_keys.go` for examples.
+
+### Step 2: Register the Operator in operation.go
+
+Add the operator type definition to `pkg/yqlib/operation.go`:
+
+```go
+var OpType = &operationType{
+ Type: "", // All caps, matches pattern in lexer
+ NumArgs: 0, // 0 for no args, 1+ for args
+ Precedence: 50, // Typical range: 40-55
+ Handler: Operator, // Reference to handler function
+}
+```
+
+**Precedence guidelines:**
+- 10-20: Logical operators (OR, AND, UNION)
+- 30: Pipe operator
+- 40: Assignment and comparison operators
+- 42: Arithmetic operators (ADD, SUBTRACT, MULTIPLY, DIVIDE)
+- 50-52: Most other operators
+- 55: High precedence (e.g., GET_VARIABLE)
+
+**Optional fields:**
+- `CheckForPostTraverse: true` - If your operator can have another directly after it without the pipe character. Most of the time this is false.
+- `ToString: customToString` - Custom string representation (rarely needed)
+
+### Step 3: Register the Operator in lexer_participle.go
+
+Edit `pkg/yqlib/lexer_participle.go` to add the operator to the lexer rules:
+- Use `simpleOp()` for simple keyword patterns
+- Use object syntax for regex patterns or complex syntax
+- Support optional characters with `_?` and aliases with `|`
+
+See existing operators in `lexer_participle.go` for pattern examples.
+
+### Step 4: Create Tests (Mandatory)
+
+Create `pkg/yqlib/operator__test.go` using the `expressionScenario` pattern:
+- Define test scenarios with `description`, `document`, `expression`, and `expected` fields
+- `expected` is a slice of strings showing output format: `"D, P[], ()::\n"`
+- Set `skipDoc: true` for edge cases you don't want in generated documentation
+- Include `subdescription` for longer test names
+- Set `expectedError` if testing error cases
+- Create main test function that iterates over scenarios
+- The main test function should use `documentScenarios` to ensure testcase documentation is generated.
+
+Test coverage must include:
+- Basic data types and nested structures
+- Edge cases (empty inputs, special characters, type errors)
+- Multiple outputs if applicable
+- Format-specific features
+
+See `operator_reverse_test.go` for a simple example and `operator_keys_test.go` for complex cases.
+
+### Step 5: Create Documentation Header
+
+Create `pkg/yqlib/doc/operators/headers/.md`:
+- Use the exact operator name as the title
+- Include a concise 1-2 sentence summary
+- Add additional context or examples if the operator is complex
+
+See existing headers in `doc/operators/headers/` for examples.
+
+## Working with Context and CandidateNode
+
+### Context Management
+- `context.ChildContext(results)` - Create child context with results
+- `context.GetVariable("varName")` - Get variables stored in context
+- `context.SetVariable("varName", value)` - Set variables in context
+
+### CandidateNode Operations
+- `candidate.CreateReplacement(ScalarNode, "!!str", stringValue)` - Create a replacement node
+- `candidate.CreateReplacementWithComments(SequenceNode, "!!seq", candidate.Style)` - With style preserved
+- `candidate.Kind` - The node type (ScalarNode, SequenceNode, MappingNode)
+- `candidate.Tag` - The YAML tag (!!str, !!int, etc.)
+- `candidate.Value` - The scalar value (for ScalarNode only)
+- `candidate.Content` - Child nodes (for SequenceNode and MappingNode)
+- `candidate.guessTagFromCustomType()` - Infer the tag from Go type
+- `candidate.AsList()` - Convert to a list representation
+
+## Key Points
+
+✅ **DO:**
+- Implement the operator handler with the correct signature
+- Register in `operation.go` with appropriate precedence
+- Add the lexer pattern in `lexer_participle.go`
+- Write comprehensive tests covering normal and edge cases
+- Create a documentation header in `doc/operators/headers/`
+- Use `Context.ChildContext()` for proper context threading
+- Handle all node types gracefully
+- Return meaningful error messages
+
+❌ **DON'T:**
+- Modify `candidate_node.go` (operators shouldn't need this)
+- Modify core navigation or evaluation logic
+- Bypass the handler function pattern
+- Add format-specific or operator-specific fields to `CandidateNode`
+- Skip tests or documentation
+
+## Examples
+
+Refer to existing operator implementations for patterns:
+
+- **No-argument operator**: `operator_reverse.go` - Processes arrays/sequences
+- **Single-argument operator**: `operator_map.go` - Takes an expression argument
+- **Complex multi-output**: `operator_keys.go` - Produces multiple results
+- **With preferences**: `operator_to_number.go` - Configuration options
+- **Error handling**: `operator_error.go` - Control flow with errors
+- **String operations**: `operator_strings.go` - Multiple related operators
+
+## Testing Patterns
+
+Refer to existing test files for specific patterns:
+- Basic expression tests in `operator_reverse_test.go`
+- Multi-output tests in `operator_keys_test.go`
+- Error handling tests in `operator_error_test.go`
+- Tests with `skipDoc` flag to exclude from generated documentation
+
+## Common Patterns
+
+Refer to existing operator implementations for these patterns:
+- Simple transformation: see `operator_reverse.go`
+- Type checking: see `operator_error.go`
+- Working with arguments: see `operator_map.go`
+- Post-traversal operators: see `operator_with.go`
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/constant.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/constant.go
index 762897d0e30..bf15c4fb75c 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/constant.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/constant.go
@@ -2,6 +2,8 @@ package cmd
var unwrapScalarFlag = newUnwrapFlag()
+var printNodeInfo = false
+
var unwrapScalar = false
var writeInplace = false
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_all_command.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_all_command.go
index ea82abef037..821cf47b5f0 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_all_command.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_all_command.go
@@ -60,7 +60,7 @@ func evaluateAll(cmd *cobra.Command, args []string) (cmdError error) {
out := cmd.OutOrStdout()
if writeInplace {
- // only use colors if its forced
+ // only use colours if its forced
colorsEnabled = forceColor
writeInPlaceHandler := yqlib.NewWriteInPlaceHandler(args[0])
out, err = writeInPlaceHandler.CreateTempFile()
@@ -101,12 +101,15 @@ func evaluateAll(cmd *cobra.Command, args []string) (cmdError error) {
}
if frontMatter != "" {
+ originalFilename := args[0]
frontMatterHandler := yqlib.NewFrontMatterHandler(args[0])
err = frontMatterHandler.Split()
if err != nil {
return err
}
args[0] = frontMatterHandler.GetYamlFrontMatterFilename()
+ yqlib.SetFilenameAlias(args[0], originalFilename)
+ defer yqlib.ClearFilenameAliases()
if frontMatter == "process" {
reader := frontMatterHandler.GetContentReader()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_sequence_command.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_sequence_command.go
index e722415e49c..4d2ecd723ac 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_sequence_command.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/evaluate_sequence_command.go
@@ -74,7 +74,7 @@ func evaluateSequence(cmd *cobra.Command, args []string) (cmdError error) {
}
if writeInplace {
- // only use colors if its forced
+ // only use colours if its forced
colorsEnabled = forceColor
writeInPlaceHandler := yqlib.NewWriteInPlaceHandler(args[0])
out, err = writeInPlaceHandler.CreateTempFile()
@@ -105,6 +105,11 @@ func evaluateSequence(cmd *cobra.Command, args []string) (cmdError error) {
}
printer := yqlib.NewPrinter(encoder, printerWriter)
+
+ if printNodeInfo {
+ printer = yqlib.NewNodeInfoPrinter(printerWriter)
+ }
+
if nulSepOutput {
printer.SetNulSepOutput(true)
}
@@ -117,12 +122,15 @@ func evaluateSequence(cmd *cobra.Command, args []string) (cmdError error) {
if frontMatter != "" {
yqlib.GetLogger().Debug("using front matter handler")
+ originalFilename := args[0]
frontMatterHandler := yqlib.NewFrontMatterHandler(args[0])
err = frontMatterHandler.Split()
if err != nil {
return err
}
args[0] = frontMatterHandler.GetYamlFrontMatterFilename()
+ yqlib.SetFilenameAlias(args[0], originalFilename)
+ defer yqlib.ClearFilenameAliases()
if frontMatter == "process" {
reader := frontMatterHandler.GetContentReader()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/root.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/root.go
index 80ebe8e122d..d2f72bfa0b7 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/root.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/root.go
@@ -2,12 +2,12 @@ package cmd
import (
"fmt"
+ "log/slog"
"os"
"strings"
"github.com/mikefarah/yq/v4/pkg/yqlib"
"github.com/spf13/cobra"
- logging "gopkg.in/op/go-logging.v1"
)
type runeValue rune
@@ -68,37 +68,29 @@ yq -P -oy sample.json
},
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
cmd.SetOut(cmd.OutOrStdout())
- level := logging.WARNING
- stringFormat := `[%{level}] %{color}%{time:15:04:05}%{color:reset} %{message}`
-
- if verbose && forceNoColor {
- level = logging.DEBUG
- stringFormat = `[%{level:5.5s}] %{time:15:04:05} %{shortfile:-33s} %{shortfunc:-25s} %{message}`
- } else if verbose {
- level = logging.DEBUG
- stringFormat = `[%{level:5.5s}] %{color}%{time:15:04:05}%{color:bold} %{shortfile:-33s} %{shortfunc:-25s}%{color:reset} %{message}`
- } else if forceNoColor {
- stringFormat = `[%{level}] %{time:15:04:05} %{message}`
- }
- var format = logging.MustStringFormatter(stringFormat)
- var backend = logging.AddModuleLevel(
- logging.NewBackendFormatter(logging.NewLogBackend(os.Stderr, "", 0), format))
+ // when NO_COLOR environment variable presents and not an empty string the coloured output should be disabled;
+ // refer to no-color.org
+ forceNoColor = forceNoColor || os.Getenv("NO_COLOR") != ""
- backend.SetLevel(level, "")
+ level := slog.LevelWarn
+ if verbose {
+ level = slog.LevelDebug
+ }
- logging.SetBackend(backend)
- yqlib.InitExpressionParser()
+ yqlib.GetLogger().SetLevel(level)
+ opts := &slog.HandlerOptions{Level: level, AddSource: verbose}
+ handler := slog.NewTextHandler(os.Stderr, opts)
+ yqlib.GetLogger().SetSlogger(slog.New(handler))
- // when NO_COLOR environment variable presents and not an empty string the coloured output should be disabled;
- // refer to no-color.org
- forceNoColor = os.Getenv("NO_COLOR") != ""
+ yqlib.InitExpressionParser()
return nil
},
}
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
+ rootCmd.PersistentFlags().BoolVarP(&printNodeInfo, "debug-node-info", "", false, "debug node info")
rootCmd.PersistentFlags().BoolVarP(&outputToJSON, "tojson", "j", false, "(deprecated) output as json. Set indent to 0 to print json in one line.")
err := rootCmd.PersistentFlags().MarkDeprecated("tojson", "please use -o=json instead")
@@ -167,6 +159,11 @@ yq -P -oy sample.json
rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredPropertiesPreferences.KeyValueSeparator, "properties-separator", yqlib.ConfiguredPropertiesPreferences.KeyValueSeparator, "separator to use between keys and values")
rootCmd.PersistentFlags().BoolVar(&yqlib.ConfiguredPropertiesPreferences.UseArrayBrackets, "properties-array-brackets", yqlib.ConfiguredPropertiesPreferences.UseArrayBrackets, "use [x] in array paths (e.g. for SpringBoot)")
+ rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredShellVariablesPreferences.KeySeparator, "shell-key-separator", yqlib.ConfiguredShellVariablesPreferences.KeySeparator, "separator for shell variable key paths")
+ if err = rootCmd.RegisterFlagCompletionFunc("shell-key-separator", cobra.NoFileCompletions); err != nil {
+ panic(err)
+ }
+
rootCmd.PersistentFlags().BoolVar(&yqlib.StringInterpolationEnabled, "string-interpolation", yqlib.StringInterpolationEnabled, "Toggles strings interpolation of \\(exp)")
rootCmd.PersistentFlags().BoolVarP(&nullInput, "null-input", "n", false, "Don't read input, simply evaluate the expression given. Useful for creating docs from scratch.")
@@ -178,7 +175,7 @@ yq -P -oy sample.json
}
rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit")
rootCmd.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the file in place of first file given.")
- rootCmd.PersistentFlags().VarP(unwrapScalarFlag, "unwrapScalar", "r", "unwrap scalar, print the value with no quotes, colors or comments. Defaults to true for yaml")
+ rootCmd.PersistentFlags().VarP(unwrapScalarFlag, "unwrapScalar", "r", "unwrap scalar, print the value with no quotes, colours or comments. Defaults to true for yaml")
rootCmd.PersistentFlags().Lookup("unwrapScalar").NoOptDefVal = "true"
rootCmd.PersistentFlags().BoolVarP(&nulSepOutput, "nul-output", "0", false, "Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char.")
@@ -196,8 +193,10 @@ yq -P -oy sample.json
panic(err)
}
rootCmd.PersistentFlags().BoolVarP(&yqlib.ConfiguredYamlPreferences.LeadingContentPreProcessing, "header-preprocess", "", true, "Slurp any header comments and separators before processing expression.")
+ rootCmd.PersistentFlags().BoolVarP(&yqlib.ConfiguredYamlPreferences.FixMergeAnchorToSpec, "yaml-fix-merge-anchor-to-spec", "", false, "Fix merge anchor to match YAML spec. Will default to true in late 2025")
+ rootCmd.PersistentFlags().BoolVarP(&yqlib.ConfiguredYamlPreferences.CompactSequenceIndent, "yaml-compact-seq-indent", "c", false, "Use compact sequence indentation where '- ' is considered part of the indentation.")
- rootCmd.PersistentFlags().StringVarP(&splitFileExp, "split-exp", "s", "", "print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter.")
+ rootCmd.PersistentFlags().StringVarP(&splitFileExp, "split-exp", "s", "", "print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter. The necessary directories will be created.")
if err = rootCmd.RegisterFlagCompletionFunc("split-exp", cobra.NoFileCompletions); err != nil {
panic(err)
}
@@ -211,6 +210,10 @@ yq -P -oy sample.json
panic(err)
}
+ rootCmd.PersistentFlags().BoolVarP(&yqlib.ConfiguredSecurityPreferences.DisableEnvOps, "security-disable-env-ops", "", false, "Disable env related operations.")
+ rootCmd.PersistentFlags().BoolVarP(&yqlib.ConfiguredSecurityPreferences.DisableFileOps, "security-disable-file-ops", "", false, "Disable file related operations (e.g. load)")
+ rootCmd.PersistentFlags().BoolVarP(&yqlib.ConfiguredSecurityPreferences.EnableSystemOps, "security-enable-system-operator", "", false, "Enable system operator to allow execution of external commands.")
+
rootCmd.AddCommand(
createEvaluateSequenceCommand(),
createEvaluateAllCommand(),
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/utils.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/utils.go
index 534615d505a..553fc994078 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/utils.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/utils.go
@@ -3,12 +3,12 @@ package cmd
import (
"fmt"
"io"
+ "log/slog"
"os"
"strings"
"github.com/mikefarah/yq/v4/pkg/yqlib"
"github.com/spf13/cobra"
- "gopkg.in/op/go-logging.v1"
)
func isAutomaticOutputFormat() bool {
@@ -18,58 +18,106 @@ func isAutomaticOutputFormat() bool {
func initCommand(cmd *cobra.Command, args []string) (string, []string, error) {
cmd.SilenceUsage = true
- fileInfo, _ := os.Stdout.Stat()
-
- if forceColor || (!forceNoColor && (fileInfo.Mode()&os.ModeCharDevice) != 0) {
- colorsEnabled = true
- }
+ setupColors()
expression, args, err := processArgs(args)
if err != nil {
return "", nil, err
}
+ if err := loadSplitFileExpression(); err != nil {
+ return "", nil, err
+ }
+
+ handleBackwardsCompatibility()
+
+ if err := validateCommandFlags(args); err != nil {
+ return "", nil, err
+ }
+
+ if err := configureFormats(args); err != nil {
+ return "", nil, err
+ }
+
+ configureUnwrapScalar()
+
+ return expression, args, nil
+}
+
+func setupColors() {
+ fileInfo, _ := os.Stdout.Stat()
+
+ if forceColor || (!forceNoColor && (fileInfo.Mode()&os.ModeCharDevice) != 0) {
+ colorsEnabled = true
+ }
+}
+
+func loadSplitFileExpression() error {
if splitFileExpFile != "" {
splitExpressionBytes, err := os.ReadFile(splitFileExpFile)
if err != nil {
- return "", nil, err
+ return err
}
splitFileExp = string(splitExpressionBytes)
}
+ return nil
+}
+func handleBackwardsCompatibility() {
// backwards compatibility
if outputToJSON {
outputFormat = "json"
}
+}
+func validateCommandFlags(args []string) error {
if writeInplace && (len(args) == 0 || args[0] == "-") {
- return "", nil, fmt.Errorf("write in place flag only applicable when giving an expression and at least one file")
+ return fmt.Errorf("write in place flag only applicable when giving an expression and at least one file")
}
if frontMatter != "" && len(args) == 0 {
- return "", nil, fmt.Errorf("front matter flag only applicable when giving an expression and at least one file")
+ return fmt.Errorf("front matter flag only applicable when giving an expression and at least one file")
}
if writeInplace && splitFileExp != "" {
- return "", nil, fmt.Errorf("write in place cannot be used with split file")
+ return fmt.Errorf("write in place cannot be used with split file")
}
if nullInput && len(args) > 0 {
- return "", nil, fmt.Errorf("cannot pass files in when using null-input flag")
+ return fmt.Errorf("cannot pass files in when using null-input flag")
}
+ return nil
+}
+
+func configureFormats(args []string) error {
inputFilename := ""
if len(args) > 0 {
inputFilename = args[0]
}
- if inputFormat == "" || inputFormat == "auto" || inputFormat == "a" {
+ if err := configureInputFormat(inputFilename); err != nil {
+ return err
+ }
+
+ if err := configureOutputFormat(); err != nil {
+ return err
+ }
+
+ yqlib.GetLogger().Debugf("Using input format %v", inputFormat)
+ yqlib.GetLogger().Debugf("Using output format %v", outputFormat)
+
+ return nil
+}
+
+func configureInputFormat(inputFilename string) error {
+ if inputFormat == "" || inputFormat == "auto" || inputFormat == "a" {
inputFormat = yqlib.FormatStringFromFilename(inputFilename)
_, err := yqlib.FormatFromString(inputFormat)
if err != nil {
// unknown file type, default to yaml
- yqlib.GetLogger().Debug("Unknown file format extension '%v', defaulting to yaml", inputFormat)
+ yqlib.GetLogger().Debugf("Unknown file format extension '%v', defaulting to yaml", inputFormat)
inputFormat = "yaml"
if isAutomaticOutputFormat() {
outputFormat = "yaml"
@@ -84,28 +132,31 @@ func initCommand(cmd *cobra.Command, args []string) (string, []string, error) {
//
outputFormat = yqlib.FormatStringFromFilename(inputFilename)
if inputFilename != "-" {
- yqlib.GetLogger().Warning("yq default output is now 'auto' (based on the filename extension). Normally yq would output '%v', but for backwards compatibility 'yaml' has been set. Please use -oy to specify yaml, or drop the -p flag.", outputFormat)
+ yqlib.GetLogger().Warningf("yq default output is now 'auto' (based on the filename extension). Normally yq would output '%v', but for backwards compatibility 'yaml' has been set. Please use -oy to specify yaml, or drop the -p flag.", outputFormat)
}
outputFormat = "yaml"
}
+ return nil
+}
+func configureOutputFormat() error {
outputFormatType, err := yqlib.FormatFromString(outputFormat)
-
if err != nil {
- return "", nil, err
+ return err
}
- yqlib.GetLogger().Debug("Using input format %v", inputFormat)
- yqlib.GetLogger().Debug("Using output format %v", outputFormat)
if outputFormatType == yqlib.YamlFormat ||
outputFormatType == yqlib.PropertiesFormat {
unwrapScalar = true
}
+
+ return nil
+}
+
+func configureUnwrapScalar() {
if unwrapScalarFlag.IsExplicitlySet() {
unwrapScalar = unwrapScalarFlag.IsSet()
}
-
- return expression, args, nil
}
func configureDecoder(evaluateTogether bool) (yqlib.Decoder, error) {
@@ -115,6 +166,9 @@ func configureDecoder(evaluateTogether bool) (yqlib.Decoder, error) {
}
yqlib.ConfiguredYamlPreferences.EvaluateTogether = evaluateTogether
+ if format.DecoderFactory == nil {
+ return nil, fmt.Errorf("no support for %s input format", inputFormat)
+ }
yqlibDecoder := format.DecoderFactory()
if yqlibDecoder == nil {
return nil, fmt.Errorf("no support for %s input format", inputFormat)
@@ -146,16 +200,23 @@ func configureEncoder() (yqlib.Encoder, error) {
}
yqlib.ConfiguredXMLPreferences.Indent = indent
yqlib.ConfiguredYamlPreferences.Indent = indent
+ yqlib.ConfiguredKYamlPreferences.Indent = indent
yqlib.ConfiguredJSONPreferences.Indent = indent
yqlib.ConfiguredYamlPreferences.UnwrapScalar = unwrapScalar
+ yqlib.ConfiguredKYamlPreferences.UnwrapScalar = unwrapScalar
yqlib.ConfiguredPropertiesPreferences.UnwrapScalar = unwrapScalar
yqlib.ConfiguredJSONPreferences.UnwrapScalar = unwrapScalar
+ yqlib.ConfiguredShellVariablesPreferences.UnwrapScalar = unwrapScalar
yqlib.ConfiguredYamlPreferences.ColorsEnabled = colorsEnabled
+ yqlib.ConfiguredKYamlPreferences.ColorsEnabled = colorsEnabled
yqlib.ConfiguredJSONPreferences.ColorsEnabled = colorsEnabled
+ yqlib.ConfiguredHclPreferences.ColorsEnabled = colorsEnabled
+ yqlib.ConfiguredTomlPreferences.ColorsEnabled = colorsEnabled
yqlib.ConfiguredYamlPreferences.PrintDocSeparators = !noDocSeparators
+ yqlib.ConfiguredKYamlPreferences.PrintDocSeparators = !noDocSeparators
encoder := yqlibOutputFormat.EncoderFactory()
@@ -174,7 +235,7 @@ func maybeFile(str string) bool {
yqlib.GetLogger().Debugf("checking '%v' is a file", str)
stat, err := os.Stat(str) // #nosec
result := err == nil && !stat.IsDir()
- if yqlib.GetLogger().IsEnabledFor(logging.DEBUG) {
+ if yqlib.GetLogger().IsEnabledFor(slog.LevelDebug) {
if err != nil {
yqlib.GetLogger().Debugf("error: %v", err)
} else {
@@ -219,7 +280,7 @@ func processArgs(originalArgs []string) (string, []string, error) {
if expressionFile == "" && maybeFirstArgIsAFile && strings.HasSuffix(args[0], ".yq") {
// lets check if an expression file was given
- yqlib.GetLogger().Debug("Assuming arg %v is an expression file", args[0])
+ yqlib.GetLogger().Debugf("Assuming arg %v is an expression file", args[0])
expressionFile = args[0]
args = args[1:]
}
@@ -235,7 +296,7 @@ func processArgs(originalArgs []string) (string, []string, error) {
yqlib.GetLogger().Debugf("processed args: %v", args)
if expression == "" && len(args) > 0 && args[0] != "-" && !maybeFile(args[0]) {
- yqlib.GetLogger().Debug("assuming expression is '%v'", args[0])
+ yqlib.GetLogger().Debugf("assuming expression is '%v'", args[0])
expression = args[0]
args = args[1:]
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/version.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/version.go
index 4a5c4cd7fb5..1b268a4f95f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/version.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/cmd/version.go
@@ -11,7 +11,7 @@ var (
GitDescribe string
// Version is main version number that is being run at the moment.
- Version = "v4.44.5"
+ Version = "v4.53.2"
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
@@ -45,5 +45,5 @@ func getHumanVersion() string {
}
// Strip off any single quotes added by the git information.
- return strings.Replace(version, "'", "", -1)
+ return strings.ReplaceAll(version, "'", "")
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/how-it-works.md b/hack/tools/vendor/github.com/mikefarah/yq/v4/how-it-works.md
index f77a4cd96d1..fbc647be267 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/how-it-works.md
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/how-it-works.md
@@ -1,8 +1,63 @@
-# How it works
+# Expression Syntax: A Visual Guide
+In `yq`, expressions are made up of operators and pipes. A context of nodes is passed through the expression, and each operation takes the context as input and returns a new context as output. That output is piped in as input for the next operation in the expression.
-In `yq` expressions are made up of operators and pipes. A context of nodes is passed through the expression and each operation takes the context as input and returns a new context as output. That output is piped in as input for the next operation in the expression. To begin with, the context is set to the first yaml document of the first yaml file (if processing in sequence using eval).
+Let's break down the process step by step using a diagram. We'll start with a single YAML document, apply an expression, and observe how the context changes at each step.
-Lets look at a couple of examples.
+Given a document like:
+
+```yaml
+root:
+ items:
+ - name: apple
+ type: fruit
+ - name: carrot
+ type: vegetable
+ - name: banana
+ type: fruit
+```
+
+You can use dot notation to access nested structures. For example, to access the `name` of the first item, you would use the expression `.root.items[0].name`, which would return `apple`.
+
+But lets see how we could find all the fruit under `items`
+
+## Step 1: Initial Context
+The context starts at the root of the YAML document. In this case, the entire document is the initial context.
+
+```
+root
+└── items
+ ├── name: apple
+ │ type: fruit
+ ├── name: carrot
+ │ type: vegetable
+ └── name: banana
+ type: fruit
+```
+
+## Step 2: Splatting the Array
+Using the expression `.root.items[]`, we "splat" the items array. This means each element of the array becomes its own node in the context:
+
+```
+Node 1: { name: apple, type: fruit }
+Node 2: { name: carrot, type: vegetable }
+Node 3: { name: banana, type: fruit }
+```
+
+## Step 3: Filtering the Nodes
+Next, we apply a filter to select only the nodes where type is fruit. The expression `.root.items[] | select(.type == "fruit")` filters the nodes:
+
+```
+Filtered Node 1: { name: apple, type: fruit }
+Filtered Node 2: { name: banana, type: fruit }
+```
+
+## Step 4: Extracting a Field
+Finally, we extract the name field from the filtered nodes using `.root.items[] | select(.type == "fruit") | .name` This results in:
+
+```
+apple
+banana
+```
## Simple assignment example
@@ -44,7 +99,6 @@ a: dog
b: dog
```
-
## Complex assignment, operator precedence rules
Just like math expressions - `yq` expressions have an order of precedence. The pipe `|` operator has a low order of precedence, so operators with higher precedence will get evaluated first.
@@ -73,7 +127,7 @@ name: sally
fruit: mango
```
-To properly update this yaml, you will need to use brackets (think BODMAS from maths) and wrap the entire LHS:
+**Important**: To properly update this YAML, you must wrap the entire LHS in parentheses. Think of it like using brackets in math to ensure the correct order of operations.
`(.[] | select(.name == "sally") | .fruit) = "mango"`
@@ -126,4 +180,4 @@ The assignment operator then copies across the value from the RHS to the value o
```yaml
a: 2
b: thing
-```
+```
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go
index 4762ea67d21..92f14cdeb02 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go
@@ -27,6 +27,22 @@ const (
FlowStyle
)
+// EncodeHint controls how a mapping node is serialised by format-specific encoders
+// that distinguish between inline and block/section representations (e.g. TOML, HCL).
+type EncodeHint int
+
+const (
+ // EncodeHintDefault lets the encoder choose the representation (e.g. TOML block
+ // mappings default to [section] headers).
+ EncodeHintDefault EncodeHint = iota
+ // EncodeHintSeparateBlock forces the node to be emitted as a separate block or
+ // table-section header (used by TOML [section] and HCL block decoders).
+ EncodeHintSeparateBlock
+ // EncodeHintInline forces the node to be emitted as an inline / flow table
+ // (used by TOML inline-table decoder and TOML encoder).
+ EncodeHintInline
+)
+
func createStringScalarNode(stringValue string) *CandidateNode {
var node = &CandidateNode{Kind: ScalarNode}
node.Value = stringValue
@@ -53,6 +69,20 @@ func createScalarNode(value interface{}, stringValue string) *CandidateNode {
return node
}
+type NodeInfo struct {
+ Kind string `yaml:"kind"`
+ Style string `yaml:"style,omitempty"`
+ Anchor string `yaml:"anchor,omitempty"`
+ Tag string `yaml:"tag,omitempty"`
+ HeadComment string `yaml:"headComment,omitempty"`
+ LineComment string `yaml:"lineComment,omitempty"`
+ FootComment string `yaml:"footComment,omitempty"`
+ Value string `yaml:"value,omitempty"`
+ Line int `yaml:"line,omitempty"`
+ Column int `yaml:"column,omitempty"`
+ Content []*NodeInfo `yaml:"content,omitempty"`
+}
+
type CandidateNode struct {
Kind Kind
Style Style
@@ -83,6 +113,9 @@ type CandidateNode struct {
// (e.g. top level cross document merge). This property does not propagate to child nodes.
EvaluateTogether bool
IsMapKey bool
+ // EncodeHint controls how a mapping node is serialised by format-specific encoders
+ // (e.g. TOML, HCL) that support both inline and block/section representations.
+ EncodeHint EncodeHint
}
func (n *CandidateNode) CreateChild() *CandidateNode {
@@ -155,6 +188,18 @@ func (n *CandidateNode) getParsedKey() interface{} {
}
+func (n *CandidateNode) FilterMapContentByKey(keyPredicate func(*CandidateNode) bool) []*CandidateNode {
+ var result []*CandidateNode
+ for index := 0; index < len(n.Content); index = index + 2 {
+ keyNode := n.Content[index]
+ valueNode := n.Content[index+1]
+ if keyPredicate(keyNode) {
+ result = append(result, keyNode, valueNode)
+ }
+ }
+ return result
+}
+
func (n *CandidateNode) GetPath() []interface{} {
key := n.getParsedKey()
if n.Parent != nil && key != nil {
@@ -198,6 +243,30 @@ func (n *CandidateNode) SetParent(parent *CandidateNode) {
n.Parent = parent
}
+type ValueVisitor func(*CandidateNode) error
+
+func (n *CandidateNode) VisitValues(visitor ValueVisitor) error {
+ switch n.Kind {
+ case MappingNode:
+ for i := 1; i < len(n.Content); i = i + 2 {
+ if err := visitor(n.Content[i]); err != nil {
+ return err
+ }
+ }
+ case SequenceNode:
+ for i := 0; i < len(n.Content); i = i + 1 {
+ if err := visitor(n.Content[i]); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func (n *CandidateNode) CanVisitValues() bool {
+ return n.Kind == MappingNode || n.Kind == SequenceNode
+}
+
func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) (*CandidateNode, *CandidateNode) {
key := rawKey.Copy()
key.SetParent(n)
@@ -215,20 +284,19 @@ func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *Candid
func (n *CandidateNode) AddChild(rawChild *CandidateNode) {
value := rawChild.Copy()
value.SetParent(n)
- if value.Key != nil {
- value.Key.SetParent(n)
- } else {
- index := len(n.Content)
- keyNode := createScalarNode(index, fmt.Sprintf("%v", index))
- keyNode.SetParent(n)
- value.Key = keyNode
- }
+ value.IsMapKey = false
+
+ index := len(n.Content)
+ keyNode := createScalarNode(index, fmt.Sprintf("%v", index))
+ keyNode.SetParent(n)
+ value.Key = keyNode
+
n.Content = append(n.Content, value)
}
func (n *CandidateNode) AddChildren(children []*CandidateNode) {
if n.Kind == MappingNode {
- for i := 0; i < len(children); i += 2 {
+ for i := 0; i < len(children)-1; i += 2 {
key := children[i]
value := children[i+1]
n.AddKeyValueChild(key, value)
@@ -271,11 +339,11 @@ func (n *CandidateNode) guessTagFromCustomType() string {
dataBucket, errorReading := parseSnippet(n.Value)
if errorReading != nil {
- log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
+ log.Debugf("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
return n.Tag
}
guessedTag := dataBucket.Tag
- log.Info("im guessing the tag %v is a %v", n.Tag, guessedTag)
+ log.Infof("im guessing the tag %v is a %v", n.Tag, guessedTag)
return guessedTag
}
@@ -358,6 +426,8 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
EvaluateTogether: n.EvaluateTogether,
IsMapKey: n.IsMapKey,
+
+ EncodeHint: n.EncodeHint,
}
if cloneContent {
@@ -391,7 +461,7 @@ func (n *CandidateNode) UpdateFrom(other *CandidateNode, prefs assignPreferences
}
func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignPreferences) {
- log.Debug("UpdateAttributesFrom: n: %v other: %v", NodeToString(n), NodeToString(other))
+ log.Debugf("UpdateAttributesFrom: n: %v other: %v", NodeToString(n), NodeToString(other))
if n.Kind != other.Kind {
// clear out the contents when switching to a different type
// e.g. map to array
@@ -411,6 +481,9 @@ func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignP
n.Anchor = other.Anchor
}
+ // Preserve EncodeHint for format-specific encoding hints
+ n.EncodeHint = other.EncodeHint
+
// merge will pickup the style of the new thing
// when autocreating nodes
@@ -428,3 +501,64 @@ func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignP
n.LineComment = other.LineComment
}
}
+
+func (n *CandidateNode) ConvertToNodeInfo() *NodeInfo {
+ info := &NodeInfo{
+ Kind: kindToString(n.Kind),
+ Style: styleToString(n.Style),
+ Anchor: n.Anchor,
+ Tag: n.Tag,
+ HeadComment: n.HeadComment,
+ LineComment: n.LineComment,
+ FootComment: n.FootComment,
+ Value: n.Value,
+ Line: n.Line,
+ Column: n.Column,
+ }
+ if len(n.Content) > 0 {
+ info.Content = make([]*NodeInfo, len(n.Content))
+ for i, child := range n.Content {
+ info.Content[i] = child.ConvertToNodeInfo()
+ }
+ }
+ return info
+}
+
+// Helper functions to convert Kind and Style to string for NodeInfo
+func kindToString(k Kind) string {
+ switch k {
+ case SequenceNode:
+ return "SequenceNode"
+ case MappingNode:
+ return "MappingNode"
+ case ScalarNode:
+ return "ScalarNode"
+ case AliasNode:
+ return "AliasNode"
+ default:
+ return "Unknown"
+ }
+}
+
+func styleToString(s Style) string {
+ var styles []string
+ if s&TaggedStyle != 0 {
+ styles = append(styles, "TaggedStyle")
+ }
+ if s&DoubleQuotedStyle != 0 {
+ styles = append(styles, "DoubleQuotedStyle")
+ }
+ if s&SingleQuotedStyle != 0 {
+ styles = append(styles, "SingleQuotedStyle")
+ }
+ if s&LiteralStyle != 0 {
+ styles = append(styles, "LiteralStyle")
+ }
+ if s&FoldedStyle != 0 {
+ styles = append(styles, "FoldedStyle")
+ }
+ if s&FlowStyle != 0 {
+ styles = append(styles, "FlowStyle")
+ }
+ return strings.Join(styles, ",")
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_goccy_yaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_goccy_yaml.go
index 7974c7231f0..f8874286fae 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_goccy_yaml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_goccy_yaml.go
@@ -9,14 +9,14 @@ import (
goccyToken "github.com/goccy/go-yaml/token"
)
-func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, cm yaml.CommentMap) (*CandidateNode, error) {
+func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, cm yaml.CommentMap, anchorMap map[string]*CandidateNode) (*CandidateNode, error) {
newChild := o.CreateChild()
- err := newChild.UnmarshalGoccyYAML(childNode, cm)
+ err := newChild.UnmarshalGoccyYAML(childNode, cm, anchorMap)
return newChild, err
}
-func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) error {
+func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap, anchorMap map[string]*CandidateNode) error {
log.Debugf("UnmarshalYAML %v", node)
log.Debugf("UnmarshalYAML %v", node.Type().String())
log.Debugf("UnmarshalYAML Node Value: %v", node.String())
@@ -36,13 +36,13 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
switch commentMapComment.Position {
case yaml.CommentHeadPosition:
o.HeadComment = comment.String()
- log.Debug("its a head comment %v", comment.String())
+ log.Debugf("its a head comment %v", comment.String())
case yaml.CommentLinePosition:
o.LineComment = comment.String()
- log.Debug("its a line comment %v", comment.String())
+ log.Debugf("its a line comment %v", comment.String())
case yaml.CommentFootPosition:
o.FootComment = comment.String()
- log.Debug("its a foot comment %v", comment.String())
+ log.Debugf("its a foot comment %v", comment.String())
}
}
}
@@ -51,6 +51,9 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
}
o.Value = node.String()
+ o.Line = node.GetToken().Position.Line
+ o.Column = node.GetToken().Position.Column
+
switch node.Type() {
case ast.IntegerType:
o.Kind = ScalarNode
@@ -62,9 +65,13 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
o.Kind = ScalarNode
o.Tag = "!!bool"
case ast.NullType:
+ log.Debugf("its a null type with value %v", node.GetToken().Value)
o.Kind = ScalarNode
o.Tag = "!!null"
o.Value = node.GetToken().Value
+ if node.GetToken().Type == goccyToken.ImplicitNullType {
+ o.Value = ""
+ }
case ast.StringType:
o.Kind = ScalarNode
o.Tag = "!!str"
@@ -86,13 +93,13 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
log.Debugf("folded Type %v", astLiteral.Start.Type)
o.Style = FoldedStyle
}
- log.Debug("start value: %v ", node.(*ast.LiteralNode).Start.Value)
- log.Debug("start value: %v ", node.(*ast.LiteralNode).Start.Type)
+ log.Debugf("start value: %v ", node.(*ast.LiteralNode).Start.Value)
+ log.Debugf("start value: %v ", node.(*ast.LiteralNode).Start.Type)
// TODO: here I could put the original value with line breaks
// to solve the multiline > problem
o.Value = astLiteral.Value.Value
case ast.TagType:
- if err := o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, cm); err != nil {
+ if err := o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, cm, anchorMap); err != nil {
return err
}
o.Tag = node.(*ast.TagNode).Start.Value
@@ -106,9 +113,9 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
o.Style = FlowStyle
}
for _, mappingValueNode := range mappingNode.Values {
- err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
+ err := o.goccyProcessMappingValueNode(mappingValueNode, cm, anchorMap)
if err != nil {
- return ast.ErrInvalidAnchorName
+ return err
}
}
if mappingNode.FootComment != nil {
@@ -120,9 +127,9 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
o.Kind = MappingNode
o.Tag = "!!map"
mappingValueNode := node.(*ast.MappingValueNode)
- err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
+ err := o.goccyProcessMappingValueNode(mappingValueNode, cm, anchorMap)
if err != nil {
- return ast.ErrInvalidAnchorName
+ return err
}
case ast.SequenceType:
log.Debugf("UnmarshalYAML - a sequence node")
@@ -141,7 +148,7 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
keyNode.Kind = ScalarNode
keyNode.Value = fmt.Sprintf("%v", i)
- valueNode, err := o.goccyDecodeIntoChild(astSeq[i], cm)
+ valueNode, err := o.goccyDecodeIntoChild(astSeq[i], cm, anchorMap)
if err != nil {
return err
}
@@ -149,32 +156,55 @@ func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) er
valueNode.Key = keyNode
o.Content[i] = valueNode
}
+ case ast.AnchorType:
+ log.Debugf("UnmarshalYAML - an anchor node")
+ anchorNode := node.(*ast.AnchorNode)
+ err := o.UnmarshalGoccyYAML(anchorNode.Value, cm, anchorMap)
+ if err != nil {
+ return err
+ }
+ o.Anchor = anchorNode.Name.String()
+ anchorMap[o.Anchor] = o
+
+ case ast.AliasType:
+ log.Debugf("UnmarshalYAML - an alias node")
+ aliasNode := node.(*ast.AliasNode)
+ o.Kind = AliasNode
+ o.Value = aliasNode.Value.String()
+ o.Alias = anchorMap[o.Value]
+
+ case ast.MergeKeyType:
+ log.Debugf("UnmarshalYAML - a merge key")
+ o.Kind = ScalarNode
+ o.Tag = "!!merge" // note - I should be able to get rid of this.
+ o.Value = "<<"
default:
- log.Debugf("UnmarshalYAML - node idea of the type!!")
+ log.Debugf("UnmarshalYAML - no idea of the type!!\n%v: %v", node.Type(), node.String())
}
log.Debugf("KIND: %v", o.Kind)
return nil
}
-func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingValueNode, cm yaml.CommentMap) error {
- log.Debug("UnmarshalYAML MAP KEY entry %v", mappingEntry.Key)
- keyNode, err := o.goccyDecodeIntoChild(mappingEntry.Key, cm)
- if err != nil {
+func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingValueNode, cm yaml.CommentMap, anchorMap map[string]*CandidateNode) error {
+ log.Debugf("UnmarshalYAML MAP KEY entry %v", mappingEntry.Key)
+
+ // AddKeyValueFirst because it clones the nodes, and we want to have the real refs when Unmarshalling
+ // particularly for the anchorMap
+ keyNode, valueNode := o.AddKeyValueChild(&CandidateNode{}, &CandidateNode{})
+
+ if err := keyNode.UnmarshalGoccyYAML(mappingEntry.Key, cm, anchorMap); err != nil {
return err
}
- keyNode.IsMapKey = true
- log.Debug("UnmarshalYAML MAP VALUE entry %v", mappingEntry.Value)
- valueNode, err := o.goccyDecodeIntoChild(mappingEntry.Value, cm)
- if err != nil {
+ log.Debugf("UnmarshalYAML MAP VALUE entry %v", mappingEntry.Value)
+ if err := valueNode.UnmarshalGoccyYAML(mappingEntry.Value, cm, anchorMap); err != nil {
return err
}
if mappingEntry.FootComment != nil {
valueNode.FootComment = mappingEntry.FootComment.String()
}
- o.AddKeyValueChild(keyNode, valueNode)
return nil
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_json.go
similarity index 98%
rename from hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go
rename to hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_json.go
index fe7d344ee83..04ad24b8db8 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_json.go
@@ -1,3 +1,5 @@
+//go:build !yq_nojson
+
package yqlib
import (
@@ -118,7 +120,7 @@ func (o *CandidateNode) UnmarshalJSON(data []byte) error {
if err != nil {
return err
}
- log.Debug("UnmarshalJSON - scalar is %v", scalar)
+ log.Debugf("UnmarshalJSON - scalar is %v", scalar)
return o.setScalarFromJson(scalar)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go
index 67f57a4803b..416f307eccf 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go
@@ -3,7 +3,7 @@ package yqlib
import (
"fmt"
- yaml "gopkg.in/yaml.v3"
+ yaml "go.yaml.in/yaml/v4"
)
func MapYamlStyle(original yaml.Style) Style {
@@ -55,13 +55,13 @@ func (o *CandidateNode) copyFromYamlNode(node *yaml.Node, anchorMap map[string]*
if o.Anchor != "" {
anchorMap[o.Anchor] = o
- log.Debug("set anchor %v to %v", o.Anchor, NodeToString(o))
+ log.Debugf("set anchor %v to %v", o.Anchor, NodeToString(o))
}
// its a single alias
if node.Alias != nil && node.Alias.Anchor != "" {
o.Alias = anchorMap[node.Alias.Anchor]
- log.Debug("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor]))
+ log.Debugf("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor]))
}
o.HeadComment = node.HeadComment
o.LineComment = node.LineComment
@@ -78,9 +78,6 @@ func (o *CandidateNode) copyToYamlNode(node *yaml.Node) {
node.Value = o.Value
node.Anchor = o.Anchor
- // node.Alias = TODO - find Alias in our own structure
- // might need to be a post process thing
-
node.HeadComment = o.HeadComment
node.LineComment = o.LineComment
@@ -109,7 +106,7 @@ func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*Can
log.Debugf("UnmarshalYAML %v", node.Tag)
switch node.Kind {
case yaml.AliasNode:
- log.Debug("UnmarshalYAML - alias from yaml: %v", o.Tag)
+ log.Debugf("UnmarshalYAML - alias from yaml: %v", o.Tag)
o.Kind = AliasNode
o.copyFromYamlNode(node, anchorMap)
return nil
@@ -179,15 +176,15 @@ func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*Can
}
func (o *CandidateNode) MarshalYAML() (*yaml.Node, error) {
- log.Debug("MarshalYAML to yaml: %v", o.Tag)
+ log.Debugf("MarshalYAML to yaml: %v", o.Tag)
switch o.Kind {
case AliasNode:
- log.Debug("MarshalYAML - alias to yaml: %v", o.Tag)
+ log.Debugf("MarshalYAML - alias to yaml: %v", o.Tag)
target := &yaml.Node{Kind: yaml.AliasNode}
o.copyToYamlNode(target)
return target, nil
case ScalarNode:
- log.Debug("MarshalYAML - scalar: %v", o.Value)
+ log.Debugf("MarshalYAML - scalar: %v", o.Value)
target := &yaml.Node{Kind: yaml.ScalarNode}
o.copyToYamlNode(target)
return target, nil
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go
index 174a794833e..a8e3a78cd77 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go
@@ -18,7 +18,7 @@ func changeOwner(info fs.FileInfo, file *os.File) error {
// this happens with snap confinement
// not really a big issue as users can chown
// the file themselves if required.
- log.Info("Skipping chown: %v", err)
+ log.Infof("Skipping chown: %v", err)
}
}
return nil
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/context.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/context.go
index aaa80da6d6d..eddf1364a05 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/context.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/context.go
@@ -3,9 +3,8 @@ package yqlib
import (
"container/list"
"fmt"
+ "log/slog"
"time"
-
- logging "gopkg.in/op/go-logging.v1"
)
type Context struct {
@@ -75,7 +74,7 @@ func (n *Context) ChildContext(results *list.List) Context {
}
func (n *Context) ToString() string {
- if !log.IsEnabledFor(logging.DEBUG) {
+ if !log.IsEnabledFor(slog.LevelDebug) {
return ""
}
result := fmt.Sprintf("Context\nDontAutoCreate: %v\n", n.DontAutoCreate)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go
index 99bece43e7d..8dda12fde43 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go
@@ -2,8 +2,7 @@ package yqlib
import (
"fmt"
-
- logging "gopkg.in/op/go-logging.v1"
+ "log/slog"
)
type DataTreeNavigator interface {
@@ -55,7 +54,7 @@ func (d *dataTreeNavigator) GetMatchingNodes(context Context, expressionNode *Ex
return context, nil
}
log.Debugf("Processing Op: %v", expressionNode.Operation.toString())
- if log.IsEnabledFor(logging.DEBUG) {
+ if log.IsEnabledFor(slog.LevelDebug) {
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
log.Debug(NodeToString(el.Value.(*CandidateNode)))
}
@@ -64,6 +63,6 @@ func (d *dataTreeNavigator) GetMatchingNodes(context Context, expressionNode *Ex
if handler != nil {
return handler(d, context, expressionNode)
}
- return Context{}, fmt.Errorf("Unknown operator %v", expressionNode.Operation.OperationType)
+ return Context{}, fmt.Errorf("unknown operator %v", expressionNode.Operation.OperationType.Type)
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go
index b5e9681e9b0..852878f17e1 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go
@@ -1,3 +1,5 @@
+//go:build !yq_nobase64
+
package yqlib
import (
@@ -7,28 +9,6 @@ import (
"strings"
)
-type base64Padder struct {
- count int
- io.Reader
-}
-
-func (c *base64Padder) pad(buf []byte) (int, error) {
- pad := strings.Repeat("=", (4 - c.count%4))
- n, err := strings.NewReader(pad).Read(buf)
- c.count += n
- return n, err
-}
-
-func (c *base64Padder) Read(buf []byte) (int, error) {
- n, err := c.Reader.Read(buf)
- c.count += n
-
- if err == io.EOF && c.count%4 != 0 {
- return c.pad(buf)
- }
- return n, err
-}
-
type base64Decoder struct {
reader io.Reader
finished bool
@@ -41,7 +21,25 @@ func NewBase64Decoder() Decoder {
}
func (dec *base64Decoder) Init(reader io.Reader) error {
- dec.reader = &base64Padder{Reader: reader}
+ // Read all data from the reader and strip leading/trailing whitespace
+ // This is necessary because base64 decoding needs to see the complete input
+ // to handle padding correctly, and we need to strip whitespace before decoding.
+ buf := new(bytes.Buffer)
+ if _, err := buf.ReadFrom(reader); err != nil {
+ return err
+ }
+
+ // Strip leading and trailing whitespace
+ stripped := strings.TrimSpace(buf.String())
+
+ // Add padding if needed (base64 strings should be a multiple of 4 characters)
+ padLen := len(stripped) % 4
+ if padLen > 0 {
+ stripped += strings.Repeat("=", 4-padLen)
+ }
+
+ // Create a new reader from the stripped and padded data
+ dec.reader = strings.NewReader(stripped)
dec.readAnything = false
dec.finished = false
return nil
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go
index 21eb136987a..6d7c31d4706 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go
@@ -1,3 +1,5 @@
+//go:build !yq_nocsv
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_goccy_yaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_goccy_yaml.go
index 11aca8a515a..6598e68d751 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_goccy_yaml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_goccy_yaml.go
@@ -16,6 +16,8 @@ import (
type goccyYamlDecoder struct {
decoder yaml.Decoder
cm yaml.CommentMap
+ // anchor map persists over multiple documents for convenience.
+ anchorMap map[string]*CandidateNode
}
func NewGoccyYAMLDecoder() Decoder {
@@ -25,6 +27,7 @@ func NewGoccyYAMLDecoder() Decoder {
func (dec *goccyYamlDecoder) Init(reader io.Reader) error {
dec.cm = yaml.CommentMap{}
dec.decoder = *yaml.NewDecoder(reader, yaml.CommentToMap(dec.cm), yaml.UseOrderedMap())
+ dec.anchorMap = make(map[string]*CandidateNode)
return nil
}
@@ -38,7 +41,7 @@ func (dec *goccyYamlDecoder) Decode() (*CandidateNode, error) {
}
candidateNode := &CandidateNode{}
- if err := candidateNode.UnmarshalGoccyYAML(ast, dec.cm); err != nil {
+ if err := candidateNode.UnmarshalGoccyYAML(ast, dec.cm, dec.anchorMap); err != nil {
return nil, err
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_hcl.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_hcl.go
new file mode 100644
index 00000000000..11cd00305f8
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_hcl.go
@@ -0,0 +1,471 @@
+//go:build !yq_nohcl
+
+package yqlib
+
+import (
+ "fmt"
+ "io"
+ "math/big"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type hclDecoder struct {
+ file *hcl.File
+ fileBytes []byte
+ readAnything bool
+ documentIndex uint
+}
+
+func NewHclDecoder() Decoder {
+ return &hclDecoder{}
+}
+
+// sortedAttributes returns attributes in declaration order by source position
+func sortedAttributes(attrs hclsyntax.Attributes) []*attributeWithName {
+ var sorted []*attributeWithName
+ for name, attr := range attrs {
+ sorted = append(sorted, &attributeWithName{Name: name, Attr: attr})
+ }
+ sort.Slice(sorted, func(i, j int) bool {
+ return sorted[i].Attr.Range().Start.Byte < sorted[j].Attr.Range().Start.Byte
+ })
+ return sorted
+}
+
+type attributeWithName struct {
+ Name string
+ Attr *hclsyntax.Attribute
+}
+
+// extractLineComment extracts any inline comment after the given position
+func extractLineComment(src []byte, endPos int) string {
+ // Look for # comment after the token
+ for i := endPos; i < len(src); i++ {
+ if src[i] == '#' {
+ // Found comment, extract until end of line
+ start := i
+ for i < len(src) && src[i] != '\n' {
+ i++
+ }
+ return strings.TrimSpace(string(src[start:i]))
+ }
+ if src[i] == '\n' {
+ // Hit newline before comment
+ break
+ }
+ // Skip whitespace and other characters
+ }
+ return ""
+}
+
+// extractHeadComment extracts comments before a given start position
+func extractHeadComment(src []byte, startPos int) string {
+ var comments []string
+
+ // Start just before the token and skip trailing whitespace
+ i := startPos - 1
+ for i >= 0 && (src[i] == ' ' || src[i] == '\t' || src[i] == '\n' || src[i] == '\r') {
+ i--
+ }
+
+ for i >= 0 {
+ // Find line boundaries
+ lineEnd := i
+ for i >= 0 && src[i] != '\n' {
+ i--
+ }
+ lineStart := i + 1
+
+ line := strings.TrimRight(string(src[lineStart:lineEnd+1]), " \t\r")
+ trimmed := strings.TrimSpace(line)
+
+ if trimmed == "" {
+ break
+ }
+
+ if !strings.HasPrefix(trimmed, "#") {
+ break
+ }
+
+ comments = append([]string{trimmed}, comments...)
+
+ // Move to previous line (skip any whitespace/newlines)
+ i = lineStart - 1
+ for i >= 0 && (src[i] == ' ' || src[i] == '\t' || src[i] == '\n' || src[i] == '\r') {
+ i--
+ }
+ }
+
+ if len(comments) > 0 {
+ return strings.Join(comments, "\n")
+ }
+ return ""
+}
+
+func (dec *hclDecoder) Init(reader io.Reader) error {
+ data, err := io.ReadAll(reader)
+ if err != nil {
+ return err
+ }
+ file, diags := hclsyntax.ParseConfig(data, "input.hcl", hcl.Pos{Line: 1, Column: 1})
+ if diags != nil && diags.HasErrors() {
+ return fmt.Errorf("hcl parse error: %w", diags)
+ }
+ dec.file = file
+ dec.fileBytes = data
+ dec.readAnything = false
+ dec.documentIndex = 0
+ return nil
+}
+
+func (dec *hclDecoder) Decode() (*CandidateNode, error) {
+ if dec.readAnything {
+ return nil, io.EOF
+ }
+ dec.readAnything = true
+
+ if dec.file == nil {
+ return nil, fmt.Errorf("no hcl file parsed")
+ }
+
+ root := &CandidateNode{Kind: MappingNode}
+
+ // process attributes in declaration order
+ body := dec.file.Body.(*hclsyntax.Body)
+ firstAttr := true
+ for _, attrWithName := range sortedAttributes(body.Attributes) {
+ keyNode := createStringScalarNode(attrWithName.Name)
+ valNode := convertHclExprToNode(attrWithName.Attr.Expr, dec.fileBytes)
+
+ // Attach comments if any
+ attrRange := attrWithName.Attr.Range()
+ headComment := extractHeadComment(dec.fileBytes, attrRange.Start.Byte)
+ if firstAttr && headComment != "" {
+ // For the first attribute, apply its head comment to the root
+ root.HeadComment = headComment
+ firstAttr = false
+ } else if headComment != "" {
+ keyNode.HeadComment = headComment
+ }
+ if lineComment := extractLineComment(dec.fileBytes, attrRange.End.Byte); lineComment != "" {
+ valNode.LineComment = lineComment
+ }
+
+ root.AddKeyValueChild(keyNode, valNode)
+ }
+
+ // process blocks
+ // Count blocks by type at THIS level to detect multiple separate blocks
+ blocksByType := make(map[string]int)
+ for _, block := range body.Blocks {
+ blocksByType[block.Type]++
+ }
+
+ for _, block := range body.Blocks {
+ addBlockToMapping(root, block, dec.fileBytes, blocksByType[block.Type] > 1)
+ }
+
+ dec.documentIndex++
+ root.document = dec.documentIndex - 1
+ return root, nil
+}
+
+func hclBodyToNode(body *hclsyntax.Body, src []byte) *CandidateNode {
+ node := &CandidateNode{Kind: MappingNode}
+ for _, attrWithName := range sortedAttributes(body.Attributes) {
+ key := createStringScalarNode(attrWithName.Name)
+ val := convertHclExprToNode(attrWithName.Attr.Expr, src)
+
+ // Attach comments if any
+ attrRange := attrWithName.Attr.Range()
+ if headComment := extractHeadComment(src, attrRange.Start.Byte); headComment != "" {
+ key.HeadComment = headComment
+ }
+ if lineComment := extractLineComment(src, attrRange.End.Byte); lineComment != "" {
+ val.LineComment = lineComment
+ }
+
+ node.AddKeyValueChild(key, val)
+ }
+
+ // Process nested blocks, counting blocks by type at THIS level
+ // to detect which block types appear multiple times
+ blocksByType := make(map[string]int)
+ for _, block := range body.Blocks {
+ blocksByType[block.Type]++
+ }
+
+ for _, block := range body.Blocks {
+ addBlockToMapping(node, block, src, blocksByType[block.Type] > 1)
+ }
+ return node
+}
+
+// addBlockToMapping nests block type and labels into the parent mapping, merging children.
+// isMultipleBlocksOfType indicates if there are multiple blocks of this type at THIS level
+func addBlockToMapping(parent *CandidateNode, block *hclsyntax.Block, src []byte, isMultipleBlocksOfType bool) {
+ bodyNode := hclBodyToNode(block.Body, src)
+ current := parent
+
+ // ensure block type mapping exists
+ var typeNode *CandidateNode
+ for i := 0; i < len(current.Content); i += 2 {
+ if current.Content[i].Value == block.Type {
+ typeNode = current.Content[i+1]
+ break
+ }
+ }
+ if typeNode == nil {
+ _, typeNode = current.AddKeyValueChild(createStringScalarNode(block.Type), &CandidateNode{Kind: MappingNode})
+ // Mark the type node if there are multiple blocks of this type at this level
+ // This tells the encoder to emit them as separate blocks rather than consolidating them
+ if isMultipleBlocksOfType {
+ typeNode.EncodeHint = EncodeHintSeparateBlock
+ }
+ }
+ current = typeNode
+
+ // walk labels, creating/merging mappings
+ for _, label := range block.Labels {
+ var next *CandidateNode
+ for i := 0; i < len(current.Content); i += 2 {
+ if current.Content[i].Value == label {
+ next = current.Content[i+1]
+ break
+ }
+ }
+ if next == nil {
+ _, next = current.AddKeyValueChild(createStringScalarNode(label), &CandidateNode{Kind: MappingNode})
+ }
+ current = next
+ }
+
+ // merge body attributes/blocks into the final mapping
+ for i := 0; i < len(bodyNode.Content); i += 2 {
+ current.AddKeyValueChild(bodyNode.Content[i], bodyNode.Content[i+1])
+ }
+}
+
+func convertHclExprToNode(expr hclsyntax.Expression, src []byte) *CandidateNode {
+ // handle literal values directly
+ switch e := expr.(type) {
+ case *hclsyntax.LiteralValueExpr:
+ v := e.Val
+ if v.IsNull() {
+ return createScalarNode(nil, "")
+ }
+ switch {
+ case v.Type().Equals(cty.String):
+ // prefer to extract exact source (to avoid extra quoting) when available
+ // Prefer the actual cty string value
+ s := v.AsString()
+ node := createScalarNode(s, s)
+ // Don't set style for regular quoted strings - let YAML handle naturally
+ return node
+ case v.Type().Equals(cty.Bool):
+ b := v.True()
+ return createScalarNode(b, strconv.FormatBool(b))
+ case v.Type() == cty.Number:
+ // prefer integers when the numeric value is integral
+ bf := v.AsBigFloat()
+ if bf == nil {
+ // fallback to string
+ return createStringScalarNode(v.GoString())
+ }
+ // check if bf represents an exact integer
+ if intVal, acc := bf.Int(nil); acc == big.Exact {
+ s := intVal.String()
+ return createScalarNode(intVal.Int64(), s)
+ }
+ s := bf.Text('g', -1)
+ return createScalarNode(0.0, s)
+ case v.Type().IsTupleType() || v.Type().IsListType() || v.Type().IsSetType():
+ seq := &CandidateNode{Kind: SequenceNode}
+ it := v.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ // convert cty.Value to a node by wrapping in literal expr via string representation
+ child := convertCtyValueToNode(val)
+ seq.AddChild(child)
+ }
+ return seq
+ case v.Type().IsMapType() || v.Type().IsObjectType():
+ m := &CandidateNode{Kind: MappingNode}
+ it := v.ElementIterator()
+ for it.Next() {
+ key, val := it.Element()
+ keyStr := key.AsString()
+ keyNode := createStringScalarNode(keyStr)
+ valNode := convertCtyValueToNode(val)
+ m.AddKeyValueChild(keyNode, valNode)
+ }
+ return m
+ default:
+ // fallback to string
+ s := v.GoString()
+ return createStringScalarNode(s)
+ }
+ case *hclsyntax.TupleConsExpr:
+ // parse tuple/list into YAML sequence
+ seq := &CandidateNode{Kind: SequenceNode}
+ for _, exprVal := range e.Exprs {
+ child := convertHclExprToNode(exprVal, src)
+ seq.AddChild(child)
+ }
+ return seq
+ case *hclsyntax.ObjectConsExpr:
+ // parse object into YAML mapping
+ m := &CandidateNode{Kind: MappingNode}
+ m.Style = FlowStyle // Mark as inline object (flow style) for encoder
+ for _, item := range e.Items {
+ // evaluate key expression to get the key string
+ keyVal, keyDiags := item.KeyExpr.Value(nil)
+ if keyDiags != nil && keyDiags.HasErrors() {
+ // fallback: try to extract key from source
+ r := item.KeyExpr.Range()
+ start := r.Start.Byte
+ end := r.End.Byte
+ if start >= 0 && end >= start && end <= len(src) {
+ keyNode := createStringScalarNode(strings.TrimSpace(string(src[start:end])))
+ valNode := convertHclExprToNode(item.ValueExpr, src)
+ m.AddKeyValueChild(keyNode, valNode)
+ }
+ continue
+ }
+ keyStr := keyVal.AsString()
+ keyNode := createStringScalarNode(keyStr)
+ valNode := convertHclExprToNode(item.ValueExpr, src)
+ m.AddKeyValueChild(keyNode, valNode)
+ }
+ return m
+ case *hclsyntax.TemplateExpr:
+ // Reconstruct template string, preserving ${} syntax for interpolations
+ var parts []string
+ for _, p := range e.Parts {
+ switch lp := p.(type) {
+ case *hclsyntax.LiteralValueExpr:
+ if lp.Val.Type().Equals(cty.String) {
+ parts = append(parts, lp.Val.AsString())
+ } else {
+ parts = append(parts, lp.Val.GoString())
+ }
+ default:
+ // Non-literal expression - reconstruct with ${} wrapper
+ r := p.Range()
+ start := r.Start.Byte
+ end := r.End.Byte
+ if start >= 0 && end >= start && end <= len(src) {
+ exprText := string(src[start:end])
+ parts = append(parts, "${"+exprText+"}")
+ } else {
+ parts = append(parts, fmt.Sprintf("${%v}", p))
+ }
+ }
+ }
+ combined := strings.Join(parts, "")
+ node := createScalarNode(combined, combined)
+ // Set DoubleQuotedStyle for all templates (which includes all quoted strings in HCL)
+ // This ensures HCL roundtrips preserve quotes, and YAML properly quotes strings with ${}
+ node.Style = DoubleQuotedStyle
+ return node
+ case *hclsyntax.ScopeTraversalExpr:
+ // Simple identifier/traversal (e.g. unquoted string literal in HCL)
+ r := e.Range()
+ start := r.Start.Byte
+ end := r.End.Byte
+ if start >= 0 && end >= start && end <= len(src) {
+ text := strings.TrimSpace(string(src[start:end]))
+ return createStringScalarNode(text)
+ }
+ // Fallback to root name if source unavailable
+ if len(e.Traversal) > 0 {
+ if root, ok := e.Traversal[0].(hcl.TraverseRoot); ok {
+ return createStringScalarNode(root.Name)
+ }
+ }
+ return createStringScalarNode("")
+ case *hclsyntax.FunctionCallExpr:
+ // Preserve function calls as raw expressions for roundtrip
+ r := e.Range()
+ start := r.Start.Byte
+ end := r.End.Byte
+ if start >= 0 && end >= start && end <= len(src) {
+ text := strings.TrimSpace(string(src[start:end]))
+ node := createStringScalarNode(text)
+ node.Style = 0
+ return node
+ }
+ node := createStringScalarNode(e.Name)
+ node.Style = 0
+ return node
+ default:
+ // try to evaluate the expression (handles unary, binary ops, etc.)
+ val, diags := expr.Value(nil)
+ if diags == nil || !diags.HasErrors() {
+ // successfully evaluated, convert cty.Value to node
+ return convertCtyValueToNode(val)
+ }
+ // fallback: extract source text for the expression
+ r := expr.Range()
+ start := r.Start.Byte
+ end := r.End.Byte
+ if start >= 0 && end >= start && end <= len(src) {
+ text := string(src[start:end])
+ // Mark as unquoted expression so encoder emits without quoting
+ node := createStringScalarNode(text)
+ node.Style = 0
+ return node
+ }
+ return createStringScalarNode(fmt.Sprintf("%v", expr))
+ }
+}
+
+func convertCtyValueToNode(v cty.Value) *CandidateNode {
+ if v.IsNull() {
+ return createScalarNode(nil, "")
+ }
+ switch {
+ case v.Type().Equals(cty.String):
+ return createScalarNode("", v.AsString())
+ case v.Type().Equals(cty.Bool):
+ b := v.True()
+ return createScalarNode(b, strconv.FormatBool(b))
+ case v.Type() == cty.Number:
+ bf := v.AsBigFloat()
+ if bf == nil {
+ return createStringScalarNode(v.GoString())
+ }
+ if intVal, acc := bf.Int(nil); acc == big.Exact {
+ s := intVal.String()
+ return createScalarNode(intVal.Int64(), s)
+ }
+ s := bf.Text('g', -1)
+ return createScalarNode(0.0, s)
+ case v.Type().IsTupleType() || v.Type().IsListType() || v.Type().IsSetType():
+ seq := &CandidateNode{Kind: SequenceNode}
+ it := v.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ seq.AddChild(convertCtyValueToNode(val))
+ }
+ return seq
+ case v.Type().IsMapType() || v.Type().IsObjectType():
+ m := &CandidateNode{Kind: MappingNode}
+ it := v.ElementIterator()
+ for it.Next() {
+ key, val := it.Element()
+ keyNode := createStringScalarNode(key.AsString())
+ valNode := convertCtyValueToNode(val)
+ m.AddKeyValueChild(keyNode, valNode)
+ }
+ return m
+ default:
+ return createStringScalarNode(v.GoString())
+ }
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_ini.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_ini.go
new file mode 100644
index 00000000000..159ca8b4a68
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_ini.go
@@ -0,0 +1,106 @@
+//go:build !yq_noini
+
+package yqlib
+
+import (
+ "fmt"
+ "io"
+
+ "github.com/go-ini/ini"
+)
+
+type iniDecoder struct {
+ reader io.Reader
+ finished bool // Flag to signal completion of processing
+}
+
+func NewINIDecoder() Decoder {
+ return &iniDecoder{
+ finished: false, // Initialise the flag as false
+ }
+}
+
+func (dec *iniDecoder) Init(reader io.Reader) error {
+ // Store the reader for use in Decode
+ dec.reader = reader
+ return nil
+}
+
+func (dec *iniDecoder) Decode() (*CandidateNode, error) {
+ // If processing is already finished, return io.EOF
+ if dec.finished {
+ return nil, io.EOF
+ }
+
+ // Read all content from the stored reader
+ content, err := io.ReadAll(dec.reader)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read INI content: %w", err)
+ }
+
+ // Parse the INI content
+ cfg, err := ini.Load(content)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse INI content: %w", err)
+ }
+
+ // Create a root CandidateNode as a MappingNode (since INI is key-value based)
+ root := &CandidateNode{
+ Kind: MappingNode,
+ Tag: "!!map",
+ Value: "",
+ }
+
+ // Process each section in the INI file
+ for _, section := range cfg.Sections() {
+ sectionName := section.Name()
+
+ if sectionName == ini.DefaultSection {
+ // For the default section, add key-value pairs directly to the root node
+ for _, key := range section.Keys() {
+ keyName := key.Name()
+ keyValue := key.String()
+
+ // Create a key node (scalar for the key name)
+ keyNode := createStringScalarNode(keyName)
+ // Create a value node (scalar for the value)
+ valueNode := createStringScalarNode(keyValue)
+
+ // Add key-value pair to the root node
+ root.AddKeyValueChild(keyNode, valueNode)
+ }
+ } else {
+ // For named sections, create a nested map
+ sectionNode := &CandidateNode{
+ Kind: MappingNode,
+ Tag: "!!map",
+ Value: "",
+ }
+
+ // Add key-value pairs to the section node
+ for _, key := range section.Keys() {
+ keyName := key.Name()
+ keyValue := key.String()
+
+ // Create a key node (scalar for the key name)
+ keyNode := createStringScalarNode(keyName)
+ // Create a value node (scalar for the value)
+ valueNode := createStringScalarNode(keyValue)
+
+ // Add key-value pair to the section node
+ sectionNode.AddKeyValueChild(keyNode, valueNode)
+ }
+
+ // Create a key node for the section name
+ sectionKeyNode := createStringScalarNode(sectionName)
+ // Add the section as a nested map to the root node
+ root.AddKeyValueChild(sectionKeyNode, sectionNode)
+ }
+ }
+
+ // Set the finished flag to true to prevent further Decode calls
+ dec.finished = true
+
+ // Return the root node
+ return root, nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go
index 778ba7eaa08..4acbdf95342 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go
@@ -1,3 +1,5 @@
+//go:build !yq_noprops
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go
index ca193cf19bb..a3e3a831765 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go
@@ -8,16 +8,19 @@ import (
"fmt"
"io"
"strconv"
+ "strings"
"time"
toml "github.com/pelletier/go-toml/v2/unstable"
)
type tomlDecoder struct {
- parser toml.Parser
- finished bool
- d DataTreeNavigator
- rootMap *CandidateNode
+ parser toml.Parser
+ finished bool
+ d DataTreeNavigator
+ rootMap *CandidateNode
+ pendingComments []string // Head comments collected from Comment nodes
+ firstContentSeen bool // Track if we've processed the first non-comment node
}
func NewTomlDecoder() Decoder {
@@ -28,7 +31,7 @@ func NewTomlDecoder() Decoder {
}
func (dec *tomlDecoder) Init(reader io.Reader) error {
- dec.parser = toml.Parser{}
+ dec.parser = toml.Parser{KeepComments: true}
buf := new(bytes.Buffer)
_, err := buf.ReadFrom(reader)
if err != nil {
@@ -39,9 +42,24 @@ func (dec *tomlDecoder) Init(reader io.Reader) error {
Kind: MappingNode,
Tag: "!!map",
}
+ dec.pendingComments = make([]string, 0)
+ dec.firstContentSeen = false
+ dec.finished = false
return nil
}
+func (dec *tomlDecoder) attachOrphanedCommentsToNode(tableNodeValue *CandidateNode) {
+ if len(dec.pendingComments) > 0 {
+ comments := strings.Join(dec.pendingComments, "\n")
+ if tableNodeValue.HeadComment == "" {
+ tableNodeValue.HeadComment = comments
+ } else {
+ tableNodeValue.HeadComment = tableNodeValue.HeadComment + "\n" + comments
+ }
+ dec.pendingComments = make([]string, 0)
+ }
+}
+
func (dec *tomlDecoder) getFullPath(tomlNode *toml.Node) []interface{} {
path := make([]interface{}, 0)
for {
@@ -56,13 +74,24 @@ func (dec *tomlDecoder) getFullPath(tomlNode *toml.Node) []interface{} {
func (dec *tomlDecoder) processKeyValueIntoMap(rootMap *CandidateNode, tomlNode *toml.Node) error {
value := tomlNode.Value()
path := dec.getFullPath(value.Next())
- log.Debug("processKeyValueIntoMap: %v", path)
valueNode, err := dec.decodeNode(value)
if err != nil {
return err
}
+ // Attach pending head comments
+ if len(dec.pendingComments) > 0 {
+ valueNode.HeadComment = strings.Join(dec.pendingComments, "\n")
+ dec.pendingComments = make([]string, 0)
+ }
+
+ // Check for inline comment chained to the KeyValue node
+ nextNode := tomlNode.Next()
+ if nextNode != nil && nextNode.Kind == toml.Comment {
+ valueNode.LineComment = string(nextNode.Data)
+ }
+
context := Context{}
context = context.SingleChildContext(rootMap)
@@ -77,15 +106,19 @@ func (dec *tomlDecoder) decodeKeyValuesIntoMap(rootMap *CandidateNode, tomlNode
for dec.parser.NextExpression() {
nextItem := dec.parser.Expression()
- log.Debug("decodeKeyValuesIntoMap -- next exp, its a %v", nextItem.Kind)
+ log.Debugf("decodeKeyValuesIntoMap -- next exp, its a %v", nextItem.Kind)
- if nextItem.Kind == toml.KeyValue {
+ switch nextItem.Kind {
+ case toml.KeyValue:
if err := dec.processKeyValueIntoMap(rootMap, nextItem); err != nil {
return false, err
}
- } else {
+ case toml.Comment:
+ // Standalone comment - add to pending for next element
+ dec.pendingComments = append(dec.pendingComments, string(nextItem.Data))
+ default:
// run out of key values
- log.Debug("done in decodeKeyValuesIntoMap, gota a %v", nextItem.Kind)
+ log.Debugf("done in decodeKeyValuesIntoMap, gota a %v", nextItem.Kind)
return true, nil
}
}
@@ -117,21 +150,39 @@ func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*CandidateNod
}
return &CandidateNode{
- Kind: MappingNode,
- Tag: "!!map",
- Content: content,
+ Kind: MappingNode,
+ Tag: "!!map",
+ EncodeHint: EncodeHintInline,
+ Content: content,
}, nil
}
func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*CandidateNode, error) {
content := make([]*CandidateNode, 0)
+ var pendingArrayComments []string
+
iterator := tomlNode.Children()
for iterator.Next() {
child := iterator.Node()
+
+ // Handle comments within arrays
+ if child.Kind == toml.Comment {
+ // Collect comments to attach to the next array element
+ pendingArrayComments = append(pendingArrayComments, string(child.Data))
+ continue
+ }
+
yamlNode, err := dec.decodeNode(child)
if err != nil {
return nil, err
}
+
+ // Attach any pending comments to this array element
+ if len(pendingArrayComments) > 0 {
+ yamlNode.HeadComment = strings.Join(pendingArrayComments, "\n")
+ pendingArrayComments = make([]string, 0)
+ }
+
content = append(content, yamlNode)
}
@@ -221,7 +272,7 @@ func (dec *tomlDecoder) Decode() (*CandidateNode, error) {
currentNode := dec.parser.Expression()
- log.Debug("currentNode: %v ", currentNode.Kind)
+ log.Debugf("currentNode: %v ", currentNode.Kind)
runAgainstCurrentExp, err = dec.processTopLevelNode(currentNode)
if err != nil {
return dec.rootMap, err
@@ -248,51 +299,102 @@ func (dec *tomlDecoder) Decode() (*CandidateNode, error) {
func (dec *tomlDecoder) processTopLevelNode(currentNode *toml.Node) (bool, error) {
var runAgainstCurrentExp bool
var err error
- log.Debug("processTopLevelNode: Going to process %v state is current %v", currentNode.Kind, NodeToString(dec.rootMap))
- if currentNode.Kind == toml.Table {
+ log.Debugf("processTopLevelNode: Going to process %v state is current %v", currentNode.Kind, NodeToString(dec.rootMap))
+ switch currentNode.Kind {
+ case toml.Comment:
+ // Collect comment to attach to next element
+ commentText := string(currentNode.Data)
+ // If we haven't seen any content yet, accumulate comments for root
+ if !dec.firstContentSeen {
+ if dec.rootMap.HeadComment == "" {
+ dec.rootMap.HeadComment = commentText
+ } else {
+ dec.rootMap.HeadComment = dec.rootMap.HeadComment + "\n" + commentText
+ }
+ } else {
+ // We've seen content, so these comments are for the next element
+ dec.pendingComments = append(dec.pendingComments, commentText)
+ }
+ return false, nil
+ case toml.Table:
+ dec.firstContentSeen = true
runAgainstCurrentExp, err = dec.processTable(currentNode)
- } else if currentNode.Kind == toml.ArrayTable {
+ case toml.ArrayTable:
+ dec.firstContentSeen = true
runAgainstCurrentExp, err = dec.processArrayTable(currentNode)
- } else {
+ default:
+ dec.firstContentSeen = true
runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(dec.rootMap, currentNode)
}
- log.Debug("processTopLevelNode: DONE Processing state is now %v", NodeToString(dec.rootMap))
+ log.Debugf("processTopLevelNode: DONE Processing state is now %v", NodeToString(dec.rootMap))
return runAgainstCurrentExp, err
}
func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
log.Debug("Enter processTable")
- fullPath := dec.getFullPath(currentNode.Child())
- log.Debug("fullpath: %v", fullPath)
+ child := currentNode.Child()
+ fullPath := dec.getFullPath(child)
+ log.Debugf("fullpath: %v", fullPath)
+
+ c := Context{}
+ c = c.SingleChildContext(dec.rootMap)
+
+ fullPath, err := getPathToUse(fullPath, dec, c)
+ if err != nil {
+ return false, err
+ }
tableNodeValue := &CandidateNode{
- Kind: MappingNode,
- Tag: "!!map",
- Content: make([]*CandidateNode, 0),
+ Kind: MappingNode,
+ Tag: "!!map",
+ Content: make([]*CandidateNode, 0),
+ EncodeHint: EncodeHintSeparateBlock,
+ }
+
+ // Attach pending head comments to the table
+ if len(dec.pendingComments) > 0 {
+ tableNodeValue.HeadComment = strings.Join(dec.pendingComments, "\n")
+ dec.pendingComments = make([]string, 0)
}
var tableValue *toml.Node
runAgainstCurrentExp := false
- var err error
- hasValue := dec.parser.NextExpression()
- // check to see if there is any table data
- if hasValue {
+ sawKeyValue := false
+ for dec.parser.NextExpression() {
tableValue = dec.parser.Expression()
- // next expression is not table data, so we are done
+ // Allow standalone comments inside the table before the first key-value.
+ // These should be associated with the next element in the table (usually the first key-value),
+ // not treated as "end of table" (which would cause subsequent key-values to be parsed at root).
+ if tableValue.Kind == toml.Comment {
+ dec.pendingComments = append(dec.pendingComments, string(tableValue.Data))
+ continue
+ }
+
+ // next expression is not table data, so we are done (but we need to re-process it at top-level)
if tableValue.Kind != toml.KeyValue {
- log.Debug("got an empty table, returning")
- return true, nil
+ log.Debug("got an empty table (or reached next section)")
+ // If the table had only comments, attach them to the table itself so they don't leak to the next node.
+ if !sawKeyValue {
+ dec.attachOrphanedCommentsToNode(tableNodeValue)
+ }
+ runAgainstCurrentExp = true
+ break
}
+ sawKeyValue = true
runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(tableNodeValue, tableValue)
if err != nil && !errors.Is(err, io.EOF) {
return false, err
}
+ break
+ }
+ // If we hit EOF after only seeing comments inside this table, attach them to the table itself
+ // so they don't leak to whatever comes next.
+ if !sawKeyValue {
+ dec.attachOrphanedCommentsToNode(tableNodeValue)
}
- c := Context{}
- c = c.SingleChildContext(dec.rootMap)
err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue)
if err != nil {
return false, err
@@ -301,7 +403,7 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
}
func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *CandidateNode) error {
- log.Debug("arrayAppend to path: %v,%v", path, NodeToString(rhsNode))
+ log.Debugf("arrayAppend to path: %v,%v", path, NodeToString(rhsNode))
rhsCandidateNode := &CandidateNode{
Kind: SequenceNode,
Tag: "!!seq",
@@ -323,35 +425,130 @@ func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode
}
func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error) {
- log.Debug("Entering processArrayTable")
- fullPath := dec.getFullPath(currentNode.Child())
- log.Debug("Fullpath: %v", fullPath)
+ log.Debug("Enter processArrayTable")
+ child := currentNode.Child()
+ fullPath := dec.getFullPath(child)
+ log.Debugf("Fullpath: %v", fullPath)
+
+ c := Context{}
+ c = c.SingleChildContext(dec.rootMap)
+
+ fullPath, err := getPathToUse(fullPath, dec, c)
+ if err != nil {
+ return false, err
+ }
// need to use the array append exp to add another entry to
// this array: fullpath += [ thing ]
-
hasValue := dec.parser.NextExpression()
- if !hasValue {
- return false, fmt.Errorf("error retrieving table %v value: %w", fullPath, dec.parser.Error())
- }
tableNodeValue := &CandidateNode{
- Kind: MappingNode,
- Tag: "!!map",
+ Kind: MappingNode,
+ Tag: "!!map",
+ EncodeHint: EncodeHintSeparateBlock,
}
- tableValue := dec.parser.Expression()
- runAgainstCurrentExp, err := dec.decodeKeyValuesIntoMap(tableNodeValue, tableValue)
- log.Debugf("table node err: %w", err)
- if err != nil && !errors.Is(err, io.EOF) {
- return false, err
+ // Attach pending head comments to the array table
+ if len(dec.pendingComments) > 0 {
+ tableNodeValue.HeadComment = strings.Join(dec.pendingComments, "\n")
+ dec.pendingComments = make([]string, 0)
}
- c := Context{}
- c = c.SingleChildContext(dec.rootMap)
+ runAgainstCurrentExp := false
+ sawKeyValue := false
+ if hasValue {
+ for {
+ exp := dec.parser.Expression()
+ // Allow standalone comments inside array tables before the first key-value.
+ if exp.Kind == toml.Comment {
+ dec.pendingComments = append(dec.pendingComments, string(exp.Data))
+ hasValue = dec.parser.NextExpression()
+ if !hasValue {
+ break
+ }
+ continue
+ }
+
+ // if the next value is a ArrayTable or Table, then its not part of this declaration (not a key value pair)
+ // so lets leave that expression for the next round of parsing
+ if exp.Kind == toml.ArrayTable || exp.Kind == toml.Table {
+ // If this array-table entry had only comments, attach them to the entry so they don't leak.
+ if !sawKeyValue {
+ dec.attachOrphanedCommentsToNode(tableNodeValue)
+ }
+ runAgainstCurrentExp = true
+ break
+ }
+
+ sawKeyValue = true
+ // otherwise, if there is a value, it must be some key value pairs of the
+ // first object in the array!
+ runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(tableNodeValue, exp)
+ if err != nil && !errors.Is(err, io.EOF) {
+ return false, err
+ }
+ break
+ }
+ }
+ // If we hit EOF after only seeing comments inside this array-table entry, attach them to the entry
+ // so they don't leak to whatever comes next.
+ if !sawKeyValue && len(dec.pendingComments) > 0 {
+ comments := strings.Join(dec.pendingComments, "\n")
+ if tableNodeValue.HeadComment == "" {
+ tableNodeValue.HeadComment = comments
+ } else {
+ tableNodeValue.HeadComment = tableNodeValue.HeadComment + "\n" + comments
+ }
+ dec.pendingComments = make([]string, 0)
+ }
// += function
err = dec.arrayAppend(c, fullPath, tableNodeValue)
return runAgainstCurrentExp, err
}
+
+// if fullPath points to an array of maps rather than a map
+// then it should set this element into the _last_ element of that array.
+// Because TOML. So we'll inject the last index into the path.
+
+func getPathToUse(fullPath []interface{}, dec *tomlDecoder, c Context) ([]interface{}, error) {
+ // We need to check the entire path (except the last element), not just the immediate parent,
+ // because we may have nested array tables like [[array.subarray.subsubarray]]
+ // where both 'array' and 'subarray' are arrays that already exist.
+
+ if len(fullPath) == 0 {
+ return fullPath, nil
+ }
+
+ resultPath := make([]interface{}, 0, len(fullPath)*2) // preallocate with extra space for indices
+
+ // Process all segments except the last one
+ for i := 0; i < len(fullPath)-1; i++ {
+ resultPath = append(resultPath, fullPath[i])
+
+ // Check if the current path segment points to an array
+ readOp := createTraversalTree(resultPath, traversePreferences{DontAutoCreate: true}, false)
+ resultContext, err := dec.d.GetMatchingNodes(c, readOp)
+ if err != nil {
+ return nil, err
+ }
+
+ if resultContext.MatchingNodes.Len() >= 1 {
+ match := resultContext.MatchingNodes.Front().Value.(*CandidateNode)
+ // If this segment points to an array, we need to add the last index
+ // before continuing with the rest of the path
+ if match.Kind == SequenceNode && len(match.Content) > 0 {
+ lastIndex := len(match.Content) - 1
+ resultPath = append(resultPath, lastIndex)
+ log.Debugf("Path segment %v is an array, injecting index %d", resultPath[:len(resultPath)-1], lastIndex)
+ }
+ }
+ }
+
+ // Add the last segment
+ resultPath = append(resultPath, fullPath[len(fullPath)-1])
+
+ log.Debugf("getPathToUse: original path %v -> result path %v", fullPath, resultPath)
+ return resultPath, nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go
index cd08d23c579..ad6a52d8c89 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go
@@ -1,3 +1,5 @@
+//go:build !yq_nouri
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go
index 99626bd307f..841519b025a 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go
@@ -64,7 +64,7 @@ func (dec *xmlDecoder) processComment(c string) string {
}
func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
- log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
+ log.Debugf("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
yamlNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
if len(n.Data) > 0 {
@@ -92,7 +92,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
log.Debugf("label=%v, i=%v, keyValuePair.FootComment: %v", label, i, keyValuePair.FootComment)
labelNode.FootComment = dec.processComment(keyValuePair.FootComment)
- log.Debug("len of children in %v is %v", label, len(children))
+ log.Debugf("len of children in %v is %v", label, len(children))
if len(children) > 1 {
valueNode, err = dec.createSequence(children)
if err != nil {
@@ -105,7 +105,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
if len(children[0].Children) == 0 && children[0].HeadComment != "" {
if len(children[0].Data) > 0 {
- log.Debug("scalar comment hack, currentlabel [%v]", labelNode.HeadComment)
+ log.Debugf("scalar comment hack, currentlabel [%v]", labelNode.HeadComment)
labelNode.HeadComment = joinComments([]string{labelNode.HeadComment, strings.TrimSpace(children[0].HeadComment)}, "\n")
children[0].HeadComment = ""
} else {
@@ -151,7 +151,7 @@ func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
scalar := dec.createValueNodeFromData(n.Data)
- log.Debug("scalar (%v), headC: %v, lineC: %v, footC: %v", scalar.Tag, n.HeadComment, n.LineComment, n.FootComment)
+ log.Debugf("scalar (%v), headC: %v, lineC: %v, footC: %v", scalar.Tag, n.HeadComment, n.LineComment, n.FootComment)
scalar.HeadComment = dec.processComment(n.HeadComment)
scalar.LineComment = dec.processComment(n.LineComment)
if scalar.Tag == "!!seq" {
@@ -211,17 +211,17 @@ func (n *xmlNode) AddChild(s string, c *xmlNode) {
if n.Children == nil {
n.Children = make([]*xmlChildrenKv, 0)
}
- log.Debug("looking for %s", s)
+ log.Debugf("looking for %s", s)
// see if we can find an existing entry to add to
for _, childEntry := range n.Children {
if childEntry.K == s {
- log.Debug("found it, appending an entry%s", s)
+ log.Debugf("found it, appending an entry%s", s)
childEntry.V = append(childEntry.V, c)
- log.Debug("yay len of children in %v is %v", s, len(childEntry.V))
+ log.Debugf("yay len of children in %v is %v", s, len(childEntry.V))
return
}
}
- log.Debug("not there, making a new one %s", s)
+ log.Debugf("not there, making a new one %s", s)
n.Children = append(n.Children, &xmlChildrenKv{K: s, V: []*xmlNode{c}})
}
@@ -267,13 +267,19 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
switch se := t.(type) {
case xml.StartElement:
- log.Debug("start element %v", se.Name.Local)
+ log.Debugf("start element %v", se.Name.Local)
elem.state = "started"
// Build new a new current element and link it to its parent
+ var label = se.Name.Local
+ if dec.prefs.KeepNamespace {
+ if se.Name.Space != "" {
+ label = se.Name.Space + ":" + se.Name.Local
+ }
+ }
elem = &element{
parent: elem,
n: &xmlNode{},
- label: se.Name.Local,
+ label: label,
}
// Extract attributes as children
@@ -296,14 +302,14 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
if len(newBit) > 0 {
elem.n.Data = append(elem.n.Data, newBit)
elem.state = "chardata"
- log.Debug("chardata [%v] for %v", elem.n.Data, elem.label)
+ log.Debugf("chardata [%v] for %v", elem.n.Data, elem.label)
}
case xml.EndElement:
if elem == nil {
log.Debug("no element, probably bad xml")
continue
}
- log.Debug("end element %v", elem.label)
+ log.Debugf("end element %v", elem.label)
elem.state = "finished"
// And add it to its parent list
if elem.parent != nil {
@@ -315,14 +321,15 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
case xml.Comment:
commentStr := string(xml.CharData(se))
- if elem.state == "started" {
+ switch elem.state {
+ case "started":
applyFootComment(elem, commentStr)
- } else if elem.state == "chardata" {
- log.Debug("got a line comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
+ case "chardata":
+ log.Debugf("got a line comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
elem.n.LineComment = joinComments([]string{elem.n.LineComment, commentStr}, " ")
- } else {
- log.Debug("got a head comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
+ default:
+ log.Debugf("got a head comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
elem.n.HeadComment = joinComments([]string{elem.n.HeadComment, commentStr}, " ")
}
@@ -347,7 +354,7 @@ func applyFootComment(elem *element, commentStr string) {
if len(elem.n.Children) > 0 {
lastChildIndex := len(elem.n.Children) - 1
childKv := elem.n.Children[lastChildIndex]
- log.Debug("got a foot comment, putting on last child for %v: [%v]", childKv.K, commentStr)
+ log.Debugf("got a foot comment, putting on last child for %v: [%v]", childKv.K, commentStr)
// if it's an array of scalars, put the foot comment on the scalar itself
if len(childKv.V) > 0 && len(childKv.V[0].Children) == 0 {
nodeToUpdate := childKv.V[len(childKv.V)-1]
@@ -356,7 +363,7 @@ func applyFootComment(elem *element, commentStr string) {
childKv.FootComment = joinComments([]string{elem.n.FootComment, commentStr}, " ")
}
} else {
- log.Debug("got a foot comment for %v: [%v]", elem.label, commentStr)
+ log.Debugf("got a foot comment for %v: [%v]", elem.label, commentStr)
elem.n.FootComment = joinComments([]string{elem.n.FootComment, commentStr}, " ")
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go
index c17f9029152..98ddf2634e0 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go
@@ -8,7 +8,14 @@ import (
"regexp"
"strings"
- yaml "gopkg.in/yaml.v3"
+ yaml "go.yaml.in/yaml/v4"
+)
+
+var (
+ commentLineRe = regexp.MustCompile(`^\s*#`)
+ yamlDirectiveLineRe = regexp.MustCompile(`^\s*%YAML`)
+ separatorLineRe = regexp.MustCompile(`^\s*---\s*$`)
+ separatorPrefixRe = regexp.MustCompile(`^\s*---\s+`)
)
type yamlDecoder struct {
@@ -33,51 +40,72 @@ func NewYamlDecoder(prefs YamlPreferences) Decoder {
}
func (dec *yamlDecoder) processReadStream(reader *bufio.Reader) (io.Reader, string, error) {
- var commentLineRegEx = regexp.MustCompile(`^\s*#`)
- var yamlDirectiveLineRegEx = regexp.MustCompile(`^\s*%YA`)
var sb strings.Builder
+
for {
- peekBytes, err := reader.Peek(4)
- if errors.Is(err, io.EOF) {
- // EOF are handled else where..
+ line, err := reader.ReadString('\n')
+ if errors.Is(err, io.EOF) && line == "" {
+ // no more data
return reader, sb.String(), nil
- } else if err != nil {
+ }
+ if err != nil && !errors.Is(err, io.EOF) {
return reader, sb.String(), err
- } else if string(peekBytes[0]) == "\n" {
- _, err := reader.ReadString('\n')
- sb.WriteString("\n")
+ }
+
+ // Determine newline style and strip it for inspection
+ newline := ""
+ if strings.HasSuffix(line, "\r\n") {
+ newline = "\r\n"
+ line = strings.TrimSuffix(line, "\r\n")
+ } else if strings.HasSuffix(line, "\n") {
+ newline = "\n"
+ line = strings.TrimSuffix(line, "\n")
+ }
+
+ trimmed := strings.TrimSpace(line)
+
+ // Document separator: exact line '---' or a '--- ' prefix followed by content
+ if separatorLineRe.MatchString(trimmed) {
+ sb.WriteString("$yqDocSeparator$")
+ sb.WriteString(newline)
if errors.Is(err, io.EOF) {
return reader, sb.String(), nil
- } else if err != nil {
- return reader, sb.String(), err
}
- } else if string(peekBytes) == "--- " {
- _, err := reader.ReadString(' ')
- sb.WriteString("$yqDocSeparator$\n")
- if errors.Is(err, io.EOF) {
- return reader, sb.String(), nil
- } else if err != nil {
- return reader, sb.String(), err
+ continue
+ }
+
+ // Handle lines that start with '--- ' followed by more content (e.g. '--- cat')
+ if separatorPrefixRe.MatchString(line) {
+ match := separatorPrefixRe.FindString(line)
+ remainder := line[len(match):]
+ // normalise separator newline: if original had none, default to LF
+ sepNewline := newline
+ if sepNewline == "" {
+ sepNewline = "\n"
}
- } else if string(peekBytes) == "---\n" {
- _, err := reader.ReadString('\n')
- sb.WriteString("$yqDocSeparator$\n")
- if errors.Is(err, io.EOF) {
+ sb.WriteString("$yqDocSeparator$")
+ sb.WriteString(sepNewline)
+ // push the remainder back onto the reader and continue processing
+ reader = bufio.NewReader(io.MultiReader(strings.NewReader(remainder), reader))
+ if errors.Is(err, io.EOF) && remainder == "" {
return reader, sb.String(), nil
- } else if err != nil {
- return reader, sb.String(), err
}
- } else if commentLineRegEx.MatchString(string(peekBytes)) || yamlDirectiveLineRegEx.MatchString(string(peekBytes)) {
- line, err := reader.ReadString('\n')
+ continue
+ }
+
+ // Comments, YAML directives, and blank lines are leading content
+ if commentLineRe.MatchString(line) || yamlDirectiveLineRe.MatchString(line) || trimmed == "" {
sb.WriteString(line)
+ sb.WriteString(newline)
if errors.Is(err, io.EOF) {
return reader, sb.String(), nil
- } else if err != nil {
- return reader, sb.String(), err
}
- } else {
- return reader, sb.String(), nil
+ continue
}
+
+ // First non-leading line: push it back onto a reader and return
+ originalLine := line + newline
+ return io.MultiReader(strings.NewReader(originalLine), reader), sb.String(), nil
}
}
@@ -129,6 +157,8 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
return nil, err
} else if err != nil {
return nil, err
+ } else if len(yamlNode.Content) == 0 {
+ return nil, errors.New("yaml node has no content")
}
candidateNode := CandidateNode{document: dec.documentIndex}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go
index ee63fd47a2d..2fcc66a2947 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go
@@ -1,7 +1,12 @@
package yqlib
import (
+ "bufio"
+ "errors"
"io"
+ "strings"
+
+ "github.com/fatih/color"
)
type Encoder interface {
@@ -25,3 +30,63 @@ func mapKeysToStrings(node *CandidateNode) {
mapKeysToStrings(child)
}
}
+
+// Some funcs are shared between encoder_yaml and encoder_kyaml
+func PrintYAMLDocumentSeparator(writer io.Writer, PrintDocSeparators bool) error {
+ if PrintDocSeparators {
+ log.Debug("writing doc sep")
+ if err := writeString(writer, "---\n"); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+func PrintYAMLLeadingContent(writer io.Writer, content string, PrintDocSeparators bool, ColorsEnabled bool) error {
+ reader := bufio.NewReader(strings.NewReader(content))
+
+ // reuse precompiled package-level regex
+ // (declared in decoder_yaml.go)
+
+ for {
+
+ readline, errReading := reader.ReadString('\n')
+ if errReading != nil && !errors.Is(errReading, io.EOF) {
+ return errReading
+ }
+ if strings.Contains(readline, "$yqDocSeparator$") {
+ // Preserve the original line ending (CRLF or LF)
+ lineEnding := "\n"
+ if strings.HasSuffix(readline, "\r\n") {
+ lineEnding = "\r\n"
+ }
+ if PrintDocSeparators {
+ if err := writeString(writer, "---"+lineEnding); err != nil {
+ return err
+ }
+ }
+
+ } else {
+ if len(readline) > 0 && readline != "\n" && readline[0] != '%' && !commentLineRe.MatchString(readline) {
+ readline = "# " + readline
+ }
+ if ColorsEnabled && strings.TrimSpace(readline) != "" {
+ readline = format(color.FgHiBlack) + readline + format(color.Reset)
+ }
+ if err := writeString(writer, readline); err != nil {
+ return err
+ }
+ }
+
+ if errors.Is(errReading, io.EOF) {
+ if readline != "" {
+ // the last comment we read didn't have a newline, put one in
+ if err := writeString(writer, "\n"); err != nil {
+ return err
+ }
+ }
+ break
+ }
+ }
+
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go
index 11ef5a253b5..cfefbcd0493 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go
@@ -1,3 +1,5 @@
+//go:build !yq_nobase64
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go
index 1fa4354c19d..332f2699606 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go
@@ -1,3 +1,5 @@
+//go:build !yq_nocsv
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_hcl.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_hcl.go
new file mode 100644
index 00000000000..f592b81dc9d
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_hcl.go
@@ -0,0 +1,690 @@
+//go:build !yq_nohcl
+
+package yqlib
+
+import (
+ "fmt"
+ "io"
+ "regexp"
+ "strings"
+
+ "github.com/fatih/color"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ hclwrite "github.com/hashicorp/hcl/v2/hclwrite"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type hclEncoder struct {
+ prefs HclPreferences
+}
+
+// commentPathSep is used to join path segments when collecting comments.
+// It uses a rarely used ASCII control character to avoid collisions with
+// normal key names (including dots).
+const commentPathSep = "\x1e"
+
+// NewHclEncoder creates a new HCL encoder
+func NewHclEncoder(prefs HclPreferences) Encoder {
+ return &hclEncoder{prefs: prefs}
+}
+
+func (he *hclEncoder) CanHandleAliases() bool {
+ return false
+}
+
+func (he *hclEncoder) PrintDocumentSeparator(_ io.Writer) error {
+ return nil
+}
+
+func (he *hclEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
+ return nil
+}
+
+func (he *hclEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ log.Debugf("I need to encode %v", NodeToString(node))
+ if node.Kind == ScalarNode {
+ return writeString(writer, node.Value+"\n")
+ }
+
+ f := hclwrite.NewEmptyFile()
+ body := f.Body()
+
+ // Collect comments as we encode
+ commentMap := make(map[string]string)
+ he.collectComments(node, "", commentMap)
+
+ if err := he.encodeNode(body, node); err != nil {
+ return fmt.Errorf("failed to encode HCL: %w", err)
+ }
+
+ // Get the formatted output and remove extra spacing before '='
+ output := f.Bytes()
+ compactOutput := he.compactSpacing(output)
+
+ // Inject comments back into the output
+ finalOutput := he.injectComments(compactOutput, commentMap)
+
+ if he.prefs.ColorsEnabled {
+ colourized := he.colorizeHcl(finalOutput)
+ _, err := writer.Write(colourized)
+ return err
+ }
+
+ _, err := writer.Write(finalOutput)
+ return err
+}
+
+// compactSpacing removes extra whitespace before '=' in attribute assignments
+func (he *hclEncoder) compactSpacing(input []byte) []byte {
+ // Use regex to replace multiple spaces before = with single space
+ re := regexp.MustCompile(`(\S)\s{2,}=`)
+ return re.ReplaceAll(input, []byte("$1 ="))
+}
+
+// collectComments recursively collects comments from nodes for later injection
+func (he *hclEncoder) collectComments(node *CandidateNode, prefix string, commentMap map[string]string) {
+ if node == nil {
+ return
+ }
+
+ // For mapping nodes, collect comments from keys and values
+ if node.Kind == MappingNode {
+ // Collect root-level head comment if at root (prefix is empty)
+ if prefix == "" && node.HeadComment != "" {
+ commentMap[joinCommentPath("__root__", "head")] = node.HeadComment
+ }
+
+ for i := 0; i < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valueNode := node.Content[i+1]
+ key := keyNode.Value
+
+ // Create a path for this key
+ path := joinCommentPath(prefix, key)
+
+ // Store comments from the key (head comments appear before the attribute)
+ if keyNode.HeadComment != "" {
+ commentMap[joinCommentPath(path, "head")] = keyNode.HeadComment
+ }
+ // Store comments from the value (line comments appear after the value)
+ if valueNode.LineComment != "" {
+ commentMap[joinCommentPath(path, "line")] = valueNode.LineComment
+ }
+ if valueNode.FootComment != "" {
+ commentMap[joinCommentPath(path, "foot")] = valueNode.FootComment
+ }
+
+ // Recurse into nested mappings
+ if valueNode.Kind == MappingNode {
+ he.collectComments(valueNode, path, commentMap)
+ }
+ }
+ }
+}
+
+// joinCommentPath concatenates path segments using commentPathSep, safely handling empty prefixes.
+func joinCommentPath(prefix, segment string) string {
+ if prefix == "" {
+ return segment
+ }
+ return prefix + commentPathSep + segment
+}
+
+// injectComments adds collected comments back into the HCL output
+func (he *hclEncoder) injectComments(output []byte, commentMap map[string]string) []byte {
+ // Convert output to string for easier manipulation
+ result := string(output)
+
+ // Root-level head comment (stored on the synthetic __root__/head path)
+ for path, comment := range commentMap {
+ if path == joinCommentPath("__root__", "head") {
+ trimmed := strings.TrimSpace(comment)
+ if trimmed != "" && !strings.HasPrefix(result, trimmed) {
+ result = trimmed + "\n" + result
+ }
+ }
+ }
+
+ // Attribute head comments: insert above matching assignment
+ for path, comment := range commentMap {
+ parts := strings.Split(path, commentPathSep)
+ if len(parts) < 2 {
+ continue
+ }
+
+ commentType := parts[len(parts)-1]
+ key := parts[len(parts)-2]
+ if commentType != "head" || key == "" {
+ continue
+ }
+
+ trimmed := strings.TrimSpace(comment)
+ if trimmed == "" {
+ continue
+ }
+
+ re := regexp.MustCompile(`(?m)^(\s*)` + regexp.QuoteMeta(key) + `\s*=`)
+ if re.MatchString(result) {
+ result = re.ReplaceAllString(result, "$1"+trimmed+"\n$0")
+ }
+ }
+
+ return []byte(result)
+}
+
+func (he *hclEncoder) colorizeHcl(input []byte) []byte {
+ hcl := string(input)
+ result := strings.Builder{}
+
+ // Create colour functions for different token types
+ commentColor := color.New(color.FgHiBlack).SprintFunc()
+ stringColor := color.New(color.FgGreen).SprintFunc()
+ numberColor := color.New(color.FgHiMagenta).SprintFunc()
+ keyColor := color.New(color.FgCyan).SprintFunc()
+ boolColor := color.New(color.FgHiMagenta).SprintFunc()
+
+ // Simple tokenization for HCL colouring
+ i := 0
+ for i < len(hcl) {
+ ch := hcl[i]
+
+ // Comments - from # to end of line
+ if ch == '#' {
+ end := i
+ for end < len(hcl) && hcl[end] != '\n' {
+ end++
+ }
+ result.WriteString(commentColor(hcl[i:end]))
+ i = end
+ continue
+ }
+
+ // Strings - quoted text
+ if ch == '"' || ch == '\'' {
+ quote := ch
+ end := i + 1
+ for end < len(hcl) && hcl[end] != quote {
+ if hcl[end] == '\\' {
+ end++ // skip escaped char
+ }
+ end++
+ }
+ if end < len(hcl) {
+ end++ // include closing quote
+ }
+ result.WriteString(stringColor(hcl[i:end]))
+ i = end
+ continue
+ }
+
+ // Numbers - sequences of digits, possibly with decimal point or minus
+ if (ch >= '0' && ch <= '9') || (ch == '-' && i+1 < len(hcl) && hcl[i+1] >= '0' && hcl[i+1] <= '9') {
+ end := i
+ if ch == '-' {
+ end++
+ }
+ for end < len(hcl) && ((hcl[end] >= '0' && hcl[end] <= '9') || hcl[end] == '.') {
+ end++
+ }
+ result.WriteString(numberColor(hcl[i:end]))
+ i = end
+ continue
+ }
+
+ // Identifiers/keys - alphanumeric + underscore
+ if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' {
+ end := i
+ for end < len(hcl) && ((hcl[end] >= 'a' && hcl[end] <= 'z') ||
+ (hcl[end] >= 'A' && hcl[end] <= 'Z') ||
+ (hcl[end] >= '0' && hcl[end] <= '9') ||
+ hcl[end] == '_' || hcl[end] == '-') {
+ end++
+ }
+ ident := hcl[i:end]
+
+ // Check if this is a keyword/reserved word
+ switch ident {
+ case "true", "false", "null":
+ result.WriteString(boolColor(ident))
+ default:
+ // Check if followed by = (it's a key)
+ j := end
+ for j < len(hcl) && (hcl[j] == ' ' || hcl[j] == '\t') {
+ j++
+ }
+ if j < len(hcl) && hcl[j] == '=' {
+ result.WriteString(keyColor(ident))
+ } else if j < len(hcl) && hcl[j] == '{' {
+ // Block type
+ result.WriteString(keyColor(ident))
+ } else {
+ result.WriteString(ident) // plain text for other identifiers
+ }
+ }
+ i = end
+ continue
+ }
+
+ // Everything else (whitespace, operators, brackets) - no color
+ result.WriteByte(ch)
+ i++
+ }
+
+ return []byte(result.String())
+}
+
+// Helper runes for unquoted identifiers
+func isHCLIdentifierStart(r rune) bool {
+ return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || r == '_'
+}
+
+func isHCLIdentifierPart(r rune) bool {
+ return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '-'
+}
+
+func isValidHCLIdentifier(s string) bool {
+ if s == "" {
+ return false
+ }
+ // HCL identifiers must start with a letter or underscore
+ // and contain only letters, digits, underscores, and hyphens
+ for i, r := range s {
+ if i == 0 {
+ if !isHCLIdentifierStart(r) {
+ return false
+ }
+ continue
+ }
+ if !isHCLIdentifierPart(r) {
+ return false
+ }
+ }
+ return true
+}
+
+// tokensForRawHCLExpr produces a minimal token stream for a simple HCL expression so we can
+// write it without introducing quotes (e.g. function calls like upper(message)).
+func tokensForRawHCLExpr(expr string) (hclwrite.Tokens, error) {
+ var tokens hclwrite.Tokens
+ for i := 0; i < len(expr); {
+ ch := expr[i]
+ switch {
+ case ch == ' ' || ch == '\t':
+ i++
+ continue
+ case isHCLIdentifierStart(rune(ch)):
+ start := i
+ i++
+ for i < len(expr) && isHCLIdentifierPart(rune(expr[i])) {
+ i++
+ }
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenIdent, Bytes: []byte(expr[start:i])})
+ continue
+ case ch >= '0' && ch <= '9':
+ start := i
+ i++
+ for i < len(expr) && ((expr[i] >= '0' && expr[i] <= '9') || expr[i] == '.') {
+ i++
+ }
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenNumberLit, Bytes: []byte(expr[start:i])})
+ continue
+ case ch == '(':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenOParen, Bytes: []byte{'('}})
+ case ch == ')':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenCParen, Bytes: []byte{')'}})
+ case ch == ',':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenComma, Bytes: []byte{','}})
+ case ch == '.':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenDot, Bytes: []byte{'.'}})
+ case ch == '+':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenPlus, Bytes: []byte{'+'}})
+ case ch == '-':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenMinus, Bytes: []byte{'-'}})
+ case ch == '*':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenStar, Bytes: []byte{'*'}})
+ case ch == '/':
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenSlash, Bytes: []byte{'/'}})
+ default:
+ return nil, fmt.Errorf("unsupported character %q in raw HCL expression", ch)
+ }
+ i++
+ }
+ return tokens, nil
+}
+
+// encodeAttribute encodes a value as an HCL attribute
+func (he *hclEncoder) encodeAttribute(body *hclwrite.Body, key string, valueNode *CandidateNode) error {
+ if valueNode.Kind == ScalarNode && valueNode.Tag == "!!str" {
+ // Handle unquoted expressions (as-is, without quotes)
+ if valueNode.Style == 0 {
+ tokens, err := tokensForRawHCLExpr(valueNode.Value)
+ if err != nil {
+ return err
+ }
+ body.SetAttributeRaw(key, tokens)
+ return nil
+ }
+ if valueNode.Style&LiteralStyle != 0 {
+ tokens, err := tokensForRawHCLExpr(valueNode.Value)
+ if err != nil {
+ return err
+ }
+ body.SetAttributeRaw(key, tokens)
+ return nil
+ }
+ // Check if template with interpolation
+ if valueNode.Style&DoubleQuotedStyle != 0 && strings.Contains(valueNode.Value, "${") {
+ return he.encodeTemplateAttribute(body, key, valueNode.Value)
+ }
+ // Check if unquoted identifier
+ if isValidHCLIdentifier(valueNode.Value) && valueNode.Style == 0 {
+ traversal := hcl.Traversal{
+ hcl.TraverseRoot{Name: valueNode.Value},
+ }
+ body.SetAttributeTraversal(key, traversal)
+ return nil
+ }
+ }
+ // Default: use cty.Value for quoted strings and all other types
+ ctyValue, err := nodeToCtyValue(valueNode)
+ if err != nil {
+ return err
+ }
+ body.SetAttributeValue(key, ctyValue)
+ return nil
+}
+
+// encodeTemplateAttribute encodes a template string with ${} interpolations
+func (he *hclEncoder) encodeTemplateAttribute(body *hclwrite.Body, key string, templateStr string) error {
+ tokens := hclwrite.Tokens{
+ {Type: hclsyntax.TokenOQuote, Bytes: []byte{'"'}},
+ }
+
+ for i := 0; i < len(templateStr); i++ {
+ if i < len(templateStr)-1 && templateStr[i] == '$' && templateStr[i+1] == '{' {
+ // Start of template interpolation
+ tokens = append(tokens, &hclwrite.Token{
+ Type: hclsyntax.TokenTemplateInterp,
+ Bytes: []byte("${"),
+ })
+ i++ // skip the '{'
+ // Find the matching '}'
+ start := i + 1
+ depth := 1
+ for i++; i < len(templateStr) && depth > 0; i++ {
+ switch templateStr[i] {
+ case '{':
+ depth++
+ case '}':
+ depth--
+ }
+ }
+ i-- // back up to the '}'
+ interpExpr := templateStr[start:i]
+ tokens = append(tokens, &hclwrite.Token{
+ Type: hclsyntax.TokenIdent,
+ Bytes: []byte(interpExpr),
+ })
+ tokens = append(tokens, &hclwrite.Token{
+ Type: hclsyntax.TokenTemplateSeqEnd,
+ Bytes: []byte("}"),
+ })
+ } else {
+ // Regular character
+ tokens = append(tokens, &hclwrite.Token{
+ Type: hclsyntax.TokenQuotedLit,
+ Bytes: []byte{templateStr[i]},
+ })
+ }
+ }
+ tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenCQuote, Bytes: []byte{'"'}})
+ body.SetAttributeRaw(key, tokens)
+ return nil
+}
+
+// encodeBlockIfMapping attempts to encode a value as a block. Returns true if it was encoded as a block.
+func (he *hclEncoder) encodeBlockIfMapping(body *hclwrite.Body, key string, valueNode *CandidateNode) bool {
+ if valueNode.Kind != MappingNode || valueNode.Style == FlowStyle {
+ return false
+ }
+
+ // If EncodeHintSeparateBlock is set, emit children as separate blocks regardless of label extraction
+ if valueNode.EncodeHint == EncodeHintSeparateBlock {
+ if handled, _ := he.encodeMappingChildrenAsBlocks(body, key, valueNode); handled {
+ return true
+ }
+ }
+
+ // Try to extract block labels from a single-entry mapping chain
+ if labels, bodyNode, ok := extractBlockLabels(valueNode); ok {
+ if len(labels) > 1 && mappingChildrenAllMappings(bodyNode) {
+ primaryLabels := labels[:len(labels)-1]
+ nestedType := labels[len(labels)-1]
+ block := body.AppendNewBlock(key, primaryLabels)
+ if handled, err := he.encodeMappingChildrenAsBlocks(block.Body(), nestedType, bodyNode); err == nil && handled {
+ return true
+ }
+ if err := he.encodeNodeAttributes(block.Body(), bodyNode); err == nil {
+ return true
+ }
+ }
+ block := body.AppendNewBlock(key, labels)
+ if err := he.encodeNodeAttributes(block.Body(), bodyNode); err == nil {
+ return true
+ }
+ }
+
+ // If all child values are mappings, treat each child key as a labelled instance of this block type
+ if handled, _ := he.encodeMappingChildrenAsBlocks(body, key, valueNode); handled {
+ return true
+ }
+
+ // No labels detected, render as unlabelled block
+ block := body.AppendNewBlock(key, nil)
+ if err := he.encodeNodeAttributes(block.Body(), valueNode); err == nil {
+ return true
+ }
+
+ return false
+}
+
+// encodeNode encodes a CandidateNode directly to HCL, preserving style information
+func (he *hclEncoder) encodeNode(body *hclwrite.Body, node *CandidateNode) error {
+ if node.Kind != MappingNode {
+ return fmt.Errorf("HCL encoder expects a mapping at the root level, got %v", kindToString(node.Kind))
+ }
+
+ for i := 0; i < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valueNode := node.Content[i+1]
+ key := keyNode.Value
+
+ // Render as block or attribute depending on value type
+ if he.encodeBlockIfMapping(body, key, valueNode) {
+ continue
+ }
+
+ // Render as attribute: key = value
+ if err := he.encodeAttribute(body, key, valueNode); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// mappingChildrenAllMappings reports whether all values in a mapping node are non-flow mappings.
+func mappingChildrenAllMappings(node *CandidateNode) bool {
+ if node == nil || node.Kind != MappingNode || node.Style == FlowStyle {
+ return false
+ }
+ if len(node.Content) == 0 {
+ return false
+ }
+ for i := 0; i < len(node.Content); i += 2 {
+ childVal := node.Content[i+1]
+ if childVal.Kind != MappingNode || childVal.Style == FlowStyle {
+ return false
+ }
+ }
+ return true
+}
+
+// encodeMappingChildrenAsBlocks emits a block for each mapping child, treating the child key as a label.
+// Returns handled=true when it emitted blocks.
+func (he *hclEncoder) encodeMappingChildrenAsBlocks(body *hclwrite.Body, blockType string, valueNode *CandidateNode) (bool, error) {
+ if !mappingChildrenAllMappings(valueNode) {
+ return false, nil
+ }
+
+ // Only emit as separate blocks if EncodeHintSeparateBlock is set
+ // This allows the encoder to respect the original block structure preserved by the decoder
+ if valueNode.EncodeHint != EncodeHintSeparateBlock {
+ return false, nil
+ }
+
+ for i := 0; i < len(valueNode.Content); i += 2 {
+ childKey := valueNode.Content[i].Value
+ childVal := valueNode.Content[i+1]
+
+ // Check if this child also represents multiple blocks (all children are mappings)
+ if mappingChildrenAllMappings(childVal) {
+ // Recursively emit each grandchild as a separate block with extended labels
+ for j := 0; j < len(childVal.Content); j += 2 {
+ grandchildKey := childVal.Content[j].Value
+ grandchildVal := childVal.Content[j+1]
+ labels := []string{childKey, grandchildKey}
+
+ // Try to extract additional labels if this is a single-entry chain
+ if extraLabels, bodyNode, ok := extractBlockLabels(grandchildVal); ok {
+ labels = append(labels, extraLabels...)
+ grandchildVal = bodyNode
+ }
+
+ block := body.AppendNewBlock(blockType, labels)
+ if err := he.encodeNodeAttributes(block.Body(), grandchildVal); err != nil {
+ return true, err
+ }
+ }
+ } else {
+ // Single block with this child as label(s)
+ labels := []string{childKey}
+ if extraLabels, bodyNode, ok := extractBlockLabels(childVal); ok {
+ labels = append(labels, extraLabels...)
+ childVal = bodyNode
+ }
+ block := body.AppendNewBlock(blockType, labels)
+ if err := he.encodeNodeAttributes(block.Body(), childVal); err != nil {
+ return true, err
+ }
+ }
+ }
+
+ return true, nil
+}
+
+// encodeNodeAttributes encodes the attributes of a mapping node (used for blocks)
+func (he *hclEncoder) encodeNodeAttributes(body *hclwrite.Body, node *CandidateNode) error {
+ if node.Kind != MappingNode {
+ return fmt.Errorf("expected mapping node for block body")
+ }
+
+ for i := 0; i < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valueNode := node.Content[i+1]
+ key := keyNode.Value
+
+ // Render as block or attribute depending on value type
+ if he.encodeBlockIfMapping(body, key, valueNode) {
+ continue
+ }
+
+ // Render attribute for non-block value
+ if err := he.encodeAttribute(body, key, valueNode); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// extractBlockLabels detects a chain of single-entry mappings that encode block labels.
+// It returns the collected labels and the final mapping to be used as the block body.
+// Pattern: {label1: {label2: { ... {bodyMap} }}}
+func extractBlockLabels(node *CandidateNode) ([]string, *CandidateNode, bool) {
+ var labels []string
+ current := node
+ for current != nil && current.Kind == MappingNode && len(current.Content) == 2 {
+ keyNode := current.Content[0]
+ valNode := current.Content[1]
+ if valNode.Kind != MappingNode {
+ break
+ }
+ labels = append(labels, keyNode.Value)
+ // If the child is itself a single mapping entry with a mapping value, keep descending.
+ if len(valNode.Content) == 2 && valNode.Content[1].Kind == MappingNode {
+ current = valNode
+ continue
+ }
+ // Otherwise, we have reached the body mapping.
+ return labels, valNode, true
+ }
+ return nil, nil, false
+}
+
+// nodeToCtyValue converts a CandidateNode directly to cty.Value, preserving order
+func nodeToCtyValue(node *CandidateNode) (cty.Value, error) {
+ switch node.Kind {
+ case ScalarNode:
+ // Parse scalar value based on its tag
+ switch node.Tag {
+ case "!!bool":
+ return cty.BoolVal(node.Value == "true"), nil
+ case "!!int":
+ var i int64
+ _, err := fmt.Sscanf(node.Value, "%d", &i)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ return cty.NumberIntVal(i), nil
+ case "!!float":
+ var f float64
+ _, err := fmt.Sscanf(node.Value, "%f", &f)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ return cty.NumberFloatVal(f), nil
+ case "!!null":
+ return cty.NullVal(cty.DynamicPseudoType), nil
+ default:
+ // Default to string
+ return cty.StringVal(node.Value), nil
+ }
+ case MappingNode:
+ // Preserve order by iterating Content directly
+ m := make(map[string]cty.Value)
+ for i := 0; i < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valueNode := node.Content[i+1]
+ v, err := nodeToCtyValue(valueNode)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ m[keyNode.Value] = v
+ }
+ return cty.ObjectVal(m), nil
+ case SequenceNode:
+ vals := make([]cty.Value, len(node.Content))
+ for i, item := range node.Content {
+ v, err := nodeToCtyValue(item)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ vals[i] = v
+ }
+ return cty.TupleVal(vals), nil
+ case AliasNode:
+ return cty.NilVal, fmt.Errorf("HCL encoder does not support aliases")
+ default:
+ return cty.NilVal, fmt.Errorf("unsupported node kind: %v", node.Kind)
+ }
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_ini.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_ini.go
new file mode 100644
index 00000000000..b2b50550c80
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_ini.go
@@ -0,0 +1,113 @@
+//go:build !yq_noini
+
+package yqlib
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+
+ "github.com/go-ini/ini"
+)
+
+type iniEncoder struct {
+ indentString string
+}
+
+// NewINIEncoder creates a new INI encoder
+func NewINIEncoder() Encoder {
+ // Hardcoded indent value of 0, meaning no additional spacing.
+ return &iniEncoder{""}
+}
+
+// CanHandleAliases indicates whether the encoder supports aliases. INI does not support aliases.
+func (ie *iniEncoder) CanHandleAliases() bool {
+ return false
+}
+
+// PrintDocumentSeparator is a no-op since INI does not support multiple documents.
+func (ie *iniEncoder) PrintDocumentSeparator(_ io.Writer) error {
+ return nil
+}
+
+// PrintLeadingContent is a no-op since INI does not support leading content or comments at the encoder level.
+func (ie *iniEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
+ return nil
+}
+
+// Encode converts a CandidateNode into INI format and writes it to the provided writer.
+func (ie *iniEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ log.Debugf("I need to encode %v", NodeToString(node))
+ log.Debugf("kids %v", len(node.Content))
+
+ if node.Kind == ScalarNode {
+ return writeStringINI(writer, node.Value+"\n")
+ }
+
+ // Create a new INI configuration.
+ cfg := ini.Empty()
+
+ if node.Kind == MappingNode {
+ // Default section for key-value pairs at the root level.
+ defaultSection, err := cfg.NewSection(ini.DefaultSection)
+ if err != nil {
+ return err
+ }
+
+ // Process the node's content.
+ for i := 0; i < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valueNode := node.Content[i+1]
+ key := keyNode.Value
+
+ switch valueNode.Kind {
+ case ScalarNode:
+ // Add key-value pair to the default section.
+ _, err := defaultSection.NewKey(key, valueNode.Value)
+ if err != nil {
+ return err
+ }
+ case MappingNode:
+ // Create a new section for nested MappingNode.
+ section, err := cfg.NewSection(key)
+ if err != nil {
+ return err
+ }
+ // Process nested key-value pairs.
+ for j := 0; j < len(valueNode.Content); j += 2 {
+ nestedKeyNode := valueNode.Content[j]
+ nestedValueNode := valueNode.Content[j+1]
+ if nestedValueNode.Kind == ScalarNode {
+ _, err := section.NewKey(nestedKeyNode.Value, nestedValueNode.Value)
+ if err != nil {
+ return err
+ }
+ } else {
+ log.Debugf("Skipping nested non-scalar value for key %s: %v", nestedKeyNode.Value, nestedValueNode.Kind)
+ }
+ }
+ default:
+ log.Debugf("Skipping non-scalar value for key %s: %v", key, valueNode.Kind)
+ }
+ }
+ } else {
+ return fmt.Errorf("INI encoder supports only MappingNode at the root level, got %v", node.Kind)
+ }
+
+ // Use a buffer to store the INI output as the library doesn't support direct io.Writer with indent.
+ var buffer bytes.Buffer
+ _, err := cfg.WriteToIndent(&buffer, ie.indentString)
+ if err != nil {
+ return err
+ }
+
+ // Write the buffer content to the provided writer.
+ _, err = writer.Write(buffer.Bytes())
+ return err
+}
+
+// writeStringINI is a helper function to write a string to the provided writer for INI encoder.
+func writeStringINI(writer io.Writer, content string) error {
+ _, err := writer.Write([]byte(content))
+ return err
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_kyaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_kyaml.go
new file mode 100644
index 00000000000..a4492e27902
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_kyaml.go
@@ -0,0 +1,318 @@
+//go:build !yq_nokyaml
+
+package yqlib
+
+import (
+ "bytes"
+ "io"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type kyamlEncoder struct {
+ prefs KYamlPreferences
+}
+
+func NewKYamlEncoder(prefs KYamlPreferences) Encoder {
+ return &kyamlEncoder{prefs: prefs}
+}
+
+func (ke *kyamlEncoder) CanHandleAliases() bool {
+ // KYAML is a restricted subset; avoid emitting anchors/aliases.
+ return false
+}
+
+func (ke *kyamlEncoder) PrintDocumentSeparator(writer io.Writer) error {
+ return PrintYAMLDocumentSeparator(writer, ke.prefs.PrintDocSeparators)
+}
+
+func (ke *kyamlEncoder) PrintLeadingContent(writer io.Writer, content string) error {
+ return PrintYAMLLeadingContent(writer, content, ke.prefs.PrintDocSeparators, ke.prefs.ColorsEnabled)
+}
+
+func (ke *kyamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ log.Debugf("encoderKYaml - going to print %v", NodeToString(node))
+ if node.Kind == ScalarNode && ke.prefs.UnwrapScalar {
+ return writeString(writer, node.Value+"\n")
+ }
+
+ destination := writer
+ tempBuffer := bytes.NewBuffer(nil)
+ if ke.prefs.ColorsEnabled {
+ destination = tempBuffer
+ }
+
+ // Mirror the YAML encoder behaviour: trailing comments on the document root
+ // are stored in FootComment and need to be printed after the document.
+ trailingContent := node.FootComment
+
+ if err := ke.writeCommentBlock(destination, node.HeadComment, 0); err != nil {
+ return err
+ }
+ if err := ke.writeNode(destination, node, 0); err != nil {
+ return err
+ }
+ if err := ke.writeInlineComment(destination, node.LineComment); err != nil {
+ return err
+ }
+ if err := writeString(destination, "\n"); err != nil {
+ return err
+ }
+ if err := ke.PrintLeadingContent(destination, trailingContent); err != nil {
+ return err
+ }
+
+ if ke.prefs.ColorsEnabled {
+ return colorizeAndPrint(tempBuffer.Bytes(), writer)
+ }
+ return nil
+}
+
+func (ke *kyamlEncoder) writeNode(writer io.Writer, node *CandidateNode, indent int) error {
+ switch node.Kind {
+ case MappingNode:
+ return ke.writeMapping(writer, node, indent)
+ case SequenceNode:
+ return ke.writeSequence(writer, node, indent)
+ case ScalarNode:
+ return writeString(writer, ke.formatScalar(node))
+ case AliasNode:
+ // Should have been exploded by the printer, but handle defensively.
+ if node.Alias == nil {
+ return writeString(writer, "null")
+ }
+ return ke.writeNode(writer, node.Alias, indent)
+ default:
+ return writeString(writer, "null")
+ }
+}
+
+func (ke *kyamlEncoder) writeMapping(writer io.Writer, node *CandidateNode, indent int) error {
+ if len(node.Content) == 0 {
+ return writeString(writer, "{}")
+ }
+ if err := writeString(writer, "{\n"); err != nil {
+ return err
+ }
+
+ for i := 0; i+1 < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valueNode := node.Content[i+1]
+
+ entryIndent := indent + ke.prefs.Indent
+ if err := ke.writeCommentBlock(writer, keyNode.HeadComment, entryIndent); err != nil {
+ return err
+ }
+ if valueNode.HeadComment != "" && valueNode.HeadComment != keyNode.HeadComment {
+ if err := ke.writeCommentBlock(writer, valueNode.HeadComment, entryIndent); err != nil {
+ return err
+ }
+ }
+
+ if err := ke.writeIndent(writer, entryIndent); err != nil {
+ return err
+ }
+ if err := writeString(writer, ke.formatKey(keyNode)); err != nil {
+ return err
+ }
+ if err := writeString(writer, ": "); err != nil {
+ return err
+ }
+ if err := ke.writeNode(writer, valueNode, entryIndent); err != nil {
+ return err
+ }
+
+ // Always emit a trailing comma; KYAML encourages explicit separators,
+ // and this ensures all quoted strings have a trailing `",` as requested.
+ if err := writeString(writer, ","); err != nil {
+ return err
+ }
+ inline := valueNode.LineComment
+ if inline == "" {
+ inline = keyNode.LineComment
+ }
+ if err := ke.writeInlineComment(writer, inline); err != nil {
+ return err
+ }
+ if err := writeString(writer, "\n"); err != nil {
+ return err
+ }
+
+ foot := valueNode.FootComment
+ if foot == "" {
+ foot = keyNode.FootComment
+ }
+ if err := ke.writeCommentBlock(writer, foot, entryIndent); err != nil {
+ return err
+ }
+ }
+
+ if err := ke.writeIndent(writer, indent); err != nil {
+ return err
+ }
+ return writeString(writer, "}")
+}
+
+func (ke *kyamlEncoder) writeSequence(writer io.Writer, node *CandidateNode, indent int) error {
+ if len(node.Content) == 0 {
+ return writeString(writer, "[]")
+ }
+ if err := writeString(writer, "[\n"); err != nil {
+ return err
+ }
+
+ for _, child := range node.Content {
+ itemIndent := indent + ke.prefs.Indent
+ if err := ke.writeCommentBlock(writer, child.HeadComment, itemIndent); err != nil {
+ return err
+ }
+ if err := ke.writeIndent(writer, itemIndent); err != nil {
+ return err
+ }
+ if err := ke.writeNode(writer, child, itemIndent); err != nil {
+ return err
+ }
+ if err := writeString(writer, ","); err != nil {
+ return err
+ }
+ if err := ke.writeInlineComment(writer, child.LineComment); err != nil {
+ return err
+ }
+ if err := writeString(writer, "\n"); err != nil {
+ return err
+ }
+ if err := ke.writeCommentBlock(writer, child.FootComment, itemIndent); err != nil {
+ return err
+ }
+ }
+
+ if err := ke.writeIndent(writer, indent); err != nil {
+ return err
+ }
+ return writeString(writer, "]")
+}
+
+func (ke *kyamlEncoder) writeIndent(writer io.Writer, indent int) error {
+ if indent <= 0 {
+ return nil
+ }
+ return writeString(writer, strings.Repeat(" ", indent))
+}
+
+func (ke *kyamlEncoder) formatKey(keyNode *CandidateNode) string {
+ // KYAML examples use bare keys. Quote keys only when needed.
+ key := keyNode.Value
+ if isValidKYamlBareKey(key) {
+ return key
+ }
+ return `"` + escapeDoubleQuotedString(key) + `"`
+}
+
+func (ke *kyamlEncoder) formatScalar(node *CandidateNode) string {
+ switch node.Tag {
+ case "!!null":
+ return "null"
+ case "!!bool":
+ return strings.ToLower(node.Value)
+ case "!!int", "!!float":
+ return node.Value
+ case "!!str":
+ return `"` + escapeDoubleQuotedString(node.Value) + `"`
+ default:
+ // Fall back to a string representation to avoid implicit typing surprises.
+ return `"` + escapeDoubleQuotedString(node.Value) + `"`
+ }
+}
+
+var kyamlBareKeyRe = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_-]*$`)
+
+func isValidKYamlBareKey(s string) bool {
+ // Conservative: require an identifier-like key; otherwise quote.
+ if s == "" {
+ return false
+ }
+ return kyamlBareKeyRe.MatchString(s)
+}
+
+func escapeDoubleQuotedString(s string) string {
+ var b strings.Builder
+ b.Grow(len(s) + 2)
+
+ for _, r := range s {
+ switch r {
+ case '\\':
+ b.WriteString(`\\`)
+ case '"':
+ b.WriteString(`\"`)
+ case '\n':
+ b.WriteString(`\n`)
+ case '\r':
+ b.WriteString(`\r`)
+ case '\t':
+ b.WriteString(`\t`)
+ default:
+ if r < 0x20 {
+ // YAML double-quoted strings support \uXXXX escapes.
+ b.WriteString(`\u`)
+ hex := "0000" + strings.ToUpper(strconv.FormatInt(int64(r), 16))
+ b.WriteString(hex[len(hex)-4:])
+ } else {
+ b.WriteRune(r)
+ }
+ }
+ }
+ return b.String()
+}
+
+func (ke *kyamlEncoder) writeCommentBlock(writer io.Writer, comment string, indent int) error {
+ if strings.TrimSpace(comment) == "" {
+ return nil
+ }
+
+ lines := strings.Split(strings.ReplaceAll(comment, "\r\n", "\n"), "\n")
+ for _, line := range lines {
+ trimmed := strings.TrimSpace(line)
+ if trimmed == "" {
+ continue
+ }
+
+ if err := ke.writeIndent(writer, indent); err != nil {
+ return err
+ }
+
+ toWrite := line
+ if !commentLineRe.MatchString(toWrite) {
+ toWrite = "# " + toWrite
+ }
+ if err := writeString(writer, toWrite); err != nil {
+ return err
+ }
+ if err := writeString(writer, "\n"); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (ke *kyamlEncoder) writeInlineComment(writer io.Writer, comment string) error {
+ comment = strings.TrimSpace(strings.ReplaceAll(comment, "\r\n", "\n"))
+ if comment == "" {
+ return nil
+ }
+
+ lines := strings.Split(comment, "\n")
+ first := strings.TrimSpace(lines[0])
+ if first == "" {
+ return nil
+ }
+
+ if !strings.HasPrefix(first, "#") {
+ first = "# " + first
+ }
+
+ if err := writeString(writer, " "); err != nil {
+ return err
+ }
+ return writeString(writer, first)
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_lua.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_lua.go
index 6fa85a57b4a..4e3ce89bebe 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_lua.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_lua.go
@@ -167,10 +167,14 @@ func needsQuoting(s string) bool {
// [%a_][%w_]*
for i, c := range s {
if i == 0 {
+ // keeping for legacy reasons, upgraded linter
+ //nolint:staticcheck
if !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
return true
}
} else {
+ // keeping for legacy reasons, upgraded linter
+ //nolint:staticcheck
if !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
return true
}
@@ -299,10 +303,10 @@ func (le *luaEncoder) encodeAny(writer io.Writer, node *CandidateNode) error {
return writeString(writer, node.Value)
}
default:
- return fmt.Errorf("Lua encoder NYI -- %s", node.Tag)
+ return fmt.Errorf("lua encoder NYI -- %s", node.Tag)
}
default:
- return fmt.Errorf("Lua encoder NYI -- %s", node.Tag)
+ return fmt.Errorf("lua encoder NYI -- %s", node.Tag)
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go
index 460a4496940..5a60a114657 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go
@@ -1,3 +1,5 @@
+//go:build !yq_noprops
+
package yqlib
import (
@@ -107,7 +109,7 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateN
case AliasNode:
return pe.doEncode(p, node.Alias, path, nil)
default:
- return fmt.Errorf("Unsupported node %v", node.Tag)
+ return fmt.Errorf("unsupported node %v", node.Tag)
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go
index 42b73ecaef2..4cf8e80417f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go
@@ -1,3 +1,5 @@
+//go:build !yq_nosh
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go
index d725dae3fef..769252ba3c0 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go
@@ -1,3 +1,5 @@
+//go:build !yq_noshell
+
package yqlib
import (
@@ -10,10 +12,13 @@ import (
)
type shellVariablesEncoder struct {
+ prefs ShellVariablesPreferences
}
func NewShellVariablesEncoder() Encoder {
- return &shellVariablesEncoder{}
+ return &shellVariablesEncoder{
+ prefs: ConfiguredShellVariablesPreferences,
+ }
}
func (pe *shellVariablesEncoder) CanHandleAliases() bool {
@@ -52,11 +57,17 @@ func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *CandidateNode, pat
// let's just pick a fallback key to use if we are encoding a single scalar
nonemptyPath = "value"
}
- _, err := io.WriteString(*w, nonemptyPath+"="+quoteValue(node.Value)+"\n")
+ var valueString string
+ if pe.prefs.UnwrapScalar {
+ valueString = node.Value
+ } else {
+ valueString = quoteValue(node.Value)
+ }
+ _, err := io.WriteString(*w, nonemptyPath+"="+valueString+"\n")
return err
case SequenceNode:
for index, child := range node.Content {
- err := pe.doEncode(w, child, appendPath(path, index))
+ err := pe.doEncode(w, child, pe.appendPath(path, index))
if err != nil {
return err
}
@@ -66,7 +77,7 @@ func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *CandidateNode, pat
for index := 0; index < len(node.Content); index = index + 2 {
key := node.Content[index]
value := node.Content[index+1]
- err := pe.doEncode(w, value, appendPath(path, key.Value))
+ err := pe.doEncode(w, value, pe.appendPath(path, key.Value))
if err != nil {
return err
}
@@ -75,11 +86,11 @@ func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *CandidateNode, pat
case AliasNode:
return pe.doEncode(w, node.Alias, path)
default:
- return fmt.Errorf("Unsupported node %v", node.Tag)
+ return fmt.Errorf("unsupported node %v", node.Tag)
}
}
-func appendPath(cookedPath string, rawKey interface{}) string {
+func (pe *shellVariablesEncoder) appendPath(cookedPath string, rawKey interface{}) string {
// Shell variable names must match
// [a-zA-Z_]+[a-zA-Z0-9_]*
@@ -124,7 +135,7 @@ func appendPath(cookedPath string, rawKey interface{}) string {
}
return key
}
- return cookedPath + "_" + key
+ return cookedPath + pe.prefs.KeySeparator + key
}
func quoteValue(value string) string {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go
index f8ced30f421..8c418cc2790 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go
@@ -1,22 +1,58 @@
+//go:build !yq_notoml
+
package yqlib
import (
+ "bytes"
"fmt"
"io"
+ "strings"
+
+ "github.com/fatih/color"
)
type tomlEncoder struct {
+ wroteRootAttr bool // Track if we wrote root-level attributes before tables
+ prefs TomlPreferences
}
func NewTomlEncoder() Encoder {
- return &tomlEncoder{}
+ return NewTomlEncoderWithPrefs(ConfiguredTomlPreferences)
+}
+
+func NewTomlEncoderWithPrefs(prefs TomlPreferences) Encoder {
+ return &tomlEncoder{prefs: prefs}
}
func (te *tomlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
- if node.Kind == ScalarNode {
- return writeString(writer, node.Value+"\n")
+ if node.Kind != MappingNode {
+ // For standalone selections, TOML tests expect raw value for scalars
+ if node.Kind == ScalarNode {
+ return writeString(writer, node.Value+"\n")
+ }
+ return fmt.Errorf("TOML encoder expects a mapping at the root level")
+ }
+
+ // Encode to a buffer first if colors are enabled
+ var buf bytes.Buffer
+ var targetWriter io.Writer
+ targetWriter = writer
+ if te.prefs.ColorsEnabled {
+ targetWriter = &buf
+ }
+
+ // Encode a root mapping as a sequence of attributes, tables, and arrays of tables
+ if err := te.encodeRootMapping(targetWriter, node); err != nil {
+ return err
}
- return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented")
+
+ if te.prefs.ColorsEnabled {
+ colourised := te.colorizeToml(buf.Bytes())
+ _, err := writer.Write(colourised)
+ return err
+ }
+
+ return nil
}
func (te *tomlEncoder) PrintDocumentSeparator(_ io.Writer) error {
@@ -30,3 +66,720 @@ func (te *tomlEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
func (te *tomlEncoder) CanHandleAliases() bool {
return false
}
+
+// ---- helpers ----
+
+// tomlKey returns the key quoted if it contains characters that are not valid
+// in a TOML bare key. TOML bare keys may only contain ASCII letters, ASCII
+// digits, underscores, and dashes.
+func tomlKey(key string) string {
+ for _, r := range key {
+ if (r < 'A' || r > 'Z') && (r < 'a' || r > 'z') && (r < '0' || r > '9') && r != '_' && r != '-' {
+ return fmt.Sprintf("%q", key)
+ }
+ }
+ return key
+}
+
+// tomlDottedKey joins path components, quoting any that require it.
+func tomlDottedKey(path []string) string {
+ parts := make([]string, len(path))
+ for i, p := range path {
+ parts[i] = tomlKey(p)
+ }
+ return strings.Join(parts, ".")
+}
+
+func (te *tomlEncoder) writeComment(w io.Writer, comment string) error {
+ if comment == "" {
+ return nil
+ }
+ lines := strings.Split(comment, "\n")
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if !strings.HasPrefix(line, "#") {
+ line = "# " + line
+ }
+ if _, err := w.Write([]byte(line + "\n")); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (te *tomlEncoder) formatScalar(node *CandidateNode) string {
+ switch node.Tag {
+ case "!!str":
+ // Quote strings per TOML spec
+ return fmt.Sprintf("%q", node.Value)
+ case "!!bool", "!!int", "!!float":
+ return node.Value
+ case "!!null":
+ // TOML does not have null; encode as empty string
+ return `""`
+ default:
+ return node.Value
+ }
+}
+
+func (te *tomlEncoder) encodeRootMapping(w io.Writer, node *CandidateNode) error {
+ te.wroteRootAttr = false // Reset state
+
+ // Write root head comment if present (at the very beginning, no leading blank line)
+ if node.HeadComment != "" {
+ if err := te.writeComment(w, node.HeadComment); err != nil {
+ return err
+ }
+ }
+
+ // Preserve existing order by iterating Content
+ for i := 0; i < len(node.Content); i += 2 {
+ keyNode := node.Content[i]
+ valNode := node.Content[i+1]
+ if err := te.encodeTopLevelEntry(w, []string{keyNode.Value}, valNode); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// encodeTopLevelEntry encodes a key/value at the root, dispatching to attribute, table, or array-of-tables
+func (te *tomlEncoder) encodeTopLevelEntry(w io.Writer, path []string, node *CandidateNode) error {
+ if len(path) == 0 {
+ return fmt.Errorf("cannot encode TOML entry with empty path")
+ }
+
+ switch node.Kind {
+ case ScalarNode:
+ // key = value
+ return te.writeAttribute(w, path[len(path)-1], node)
+ case SequenceNode:
+ // Empty arrays should be encoded as [] attributes
+ if len(node.Content) == 0 {
+ return te.writeArrayAttribute(w, path[len(path)-1], node)
+ }
+
+ // If all items are mappings => array of tables; else => array attribute
+ allMaps := true
+ for _, it := range node.Content {
+ if it.Kind != MappingNode {
+ allMaps = false
+ break
+ }
+ }
+ if allMaps {
+ key := path[len(path)-1]
+ quotedKey := tomlKey(key)
+ for _, it := range node.Content {
+ // [[key]] then body
+ if _, err := w.Write([]byte("[[" + quotedKey + "]]\n")); err != nil {
+ return err
+ }
+ if err := te.encodeMappingBodyWithPath(w, []string{key}, it); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ // Regular array attribute
+ return te.writeArrayAttribute(w, path[len(path)-1], node)
+ case MappingNode:
+ // Use inline table syntax for nodes explicitly marked as TOML inline tables
+ // or YAML flow mappings. All other mappings become readable TOML table sections.
+ if node.EncodeHint == EncodeHintInline || node.Style&FlowStyle != 0 {
+ return te.writeInlineTableAttribute(w, path[len(path)-1], node)
+ }
+ return te.encodeSeparateMapping(w, path, node)
+ default:
+ return fmt.Errorf("unsupported node kind for TOML: %v", node.Kind)
+ }
+}
+
+func (te *tomlEncoder) writeAttribute(w io.Writer, key string, value *CandidateNode) error {
+ te.wroteRootAttr = true // Mark that we wrote a root attribute
+
+ // Write head comment before the attribute
+ if err := te.writeComment(w, value.HeadComment); err != nil {
+ return err
+ }
+
+ // Write the attribute
+ line := tomlKey(key) + " = " + te.formatScalar(value)
+
+ // Add line comment if present
+ if value.LineComment != "" {
+ lineComment := strings.TrimSpace(value.LineComment)
+ if !strings.HasPrefix(lineComment, "#") {
+ lineComment = "# " + lineComment
+ }
+ line += " " + lineComment
+ }
+
+ _, err := w.Write([]byte(line + "\n"))
+ return err
+}
+
+func (te *tomlEncoder) writeArrayAttribute(w io.Writer, key string, seq *CandidateNode) error {
+ te.wroteRootAttr = true // Mark that we wrote a root attribute
+
+ // Write head comment before the array
+ if err := te.writeComment(w, seq.HeadComment); err != nil {
+ return err
+ }
+
+ // Handle empty arrays
+ if len(seq.Content) == 0 {
+ line := tomlKey(key) + " = []"
+ if seq.LineComment != "" {
+ lineComment := strings.TrimSpace(seq.LineComment)
+ if !strings.HasPrefix(lineComment, "#") {
+ lineComment = "# " + lineComment
+ }
+ line += " " + lineComment
+ }
+ _, err := w.Write([]byte(line + "\n"))
+ return err
+ }
+
+ // Check if any array elements have head comments - if so, use multiline format
+ hasElementComments := false
+ for _, it := range seq.Content {
+ if it.HeadComment != "" {
+ hasElementComments = true
+ break
+ }
+ }
+
+ if hasElementComments {
+ // Write multiline array format with comments
+ if _, err := w.Write([]byte(tomlKey(key) + " = [\n")); err != nil {
+ return err
+ }
+
+ for i, it := range seq.Content {
+ // Write head comment for this element
+ if it.HeadComment != "" {
+ commentLines := strings.Split(it.HeadComment, "\n")
+ for _, commentLine := range commentLines {
+ if strings.TrimSpace(commentLine) != "" {
+ if !strings.HasPrefix(strings.TrimSpace(commentLine), "#") {
+ commentLine = "# " + commentLine
+ }
+ if _, err := w.Write([]byte(" " + commentLine + "\n")); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ // Write the element value
+ var itemStr string
+ switch it.Kind {
+ case ScalarNode:
+ itemStr = te.formatScalar(it)
+ case SequenceNode:
+ nested, err := te.sequenceToInlineArray(it)
+ if err != nil {
+ return err
+ }
+ itemStr = nested
+ case MappingNode:
+ inline, err := te.mappingToInlineTable(it)
+ if err != nil {
+ return err
+ }
+ itemStr = inline
+ case AliasNode:
+ return fmt.Errorf("aliases are not supported in TOML")
+ default:
+ return fmt.Errorf("unsupported array item kind: %v", it.Kind)
+ }
+
+ // Always add trailing comma in multiline arrays
+ itemStr += ","
+
+ if _, err := w.Write([]byte(" " + itemStr + "\n")); err != nil {
+ return err
+ }
+
+ // Add blank line between elements (except after the last one)
+ if i < len(seq.Content)-1 {
+ if _, err := w.Write([]byte("\n")); err != nil {
+ return err
+ }
+ }
+ }
+
+ if _, err := w.Write([]byte("]\n")); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ // Join scalars or nested arrays recursively into TOML array syntax
+ items := make([]string, 0, len(seq.Content))
+ for _, it := range seq.Content {
+ switch it.Kind {
+ case ScalarNode:
+ items = append(items, te.formatScalar(it))
+ case SequenceNode:
+ // Nested arrays: encode inline
+ nested, err := te.sequenceToInlineArray(it)
+ if err != nil {
+ return err
+ }
+ items = append(items, nested)
+ case MappingNode:
+ // Inline table inside array
+ inline, err := te.mappingToInlineTable(it)
+ if err != nil {
+ return err
+ }
+ items = append(items, inline)
+ case AliasNode:
+ return fmt.Errorf("aliases are not supported in TOML")
+ default:
+ return fmt.Errorf("unsupported array item kind: %v", it.Kind)
+ }
+ }
+
+ line := tomlKey(key) + " = [" + strings.Join(items, ", ") + "]"
+
+ // Add line comment if present
+ if seq.LineComment != "" {
+ lineComment := strings.TrimSpace(seq.LineComment)
+ if !strings.HasPrefix(lineComment, "#") {
+ lineComment = "# " + lineComment
+ }
+ line += " " + lineComment
+ }
+
+ _, err := w.Write([]byte(line + "\n"))
+ return err
+}
+
+func (te *tomlEncoder) sequenceToInlineArray(seq *CandidateNode) (string, error) {
+ items := make([]string, 0, len(seq.Content))
+ for _, it := range seq.Content {
+ switch it.Kind {
+ case ScalarNode:
+ items = append(items, te.formatScalar(it))
+ case SequenceNode:
+ nested, err := te.sequenceToInlineArray(it)
+ if err != nil {
+ return "", err
+ }
+ items = append(items, nested)
+ case MappingNode:
+ inline, err := te.mappingToInlineTable(it)
+ if err != nil {
+ return "", err
+ }
+ items = append(items, inline)
+ default:
+ return "", fmt.Errorf("unsupported array item kind: %v", it.Kind)
+ }
+ }
+ return "[" + strings.Join(items, ", ") + "]", nil
+}
+
+func (te *tomlEncoder) mappingToInlineTable(m *CandidateNode) (string, error) {
+ // key = { a = 1, b = "x" }
+ parts := make([]string, 0, len(m.Content)/2)
+ for i := 0; i < len(m.Content); i += 2 {
+ k := m.Content[i].Value
+ v := m.Content[i+1]
+ switch v.Kind {
+ case ScalarNode:
+ parts = append(parts, fmt.Sprintf("%s = %s", tomlKey(k), te.formatScalar(v)))
+ case SequenceNode:
+ // inline array in inline table
+ arr, err := te.sequenceToInlineArray(v)
+ if err != nil {
+ return "", err
+ }
+ parts = append(parts, fmt.Sprintf("%s = %s", tomlKey(k), arr))
+ case MappingNode:
+ // nested inline table
+ inline, err := te.mappingToInlineTable(v)
+ if err != nil {
+ return "", err
+ }
+ parts = append(parts, fmt.Sprintf("%s = %s", tomlKey(k), inline))
+ default:
+ return "", fmt.Errorf("unsupported inline table value kind: %v", v.Kind)
+ }
+ }
+ return "{ " + strings.Join(parts, ", ") + " }", nil
+}
+
+func (te *tomlEncoder) writeInlineTableAttribute(w io.Writer, key string, m *CandidateNode) error {
+ inline, err := te.mappingToInlineTable(m)
+ if err != nil {
+ return err
+ }
+ _, err = w.Write([]byte(tomlKey(key) + " = " + inline + "\n"))
+ return err
+}
+
+func (te *tomlEncoder) writeTableHeader(w io.Writer, path []string, m *CandidateNode) error {
+ // Add blank line before table header (or before comment if present) if we wrote root attributes
+ needsBlankLine := te.wroteRootAttr
+ if needsBlankLine {
+ if _, err := w.Write([]byte("\n")); err != nil {
+ return err
+ }
+ te.wroteRootAttr = false // Only add once
+ }
+
+ // Write head comment before the table header
+ if m.HeadComment != "" {
+ if err := te.writeComment(w, m.HeadComment); err != nil {
+ return err
+ }
+ }
+
+ // Write table header [a.b.c]
+ header := "[" + tomlDottedKey(path) + "]\n"
+ _, err := w.Write([]byte(header))
+ return err
+}
+
+// encodeSeparateMapping handles a mapping that should be encoded as table sections.
+// It emits the table header for this mapping if it has any content, then processes children.
+func (te *tomlEncoder) encodeSeparateMapping(w io.Writer, path []string, m *CandidateNode) error {
+ // Check if this mapping has any non-mapping, non-array-of-tables children (i.e., attributes).
+ // Inline mapping children also count as attributes since they render as key = { ... }.
+ hasAttrs := false
+ for i := 0; i < len(m.Content); i += 2 {
+ v := m.Content[i+1]
+ if v.Kind == ScalarNode {
+ hasAttrs = true
+ break
+ }
+ if v.Kind == MappingNode && (v.EncodeHint == EncodeHintInline || v.Style&FlowStyle != 0) {
+ hasAttrs = true
+ break
+ }
+ if v.Kind == SequenceNode {
+ // Check if it's NOT an array of tables
+ allMaps := true
+ for _, it := range v.Content {
+ if it.Kind != MappingNode {
+ allMaps = false
+ break
+ }
+ }
+ if !allMaps {
+ hasAttrs = true
+ break
+ }
+ }
+ }
+
+ // If there are attributes or if the mapping is empty, emit the table header
+ if hasAttrs || len(m.Content) == 0 {
+ if err := te.writeTableHeader(w, path, m); err != nil {
+ return err
+ }
+ if err := te.encodeMappingBodyWithPath(w, path, m); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ // No attributes, just nested table structures - process children recursively
+ for i := 0; i < len(m.Content); i += 2 {
+ k := m.Content[i].Value
+ v := m.Content[i+1]
+ switch v.Kind {
+ case MappingNode:
+ newPath := append(append([]string{}, path...), k)
+ if err := te.encodeSeparateMapping(w, newPath, v); err != nil {
+ return err
+ }
+ case SequenceNode:
+ // If sequence of maps, emit [[path.k]] per element
+ allMaps := true
+ for _, it := range v.Content {
+ if it.Kind != MappingNode {
+ allMaps = false
+ break
+ }
+ }
+ if allMaps {
+ key := tomlDottedKey(append(append([]string{}, path...), k))
+ for _, it := range v.Content {
+ if _, err := w.Write([]byte("[[" + key + "]]\n")); err != nil {
+ return err
+ }
+ if err := te.encodeMappingBodyWithPath(w, append(append([]string{}, path...), k), it); err != nil {
+ return err
+ }
+ }
+ } else {
+ // Regular array attribute under the current table path
+ if err := te.writeArrayAttribute(w, k, v); err != nil {
+ return err
+ }
+ }
+ case ScalarNode:
+ // Attributes directly under the current table path
+ if err := te.writeAttribute(w, k, v); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// encodeMappingBodyWithPath encodes attributes and nested arrays of tables using full dotted path context
+func (te *tomlEncoder) encodeMappingBodyWithPath(w io.Writer, path []string, m *CandidateNode) error {
+ // First, attributes (scalars and non-map arrays)
+ for i := 0; i < len(m.Content); i += 2 {
+ k := m.Content[i].Value
+ v := m.Content[i+1]
+ switch v.Kind {
+ case ScalarNode:
+ if err := te.writeAttribute(w, k, v); err != nil {
+ return err
+ }
+ case SequenceNode:
+ allMaps := true
+ for _, it := range v.Content {
+ if it.Kind != MappingNode {
+ allMaps = false
+ break
+ }
+ }
+ if !allMaps {
+ if err := te.writeArrayAttribute(w, k, v); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ // Then, nested arrays of tables with full path
+ for i := 0; i < len(m.Content); i += 2 {
+ k := m.Content[i].Value
+ v := m.Content[i+1]
+ if v.Kind == SequenceNode {
+ allMaps := true
+ for _, it := range v.Content {
+ if it.Kind != MappingNode {
+ allMaps = false
+ break
+ }
+ }
+ if allMaps {
+ dotted := tomlDottedKey(append(append([]string{}, path...), k))
+ for _, it := range v.Content {
+ if _, err := w.Write([]byte("[[" + dotted + "]]\n")); err != nil {
+ return err
+ }
+ if err := te.encodeMappingBodyWithPath(w, append(append([]string{}, path...), k), it); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+
+ // Finally, child mappings: inline-hint or flow-style ones become inline table attributes,
+ // while all others are emitted as separate sub-table sections.
+ for i := 0; i < len(m.Content); i += 2 {
+ k := m.Content[i].Value
+ v := m.Content[i+1]
+ if v.Kind == MappingNode {
+ if v.EncodeHint == EncodeHintInline || v.Style&FlowStyle != 0 {
+ if err := te.writeInlineTableAttribute(w, k, v); err != nil {
+ return err
+ }
+ } else {
+ subPath := append(append([]string{}, path...), k)
+ if err := te.encodeSeparateMapping(w, subPath, v); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// colorizeToml applies syntax highlighting to TOML output using fatih/color
+func (te *tomlEncoder) colorizeToml(input []byte) []byte {
+ toml := string(input)
+ result := strings.Builder{}
+
+ // Force color output (don't check for TTY)
+ color.NoColor = false
+
+ // Create color functions for different token types
+ // Use EnableColor() to ensure colors work even when NO_COLOR env is set
+ commentColorObj := color.New(color.FgHiBlack)
+ commentColorObj.EnableColor()
+ stringColorObj := color.New(color.FgGreen)
+ stringColorObj.EnableColor()
+ numberColorObj := color.New(color.FgHiMagenta)
+ numberColorObj.EnableColor()
+ keyColorObj := color.New(color.FgCyan)
+ keyColorObj.EnableColor()
+ boolColorObj := color.New(color.FgHiMagenta)
+ boolColorObj.EnableColor()
+ sectionColorObj := color.New(color.FgYellow, color.Bold)
+ sectionColorObj.EnableColor()
+
+ commentColor := commentColorObj.SprintFunc()
+ stringColor := stringColorObj.SprintFunc()
+ numberColor := numberColorObj.SprintFunc()
+ keyColor := keyColorObj.SprintFunc()
+ boolColor := boolColorObj.SprintFunc()
+ sectionColor := sectionColorObj.SprintFunc()
+
+ // Simple tokenization for TOML colouring
+ i := 0
+ for i < len(toml) {
+ ch := toml[i]
+
+ // Comments - from # to end of line
+ if ch == '#' {
+ end := i
+ for end < len(toml) && toml[end] != '\n' {
+ end++
+ }
+ result.WriteString(commentColor(toml[i:end]))
+ i = end
+ continue
+ }
+
+ // Table sections - [section] or [[array]]
+ // Only treat '[' as a table section if it appears at the start of the line
+ // (possibly after whitespace). This avoids mis-colouring inline arrays like
+ // "ports = [8000, 8001]" as table sections.
+ if ch == '[' {
+ isSectionHeader := true
+ if i > 0 {
+ isSectionHeader = false
+ j := i - 1
+ for j >= 0 && toml[j] != '\n' {
+ if toml[j] != ' ' && toml[j] != '\t' && toml[j] != '\r' {
+ // Found a non-whitespace character before this '[' on the same line,
+ // so this is not a table header.
+ break
+ }
+ j--
+ }
+ if j < 0 || toml[j] == '\n' {
+ // Reached the start of the string or a newline without encountering
+ // any non-whitespace, so '[' is at the logical start of the line.
+ isSectionHeader = true
+ }
+ }
+ if isSectionHeader {
+ end := i + 1
+ // Check for [[
+ if end < len(toml) && toml[end] == '[' {
+ end++
+ }
+ // Find closing ]
+ for end < len(toml) && toml[end] != ']' {
+ end++
+ }
+ // Include closing ]
+ if end < len(toml) {
+ end++
+ // Check for ]]
+ if end < len(toml) && toml[end] == ']' {
+ end++
+ }
+ }
+ result.WriteString(sectionColor(toml[i:end]))
+ i = end
+ continue
+ }
+ }
+
+ // Strings - quoted text (double or single quotes)
+ if ch == '"' || ch == '\'' {
+ quote := ch
+ end := i + 1
+ for end < len(toml) {
+ if toml[end] == quote {
+ break
+ }
+ if toml[end] == '\\' && end+1 < len(toml) {
+ // Skip the backslash and the escaped character
+ end += 2
+ continue
+ }
+ end++
+ }
+ if end < len(toml) {
+ end++ // include closing quote
+ }
+ result.WriteString(stringColor(toml[i:end]))
+ i = end
+ continue
+ }
+
+ // Numbers - sequences of digits, possibly with decimal point or minus
+ if (ch >= '0' && ch <= '9') || (ch == '-' && i+1 < len(toml) && toml[i+1] >= '0' && toml[i+1] <= '9') {
+ end := i
+ if ch == '-' {
+ end++
+ }
+ for end < len(toml) {
+ c := toml[end]
+ if (c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' {
+ end++
+ } else if (c == '+' || c == '-') && end > 0 && (toml[end-1] == 'e' || toml[end-1] == 'E') {
+ // Only allow + or - immediately after 'e' or 'E' for scientific notation
+ end++
+ } else {
+ break
+ }
+ }
+ result.WriteString(numberColor(toml[i:end]))
+ i = end
+ continue
+ }
+
+ // Identifiers/keys - alphanumeric + underscore + dash
+ if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' {
+ end := i
+ for end < len(toml) && ((toml[end] >= 'a' && toml[end] <= 'z') ||
+ (toml[end] >= 'A' && toml[end] <= 'Z') ||
+ (toml[end] >= '0' && toml[end] <= '9') ||
+ toml[end] == '_' || toml[end] == '-') {
+ end++
+ }
+ ident := toml[i:end]
+
+ // Check if this is a boolean/null keyword
+ switch ident {
+ case "true", "false":
+ result.WriteString(boolColor(ident))
+ default:
+ // Check if followed by = or whitespace then = (it's a key)
+ j := end
+ for j < len(toml) && (toml[j] == ' ' || toml[j] == '\t') {
+ j++
+ }
+ if j < len(toml) && toml[j] == '=' {
+ result.WriteString(keyColor(ident))
+ } else {
+ result.WriteString(ident) // plain text for other identifiers
+ }
+ }
+ i = end
+ continue
+ }
+
+ // Everything else (whitespace, operators, brackets) - no color
+ result.WriteByte(ch)
+ i++
+ }
+
+ return []byte(result.String())
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go
index 86bcc11ae45..3cc9ad34610 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go
@@ -1,3 +1,5 @@
+//go:build !yq_nouri
+
package yqlib
import (
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go
index d33e2acc6c0..652d574f48f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go
@@ -59,7 +59,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
- log.Warning("Unable to write newline, skipping: %w", err)
+ log.Warningf("Unable to write newline, skipping: %v", err)
}
}
}
@@ -131,7 +131,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
- log.Warning("Unable to write newline, skipping: %w", err)
+ log.Warningf("Unable to write newline, skipping: %v", err)
}
} else if key.Value == e.prefs.DirectiveName {
var directive xml.Directive = []byte(value.Value)
@@ -139,7 +139,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
- log.Warning("Unable to write newline, skipping: %w", err)
+ log.Warningf("Unable to write newline, skipping: %v", err)
}
} else {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go
index f198c05257f..b46ae44428c 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go
@@ -1,15 +1,11 @@
package yqlib
import (
- "bufio"
"bytes"
- "errors"
"io"
- "regexp"
"strings"
- "github.com/fatih/color"
- "gopkg.in/yaml.v3"
+ "go.yaml.in/yaml/v4"
)
type yamlEncoder struct {
@@ -25,64 +21,24 @@ func (ye *yamlEncoder) CanHandleAliases() bool {
}
func (ye *yamlEncoder) PrintDocumentSeparator(writer io.Writer) error {
- if ye.prefs.PrintDocSeparators {
- log.Debug("writing doc sep")
- if err := writeString(writer, "---\n"); err != nil {
- return err
- }
- }
- return nil
+ return PrintYAMLDocumentSeparator(writer, ye.prefs.PrintDocSeparators)
}
func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) error {
- reader := bufio.NewReader(strings.NewReader(content))
-
- var commentLineRegEx = regexp.MustCompile(`^\s*#`)
-
- for {
-
- readline, errReading := reader.ReadString('\n')
- if errReading != nil && !errors.Is(errReading, io.EOF) {
- return errReading
- }
- if strings.Contains(readline, "$yqDocSeparator$") {
-
- if err := ye.PrintDocumentSeparator(writer); err != nil {
- return err
- }
-
- } else {
- if len(readline) > 0 && readline != "\n" && readline[0] != '%' && !commentLineRegEx.MatchString(readline) {
- readline = "# " + readline
- }
- if ye.prefs.ColorsEnabled && strings.TrimSpace(readline) != "" {
- readline = format(color.FgHiBlack) + readline + format(color.Reset)
- }
- if err := writeString(writer, readline); err != nil {
- return err
- }
- }
-
- if errors.Is(errReading, io.EOF) {
- if readline != "" {
- // the last comment we read didn't have a newline, put one in
- if err := writeString(writer, "\n"); err != nil {
- return err
- }
- }
- break
- }
- }
-
- return nil
+ return PrintYAMLLeadingContent(writer, content, ye.prefs.PrintDocSeparators, ye.prefs.ColorsEnabled)
}
func (ye *yamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
- log.Debug("encoderYaml - going to print %v", NodeToString(node))
+ log.Debugf("encoderYaml - going to print %v", NodeToString(node))
+ // Detect line ending style from LeadingContent
+ lineEnding := "\n"
+ if strings.Contains(node.LeadingContent, "\r\n") {
+ lineEnding = "\r\n"
+ }
if node.Kind == ScalarNode && ye.prefs.UnwrapScalar {
valueToPrint := node.Value
if node.LeadingContent == "" || valueToPrint != "" {
- valueToPrint = valueToPrint + "\n"
+ valueToPrint = valueToPrint + lineEnding
}
return writeString(writer, valueToPrint)
}
@@ -96,6 +52,9 @@ func (ye *yamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
var encoder = yaml.NewEncoder(destination)
encoder.SetIndent(ye.prefs.Indent)
+ if ye.prefs.CompactSequenceIndent {
+ encoder.CompactSeqIndent()
+ }
target, err := node.MarshalYAML()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go
index 47226290655..54e287215aa 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go
@@ -9,6 +9,7 @@ type ExpressionNode struct {
Operation *Operation
LHS *ExpressionNode
RHS *ExpressionNode
+ Parent *ExpressionNode
}
type ExpressionParserInterface interface {
@@ -25,7 +26,7 @@ func newExpressionParser() ExpressionParserInterface {
}
func (p *expressionParserImpl) ParseExpression(expression string) (*ExpressionNode, error) {
- log.Debug("Parsing expression: [%v]", expression)
+ log.Debugf("Parsing expression: [%v]", expression)
tokens, err := p.pathTokeniser.Tokenise(expression)
if err != nil {
return nil, err
@@ -50,20 +51,32 @@ func (p *expressionParserImpl) createExpressionTree(postFixPath []*Operation) (*
log.Debugf("pathTree %v ", Operation.toString())
if Operation.OperationType.NumArgs > 0 {
numArgs := Operation.OperationType.NumArgs
- if numArgs == 1 {
+ switch numArgs {
+ case 1:
if len(stack) < 1 {
+ // Allow certain unary ops to accept zero args by interpreting missing RHS as nil
+ // TODO - make this more general on OperationType
+ if Operation.OperationType == firstOpType {
+ // no RHS provided; proceed without popping
+ break
+ }
return nil, fmt.Errorf("'%v' expects 1 arg but received none", strings.TrimSpace(Operation.StringValue))
}
remaining, rhs := stack[:len(stack)-1], stack[len(stack)-1]
newNode.RHS = rhs
+ rhs.Parent = &newNode
stack = remaining
- } else if numArgs == 2 {
+ case 2:
if len(stack) < 2 {
return nil, fmt.Errorf("'%v' expects 2 args but there is %v", strings.TrimSpace(Operation.StringValue), len(stack))
}
remaining, lhs, rhs := stack[:len(stack)-2], stack[len(stack)-2], stack[len(stack)-1]
newNode.LHS = lhs
+ lhs.Parent = &newNode
+
newNode.RHS = rhs
+ rhs.Parent = &newNode
+
stack = remaining
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go
index fa7afa337f4..c5101548c6a 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go
@@ -3,8 +3,7 @@ package yqlib
import (
"errors"
"fmt"
-
- logging "gopkg.in/op/go-logging.v1"
+ "log/slog"
)
type expressionPostFixer interface {
@@ -26,11 +25,12 @@ func popOpToResult(opStack []*token, result []*Operation) ([]*token, []*Operatio
}
func validateNoOpenTokens(token *token) error {
- if token.TokenType == openCollect {
+ switch token.TokenType {
+ case openCollect:
return fmt.Errorf(("bad expression, could not find matching `]`"))
- } else if token.TokenType == openCollectObject {
+ case openCollectObject:
return fmt.Errorf(("bad expression, could not find matching `}`"))
- } else if token.TokenType == openBracket {
+ case openBracket:
return fmt.Errorf(("bad expression, could not find matching `)`"))
}
return nil
@@ -64,7 +64,7 @@ func (p *expressionPostFixerImpl) ConvertToPostfix(infixTokens []*token) ([]*Ope
opStack, result = popOpToResult(opStack, result)
}
if len(opStack) == 0 {
- return nil, errors.New("Bad path expression, got close collect brackets without matching opening bracket")
+ return nil, errors.New("bad path expression, got close collect brackets without matching opening bracket")
}
// now we should have [ as the last element on the opStack, get rid of it
opStack = opStack[0 : len(opStack)-1]
@@ -133,7 +133,7 @@ func (p *expressionPostFixerImpl) ConvertToPostfix(infixTokens []*token) ([]*Ope
return nil, fmt.Errorf("bad expression - probably missing close bracket on %v", opStack[len(opStack)-1].toString(false))
}
- if log.IsEnabledFor(logging.DEBUG) {
+ if log.IsEnabledFor(slog.LevelDebug) {
log.Debugf("PostFix Result:")
for _, currentToken := range result {
log.Debugf("> %v", currentToken.toString())
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go
index 307e45911b4..72d435cf616 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go
@@ -7,7 +7,15 @@ import (
)
func tryRenameFile(from string, to string) error {
- if renameError := os.Rename(from, to); renameError != nil {
+ if info, err := os.Lstat(to); err == nil && info.Mode()&os.ModeSymlink != 0 {
+ log.Debug("Target file is symlink, skipping rename and attempting to copy contents")
+
+ if copyError := copyFileContents(from, to); copyError != nil {
+ return fmt.Errorf("failed copying from %v to %v: %w", from, to, copyError)
+ }
+ tryRemoveTempFile(from)
+ return nil
+ } else if renameError := os.Rename(from, to); renameError != nil {
log.Debugf("Error renaming from %v to %v, attempting to copy contents", from, to)
log.Debug(renameError.Error())
log.Debug("going to try copying instead")
@@ -22,7 +30,7 @@ func tryRenameFile(from string, to string) error {
}
func tryRemoveTempFile(filename string) {
- log.Debug("Removing temp file: %v", filename)
+ log.Debugf("Removing temp file: %v", filename)
removeErr := os.Remove(filename)
if removeErr != nil {
log.Errorf("Failed to remove temp file: %v", filename)
@@ -60,8 +68,7 @@ func SafelyCloseReader(reader io.Reader) {
func safelyCloseFile(file *os.File) {
err := file.Close()
if err != nil {
- log.Error("Error closing file!")
- log.Error(err.Error())
+ log.Errorf("Error closing file %v: %v", file.Name(), err)
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/format.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/format.go
index 144aac08d0e..4cf456f7193 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/format.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/format.go
@@ -3,6 +3,7 @@ package yqlib
import (
"fmt"
"path/filepath"
+ "slices"
"strings"
)
@@ -21,6 +22,12 @@ var YamlFormat = &Format{"yaml", []string{"y", "yml"},
func() Decoder { return NewYamlDecoder(ConfiguredYamlPreferences) },
}
+var KYamlFormat = &Format{"kyaml", []string{"ky"},
+ func() Encoder { return NewKYamlEncoder(ConfiguredKYamlPreferences) },
+ // KYaml is stricter YAML
+ func() Decoder { return NewYamlDecoder(ConfiguredYamlPreferences) },
+}
+
var JSONFormat = &Format{"json", []string{"j"},
func() Encoder { return NewJSONEncoder(ConfiguredJSONPreferences) },
func() Decoder { return NewJSONDecoder() },
@@ -62,10 +69,15 @@ var ShFormat = &Format{"", nil,
}
var TomlFormat = &Format{"toml", []string{},
- func() Encoder { return NewTomlEncoder() },
+ func() Encoder { return NewTomlEncoderWithPrefs(ConfiguredTomlPreferences) },
func() Decoder { return NewTomlDecoder() },
}
+var HclFormat = &Format{"hcl", []string{"h", "tf"},
+ func() Encoder { return NewHclEncoder(ConfiguredHclPreferences) },
+ func() Decoder { return NewHclDecoder() },
+}
+
var ShellVariablesFormat = &Format{"shell", []string{"s", "sh"},
func() Encoder { return NewShellVariablesEncoder() },
nil,
@@ -76,8 +88,14 @@ var LuaFormat = &Format{"lua", []string{"l"},
func() Decoder { return NewLuaDecoder(ConfiguredLuaPreferences) },
}
+var INIFormat = &Format{"ini", []string{"i"},
+ func() Encoder { return NewINIEncoder() },
+ func() Decoder { return NewINIDecoder() },
+}
+
var Formats = []*Format{
YamlFormat,
+ KYamlFormat,
JSONFormat,
PropertiesFormat,
CSVFormat,
@@ -87,20 +105,17 @@ var Formats = []*Format{
UriFormat,
ShFormat,
TomlFormat,
+ HclFormat,
ShellVariablesFormat,
LuaFormat,
+ INIFormat,
}
func (f *Format) MatchesName(name string) bool {
if f.FormalName == name {
return true
}
- for _, n := range f.Names {
- if n == name {
- return true
- }
- }
- return false
+ return slices.Contains(f.Names, name)
}
func (f *Format) GetConfiguredEncoder() Encoder {
@@ -111,7 +126,7 @@ func FormatStringFromFilename(filename string) string {
if filename != "" {
GetLogger().Debugf("checking filename '%s' for auto format detection", filename)
ext := filepath.Ext(filename)
- if ext != "" && ext[0] == '.' {
+ if len(ext) >= 2 && ext[0] == '.' {
format := strings.ToLower(ext[1:])
GetLogger().Debugf("detected format '%s'", format)
return format
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go
index e192f443622..4c56aabd6fb 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go
@@ -58,7 +58,7 @@ func (f *frontMatterHandlerImpl) Split() error {
return err
}
f.yamlFrontMatterFilename = yamlTempFile.Name()
- log.Debug("yamlTempFile: %v", yamlTempFile.Name())
+ log.Debugf("yamlTempFile: %v", yamlTempFile.Name())
lineCount := 0
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/hcl.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/hcl.go
new file mode 100644
index 00000000000..74ddf7dcbb5
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/hcl.go
@@ -0,0 +1,15 @@
+package yqlib
+
+type HclPreferences struct {
+ ColorsEnabled bool
+}
+
+func NewDefaultHclPreferences() HclPreferences {
+ return HclPreferences{ColorsEnabled: false}
+}
+
+func (p *HclPreferences) Copy() HclPreferences {
+ return HclPreferences{ColorsEnabled: p.ColorsEnabled}
+}
+
+var ConfiguredHclPreferences = NewDefaultHclPreferences()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/ini.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/ini.go
new file mode 100644
index 00000000000..ba8bbaf2821
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/ini.go
@@ -0,0 +1,19 @@
+package yqlib
+
+type INIPreferences struct {
+ ColorsEnabled bool
+}
+
+func NewDefaultINIPreferences() INIPreferences {
+ return INIPreferences{
+ ColorsEnabled: false,
+ }
+}
+
+func (p *INIPreferences) Copy() INIPreferences {
+ return INIPreferences{
+ ColorsEnabled: p.ColorsEnabled,
+ }
+}
+
+var ConfiguredINIPreferences = NewDefaultINIPreferences()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/kyaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/kyaml.go
new file mode 100644
index 00000000000..11d8774d2ea
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/kyaml.go
@@ -0,0 +1,30 @@
+//go:build !yq_nokyaml
+
+package yqlib
+
+type KYamlPreferences struct {
+ Indent int
+ ColorsEnabled bool
+ PrintDocSeparators bool
+ UnwrapScalar bool
+}
+
+func NewDefaultKYamlPreferences() KYamlPreferences {
+ return KYamlPreferences{
+ Indent: 2,
+ ColorsEnabled: false,
+ PrintDocSeparators: true,
+ UnwrapScalar: true,
+ }
+}
+
+func (p *KYamlPreferences) Copy() KYamlPreferences {
+ return KYamlPreferences{
+ Indent: p.Indent,
+ ColorsEnabled: p.ColorsEnabled,
+ PrintDocSeparators: p.PrintDocSeparators,
+ UnwrapScalar: p.UnwrapScalar,
+ }
+}
+
+var ConfiguredKYamlPreferences = NewDefaultKYamlPreferences()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go
index cc6841b3e55..12e63e3713f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go
@@ -31,24 +31,25 @@ type token struct {
}
func (t *token) toString(detail bool) string {
- if t.TokenType == operationToken {
+ switch t.TokenType {
+ case operationToken:
if detail {
return fmt.Sprintf("%v (%v)", t.Operation.toString(), t.Operation.OperationType.Precedence)
}
return t.Operation.toString()
- } else if t.TokenType == openBracket {
+ case openBracket:
return "("
- } else if t.TokenType == closeBracket {
+ case closeBracket:
return ")"
- } else if t.TokenType == openCollect {
+ case openCollect:
return "["
- } else if t.TokenType == closeCollect {
+ case closeCollect:
return "]"
- } else if t.TokenType == openCollectObject {
+ case openCollectObject:
return "{"
- } else if t.TokenType == closeCollectObject {
+ case closeCollectObject:
return "}"
- } else if t.TokenType == traverseArrayCollect {
+ case traverseArrayCollect:
return ".["
}
@@ -60,7 +61,7 @@ func unwrap(value string) string {
}
func extractNumberParameter(value string) (int, error) {
- parameterParser := regexp.MustCompile(`.*\(([0-9]+)\)`)
+ parameterParser := regexp.MustCompile(`.*\((-?[0-9]+)\)`)
matches := parameterParser.FindStringSubmatch(value)
var indent, errParsingInt = parseInt(matches[1])
if errParsingInt != nil {
@@ -104,7 +105,7 @@ func handleToken(tokens []*token, index int, postProcessedTokens []*token) (toke
skipNextToken = false
currentToken := tokens[index]
- log.Debug("processing %v", currentToken.toString(true))
+ log.Debugf("processing %v", currentToken.toString(true))
if currentToken.TokenType == traverseArrayCollect {
// `.[exp]`` works by creating a traversal array of [self, exp] and piping that into the traverse array operator
@@ -130,6 +131,11 @@ func handleToken(tokens []*token, index int, postProcessedTokens []*token) (toke
log.Debugf("previous token is : traverseArrayOpType")
// need to put the number 0 before this token, as that is implied
postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: createValueOperation(0, "0")})
+ } else if index >= 2 && tokens[index-1].TokenType == openCollect &&
+ (tokens[index-2].TokenType == operationToken || tokens[index-2].TokenType == closeCollect || tokens[index-2].TokenType == closeCollectObject) {
+ log.Debugf("previous token is : openCollect following a traversal, implying 0 start")
+ // need to put the number 0 before this token, as that is implied
+ postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: createValueOperation(0, "0")})
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go
index 870b39cf163..938b8a717a8 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go
@@ -57,7 +57,7 @@ var participleYqRules = []*participleYqRule{
simpleOp("sort_?keys", sortKeysOpType),
{"ArrayToMap", "array_?to_?map", expressionOpToken(`(.[] | select(. != null) ) as $i ireduce({}; .[$i | key] = $i)`), 0},
-
+ {"Root", "root", expressionOpToken(`parent(-1)`), 0},
{"YamlEncodeWithIndent", `to_?yaml\([0-9]+\)`, encodeParseIndent(YamlFormat), 0},
{"XMLEncodeWithIndent", `to_?xml\([0-9]+\)`, encodeParseIndent(XMLFormat), 0},
{"JSONEncodeWithIndent", `to_?json\([0-9]+\)`, encodeParseIndent(JSONFormat), 0},
@@ -96,6 +96,8 @@ var participleYqRules = []*participleYqRule{
simpleOp("load_?str|str_?load", loadStringOpType),
{"LoadYaml", `load`, loadOp(NewYamlDecoder(LoadYamlPreferences)), 0},
+ simpleOp("system", systemOpType),
+
{"SplitDocument", `splitDoc|split_?doc`, opToken(splitDocumentOpType), 0},
simpleOp("select", selectOpType),
@@ -118,6 +120,7 @@ var participleYqRules = []*participleYqRule{
simpleOp("sort_?by", sortByOpType),
simpleOp("sort", sortOpType),
+ simpleOp("first", firstOpType),
simpleOp("reverse", reverseOpType),
@@ -130,7 +133,8 @@ var participleYqRules = []*participleYqRule{
simpleOp("contains", containsOpType),
simpleOp("split", splitStringOpType),
- {"ParentWithLevel", `parent\([0-9]+\)`, parentWithLevel(), 0},
+ simpleOp("parents", getParentsOpType),
+ {"ParentWithLevel", `parent\(-?[0-9]+\)`, parentWithLevel(), 0},
{"ParentWithDefaultLevel", `parent`, parentWithDefaultLevel(), 0},
simpleOp("keys", keysOpType),
@@ -281,7 +285,7 @@ func pathToken(wrapped bool) yqAction {
if wrapped {
value = unwrap(value)
}
- log.Debug("PathToken %v", value)
+ log.Debugf("PathToken %v", value)
op := &Operation{OperationType: traversePathOpType, Value: value, StringValue: value, Preferences: prefs}
return &token{TokenType: operationToken, Operation: op, CheckForPostTraverse: true}, nil
}
@@ -334,7 +338,7 @@ func flattenWithDepth() yqAction {
func assignAllCommentsOp(updateAssign bool) yqAction {
return func(rawToken lexer.Token) (*token, error) {
- log.Debug("assignAllCommentsOp %v", rawToken.Value)
+ log.Debugf("assignAllCommentsOp %v", rawToken.Value)
value := rawToken.Value
op := &Operation{
OperationType: assignCommentOpType,
@@ -349,7 +353,7 @@ func assignAllCommentsOp(updateAssign bool) yqAction {
func assignOpToken(updateAssign bool) yqAction {
return func(rawToken lexer.Token) (*token, error) {
- log.Debug("assignOpToken %v", rawToken.Value)
+ log.Debugf("assignOpToken %v", rawToken.Value)
value := rawToken.Value
prefs := assignPreferences{DontOverWriteAnchor: true}
if strings.Contains(value, "c") {
@@ -374,12 +378,10 @@ func nullValue() yqAction {
func stringValue() yqAction {
return func(rawToken lexer.Token) (*token, error) {
- log.Debug("rawTokenvalue: %v", rawToken.Value)
+ log.Debugf("rawTokenvalue: %v", rawToken.Value)
value := unwrap(rawToken.Value)
- log.Debug("unwrapped: %v", value)
- value = strings.ReplaceAll(value, "\\\"", "\"")
- value = strings.ReplaceAll(value, "\\n", "\n")
- log.Debug("replaced: %v", value)
+ log.Debugf("unwrapped: %v", value)
+ value = processEscapeCharacters(value)
return &token{TokenType: operationToken, Operation: &Operation{
OperationType: stringInterpolationOpType,
StringValue: value,
@@ -451,6 +453,7 @@ func multiplyWithPrefs(op *operationType) yqAction {
prefs.AssignPrefs.ClobberCustomTags = true
}
prefs.TraversePrefs.DontFollowAlias = true
+ prefs.TraversePrefs.ExactKeyMatch = true
op := &Operation{OperationType: op, Value: multiplyOpType.Type, StringValue: options, Preferences: prefs}
return &token{TokenType: operationToken, Operation: op}, nil
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lib.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lib.go
index 155619307b7..876353ac1ae 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lib.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/lib.go
@@ -4,11 +4,10 @@ package yqlib
import (
"container/list"
"fmt"
+ "log/slog"
"math"
"strconv"
"strings"
-
- logging "gopkg.in/op/go-logging.v1"
)
var ExpressionParser ExpressionParserInterface
@@ -19,15 +18,26 @@ func InitExpressionParser() {
}
}
-var log = logging.MustGetLogger("yq-lib")
+var log = newLogger()
var PrettyPrintExp = `(... | (select(tag != "!!str"), select(tag == "!!str") | select(test("(?i)^(y|yes|n|no|on|off)$") | not)) ) style=""`
// GetLogger returns the yq logger instance.
-func GetLogger() *logging.Logger {
+func GetLogger() *Logger {
return log
}
+func getContentValueByKey(content []*CandidateNode, key string) *CandidateNode {
+ for index := 0; index < len(content)-1; index = index + 2 {
+ keyNode := content[index]
+ valueNode := content[index+1]
+ if keyNode.Value == key {
+ return valueNode
+ }
+ }
+ return nil
+}
+
func recurseNodeArrayEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if len(lhs.Content) != len(rhs.Content) {
return false
@@ -70,7 +80,7 @@ func recurseNodeObjectEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
key := lhs.Content[index]
value := lhs.Content[index+1]
- indexInRHS := findInArray(rhs, key)
+ indexInRHS := findKeyInMap(rhs, key)
if indexInRHS == -1 || !recursiveNodeEqual(value, rhs.Content[indexInRHS+1]) {
return false
@@ -175,6 +185,76 @@ func parseInt(numberString string) (int, error) {
return int(parsed), err
}
+func processEscapeCharacters(original string) string {
+ if original == "" {
+ return original
+ }
+
+ var result strings.Builder
+ runes := []rune(original)
+
+ for i := 0; i < len(runes); i++ {
+ if runes[i] == '\\' && i < len(runes)-1 {
+ next := runes[i+1]
+ switch next {
+ case '\\':
+ // Check if followed by opening bracket - if so, preserve both backslashes
+ // this is required for string interpolation to work correctly.
+ if i+2 < len(runes) && runes[i+2] == '(' {
+ // Preserve \\ when followed by (
+ result.WriteRune('\\')
+ result.WriteRune('\\')
+ i++ // Skip the next backslash (we'll process the ( normally on next iteration)
+ continue
+ }
+ // Escaped backslash: \\ -> \
+ result.WriteRune('\\')
+ i++ // Skip the next backslash
+ continue
+ case '"':
+ result.WriteRune('"')
+ i++ // Skip the quote
+ continue
+ case 'n':
+ result.WriteRune('\n')
+ i++ // Skip the 'n'
+ continue
+ case 't':
+ result.WriteRune('\t')
+ i++ // Skip the 't'
+ continue
+ case 'r':
+ result.WriteRune('\r')
+ i++ // Skip the 'r'
+ continue
+ case 'f':
+ result.WriteRune('\f')
+ i++ // Skip the 'f'
+ continue
+ case 'v':
+ result.WriteRune('\v')
+ i++ // Skip the 'v'
+ continue
+ case 'b':
+ result.WriteRune('\b')
+ i++ // Skip the 'b'
+ continue
+ case 'a':
+ result.WriteRune('\a')
+ i++ // Skip the 'a'
+ continue
+ }
+ }
+ result.WriteRune(runes[i])
+ }
+
+ value := result.String()
+ if value != original {
+ log.Debugf("processEscapeCharacters from [%v] to [%v]", original, value)
+ }
+ return value
+}
+
func headAndLineComment(node *CandidateNode) string {
return headComment(node) + lineComment(node)
}
@@ -193,7 +273,7 @@ func footComment(node *CandidateNode) string {
// use for debugging only
func NodesToString(collection *list.List) string {
- if !log.IsEnabledFor(logging.DEBUG) {
+ if !log.IsEnabledFor(slog.LevelDebug) {
return ""
}
@@ -205,7 +285,7 @@ func NodesToString(collection *list.List) string {
}
func NodeToString(node *CandidateNode) string {
- if !log.IsEnabledFor(logging.DEBUG) {
+ if !log.IsEnabledFor(slog.LevelDebug) {
return ""
}
if node == nil {
@@ -223,7 +303,7 @@ func NodeToString(node *CandidateNode) string {
}
func NodeContentToString(node *CandidateNode, depth int) string {
- if !log.IsEnabledFor(logging.DEBUG) {
+ if !log.IsEnabledFor(slog.LevelDebug) {
return ""
}
var sb strings.Builder
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/logger.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/logger.go
new file mode 100644
index 00000000000..d0194159eb0
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/logger.go
@@ -0,0 +1,77 @@
+package yqlib
+
+import (
+ "fmt"
+ "log/slog"
+ "os"
+)
+
+// Logger wraps log/slog providing a printf-style interface used throughout yq.
+type Logger struct {
+ levelVar slog.LevelVar
+ slogger *slog.Logger
+}
+
+func newLogger() *Logger {
+ l := &Logger{}
+ l.levelVar.Set(slog.LevelWarn)
+ handler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: &l.levelVar})
+ l.slogger = slog.New(handler)
+ return l
+}
+
+// SetLevel sets the minimum log level.
+func (l *Logger) SetLevel(level slog.Level) {
+ l.levelVar.Set(level)
+}
+
+// GetLevel returns the current log level.
+func (l *Logger) GetLevel() slog.Level {
+ return l.levelVar.Level()
+}
+
+// IsEnabledFor returns true if the given level is enabled.
+func (l *Logger) IsEnabledFor(level slog.Level) bool {
+ return l.levelVar.Level() <= level
+}
+
+// SetSlogger replaces the underlying slog.Logger (e.g. to configure output format).
+func (l *Logger) SetSlogger(logger *slog.Logger) {
+ l.slogger = logger
+}
+
+func (l *Logger) Debug(msg string) {
+ if l.IsEnabledFor(slog.LevelDebug) {
+ l.slogger.Debug(msg)
+ }
+}
+
+func (l *Logger) Debugf(format string, args ...interface{}) {
+ if l.IsEnabledFor(slog.LevelDebug) {
+ l.slogger.Debug(fmt.Sprintf(format, args...))
+ }
+}
+
+func (l *Logger) Info(msg string) {
+ l.slogger.Info(msg)
+}
+
+func (l *Logger) Infof(format string, args ...interface{}) {
+ l.slogger.Info(fmt.Sprintf(format, args...))
+}
+
+func (l *Logger) Warning(msg string) {
+ l.slogger.Warn(msg)
+}
+
+func (l *Logger) Warningf(format string, args ...interface{}) {
+ l.slogger.Warn(fmt.Sprintf(format, args...))
+}
+
+func (l *Logger) Error(msg string) {
+ l.slogger.Error(msg)
+}
+
+func (l *Logger) Errorf(format string, args ...interface{}) {
+ l.slogger.Error(fmt.Sprintf(format, args...))
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_base64.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_base64.go
new file mode 100644
index 00000000000..b6fe32bc2e7
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_base64.go
@@ -0,0 +1,11 @@
+//go:build yq_nobase64
+
+package yqlib
+
+func NewBase64Decoder() Decoder {
+ return nil
+}
+
+func NewBase64Encoder() Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_csv.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_csv.go
new file mode 100644
index 00000000000..8dbe44ca14f
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_csv.go
@@ -0,0 +1,11 @@
+//go:build yq_nocsv
+
+package yqlib
+
+func NewCSVObjectDecoder(prefs CsvPreferences) Decoder {
+ return nil
+}
+
+func NewCsvEncoder(prefs CsvPreferences) Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_hcl.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_hcl.go
new file mode 100644
index 00000000000..0db24f873a5
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_hcl.go
@@ -0,0 +1,11 @@
+//go:build yq_nohcl
+
+package yqlib
+
+func NewHclDecoder() Decoder {
+ return nil
+}
+
+func NewHclEncoder(_ HclPreferences) Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_ini.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_ini.go
new file mode 100644
index 00000000000..df89b97c69b
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_ini.go
@@ -0,0 +1,11 @@
+//go:build yq_noini
+
+package yqlib
+
+func NewINIDecoder() Decoder {
+ return nil
+}
+
+func NewINIEncoder() Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_json.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_json.go
index ae9d531adf6..6e11557399c 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_json.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_json.go
@@ -6,6 +6,6 @@ func NewJSONDecoder() Decoder {
return nil
}
-func NewJSONEncoder(indent int, colorise bool, unwrapScalar bool) Encoder {
+func NewJSONEncoder(prefs JsonPreferences) Encoder {
return nil
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_kyaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_kyaml.go
new file mode 100644
index 00000000000..6a68c0acf36
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_kyaml.go
@@ -0,0 +1,7 @@
+//go:build yq_nokyaml
+
+package yqlib
+
+func NewKYamlEncoder(_ KYamlPreferences) Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_props.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_props.go
new file mode 100644
index 00000000000..955246fcc59
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_props.go
@@ -0,0 +1,11 @@
+//go:build yq_noprops
+
+package yqlib
+
+func NewPropertiesDecoder() Decoder {
+ return nil
+}
+
+func NewPropertiesEncoder(prefs PropertiesPreferences) Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_sh.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_sh.go
new file mode 100644
index 00000000000..0f4aaee779e
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_sh.go
@@ -0,0 +1,7 @@
+//go:build yq_nosh
+
+package yqlib
+
+func NewShEncoder() Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_shellvariables.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_shellvariables.go
new file mode 100644
index 00000000000..c2dfd76e6a3
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_shellvariables.go
@@ -0,0 +1,7 @@
+//go:build yq_noshell
+
+package yqlib
+
+func NewShellVariablesEncoder() Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_toml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_toml.go
index 3067dae8045..13bf82527eb 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_toml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_toml.go
@@ -5,3 +5,11 @@ package yqlib
func NewTomlDecoder() Decoder {
return nil
}
+
+func NewTomlEncoder() Encoder {
+ return nil
+}
+
+func NewTomlEncoderWithPrefs(prefs TomlPreferences) Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_uri.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_uri.go
new file mode 100644
index 00000000000..6deeb31e297
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_uri.go
@@ -0,0 +1,11 @@
+//go:build yq_nouri
+
+package yqlib
+
+func NewUriDecoder() Decoder {
+ return nil
+}
+
+func NewUriEncoder() Encoder {
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_xml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_xml.go
index d3f96bb6c29..c1a850ad508 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_xml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/no_xml.go
@@ -6,6 +6,6 @@ func NewXMLDecoder(prefs XmlPreferences) Decoder {
return nil
}
-func NewXMLEncoder(indent int, prefs XmlPreferences) Encoder {
+func NewXMLEncoder(prefs XmlPreferences) Encoder {
return nil
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operation.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operation.go
index 6ed55abc6e9..cbea1d7b9c7 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operation.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operation.go
@@ -25,7 +25,7 @@ var valueToStringFunc = func(p *Operation) string {
}
func createValueOperation(value interface{}, stringValue string) *Operation {
- log.Debug("creating value op for string %v", stringValue)
+ log.Debugf("creating value op for string %v", stringValue)
var node = createScalarNode(value, stringValue)
return &Operation{
@@ -128,6 +128,7 @@ var getKindOpType = &operationType{Type: "GET_KIND", NumArgs: 0, Precedence: 50,
var getKeyOpType = &operationType{Type: "GET_KEY", NumArgs: 0, Precedence: 50, Handler: getKeyOperator}
var isKeyOpType = &operationType{Type: "IS_KEY", NumArgs: 0, Precedence: 50, Handler: isKeyOperator}
var getParentOpType = &operationType{Type: "GET_PARENT", NumArgs: 0, Precedence: 50, Handler: getParentOperator}
+var getParentsOpType = &operationType{Type: "GET_PARENTS", NumArgs: 0, Precedence: 50, Handler: getParentsOperator}
var getCommentOpType = &operationType{Type: "GET_COMMENT", NumArgs: 0, Precedence: 50, Handler: getCommentsOperator}
var getAnchorOpType = &operationType{Type: "GET_ANCHOR", NumArgs: 0, Precedence: 50, Handler: getAnchorOperator}
@@ -142,6 +143,7 @@ var delPathsOpType = &operationType{Type: "DEL_PATHS", NumArgs: 1, Precedence: 5
var explodeOpType = &operationType{Type: "EXPLODE", NumArgs: 1, Precedence: 52, Handler: explodeOperator, CheckForPostTraverse: true}
var sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 52, Handler: sortByOperator, CheckForPostTraverse: true}
+var firstOpType = &operationType{Type: "FIRST", NumArgs: 1, Precedence: 52, Handler: firstOperator, CheckForPostTraverse: true}
var reverseOpType = &operationType{Type: "REVERSE", NumArgs: 0, Precedence: 52, Handler: reverseOperator, CheckForPostTraverse: true}
var sortOpType = &operationType{Type: "SORT", NumArgs: 0, Precedence: 52, Handler: sortOperator, CheckForPostTraverse: true}
var shuffleOpType = &operationType{Type: "SHUFFLE", NumArgs: 0, Precedence: 52, Handler: shuffleOperator, CheckForPostTraverse: true}
@@ -162,6 +164,8 @@ var stringInterpolationOpType = &operationType{Type: "STRING_INT", NumArgs: 0, P
var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 52, Handler: loadOperator, CheckForPostTraverse: true}
var loadStringOpType = &operationType{Type: "LOAD_STRING", NumArgs: 1, Precedence: 52, Handler: loadStringOperator}
+var systemOpType = &operationType{Type: "SYSTEM", NumArgs: 1, Precedence: 50, Handler: systemOperator}
+
var keysOpType = &operationType{Type: "KEYS", NumArgs: 0, Precedence: 52, Handler: keysOperator, CheckForPostTraverse: true}
var collectObjectOpType = &operationType{Type: "COLLECT_OBJECT", NumArgs: 0, Precedence: 50, Handler: collectObjectOperator}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go
index 6f2322bc25a..538b858c5e7 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go
@@ -38,14 +38,23 @@ func toNodes(candidate *CandidateNode, lhs *CandidateNode) []*CandidateNode {
func addOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("Add operator")
+ // only calculate when empty IF we are the root expression; OR
+ // calcWhenEmpty := expressionNode.Parent == nil || expressionNode.Parent.LHS == expressionNode
+ calcWhenEmpty := context.MatchingNodes.Len() > 0
- return crossFunction(d, context.ReadOnlyClone(), expressionNode, add, false)
+ return crossFunction(d, context.ReadOnlyClone(), expressionNode, add, calcWhenEmpty)
}
func add(_ *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
lhsNode := lhs
- if lhsNode.Tag == "!!null" {
+ if lhs == nil && rhs == nil {
+ return nil, nil
+ } else if lhs == nil {
+ return rhs.Copy(), nil
+ } else if rhs == nil {
+ return lhs.Copy(), nil
+ } else if lhsNode.Tag == "!!null" {
return lhs.CopyAsReplacement(rhs), nil
}
@@ -186,9 +195,9 @@ func addMaps(target *CandidateNode, lhsC *CandidateNode, rhsC *CandidateNode) {
for index := 0; index < len(rhs.Content); index = index + 2 {
key := rhs.Content[index]
value := rhs.Content[index+1]
- log.Debug("finding %v", key.Value)
+ log.Debugf("finding %v", key.Value)
indexInLHS := findKeyInMap(target, key)
- log.Debug("indexInLhs %v", indexInLHS)
+ log.Debugf("indexInLhs %v", indexInLHS)
if indexInLHS < 0 {
// not in there, append it
target.AddKeyValueChild(key, value)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go
index 4a2cdf4e942..788469f8894 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go
@@ -5,6 +5,8 @@ import (
"fmt"
)
+var showMergeAnchorToSpecWarning = true
+
func assignAliasOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("AssignAlias operator!")
@@ -138,6 +140,59 @@ func explodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
return context, nil
}
+func fixedReconstructAliasedMap(node *CandidateNode) error {
+ var newContent = []*CandidateNode{}
+
+ for index := 0; index < len(node.Content); index = index + 2 {
+ keyNode := node.Content[index]
+ valueNode := node.Content[index+1]
+ if keyNode.Tag != "!!merge" {
+ // always add in plain nodes
+ // explode both the key and value nodes
+ if err := explodeNode(keyNode, Context{}); err != nil {
+ return err
+ }
+ if err := explodeNode(valueNode, Context{}); err != nil {
+ return err
+ }
+ newContent = append(newContent, keyNode, valueNode)
+ } else {
+ sequence := valueNode
+ if sequence.Kind == AliasNode {
+ sequence = sequence.Alias
+ }
+ if sequence.Kind != SequenceNode {
+ sequence = &CandidateNode{Content: []*CandidateNode{sequence}}
+ }
+ for index := 0; index < len(sequence.Content); index = index + 1 {
+ // for merge anchors, we only set them if the key is not already in node or the newContent
+ mergeNodeSeq := sequence.Content[index]
+ if mergeNodeSeq.Kind == AliasNode {
+ mergeNodeSeq = mergeNodeSeq.Alias
+ }
+ if mergeNodeSeq.Kind != MappingNode {
+ return fmt.Errorf("can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got sequence containing %v", mergeNodeSeq.Tag)
+ }
+ itemsToAdd := mergeNodeSeq.FilterMapContentByKey(func(keyNode *CandidateNode) bool {
+ return getContentValueByKey(node.Content, keyNode.Value) == nil &&
+ getContentValueByKey(newContent, keyNode.Value) == nil
+ })
+
+ for _, item := range itemsToAdd {
+ // copy to ensure exploding doesn't modify the original node
+ itemCopy := item.Copy()
+ if err := explodeNode(itemCopy, Context{}); err != nil {
+ return err
+ }
+ newContent = append(newContent, itemCopy)
+ }
+ }
+ }
+ }
+ node.Content = newContent
+ return nil
+}
+
func reconstructAliasedMap(node *CandidateNode, context Context) error {
var newContent = list.New()
// can I short cut here by prechecking if there's an anchor in the map?
@@ -201,7 +256,7 @@ func explodeNode(node *CandidateNode, context Context) error {
node.Value = node.Alias.Value
node.Alias = nil
}
- log.Debug("now I'm %v", NodeToString(node))
+ log.Debugf("now I'm %v", NodeToString(node))
return nil
case MappingNode:
// //check the map has an alias in it
@@ -215,6 +270,13 @@ func explodeNode(node *CandidateNode, context Context) error {
}
if hasAlias {
+ if ConfiguredYamlPreferences.FixMergeAnchorToSpec {
+ return fixedReconstructAliasedMap(node)
+ }
+ if showMergeAnchorToSpecWarning {
+ log.Warning("--yaml-fix-merge-anchor-to-spec is false; causing merge anchors to override the existing values which isn't to the yaml spec. This flag will default to true in late 2025.")
+ showMergeAnchorToSpecWarning = false
+ }
// this is a slow op, which is why we want to check before running it.
return reconstructAliasedMap(node, context)
}
@@ -242,9 +304,9 @@ func applyAlias(node *CandidateNode, alias *CandidateNode, aliasIndex int, newCo
if alias == nil {
return nil
}
- log.Debug("alias: %v", NodeToString(alias))
+ log.Debugf("alias: %v", NodeToString(alias))
if alias.Kind != MappingNode {
- return fmt.Errorf("merge anchor only supports maps, got %v instead", alias.Tag)
+ return fmt.Errorf("can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got sequence containing %v", alias.Tag)
}
for index := 0; index < len(alias.Content); index = index + 2 {
keyNode := alias.Content[index]
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go
index c9ed2f5b6fc..4edb2786005 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go
@@ -37,7 +37,7 @@ func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode
prefs := getAssignPreferences(expressionNode.Operation.Preferences)
- log.Debug("assignUpdateOperator prefs: %v", prefs)
+ log.Debugf("assignUpdateOperator prefs: %v", prefs)
if !expressionNode.Operation.UpdateAssign {
// this works because we already ran against LHS with an editable context.
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go
index 13f50260226..793477911db 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go
@@ -142,7 +142,7 @@ func notOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Cont
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- log.Debug("notOperation checking %v", candidate)
+ log.Debugf("notOperation checking %v", candidate)
truthy := isTruthyNode(candidate)
result := createBooleanCandidate(candidate, !truthy)
results.PushBack(result)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go
index 6d44f7b24ab..2e96b6f1f65 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go
@@ -2,6 +2,7 @@ package yqlib
import (
"container/list"
+ "fmt"
)
/*
@@ -34,6 +35,9 @@ func collectObjectOperator(d *dataTreeNavigator, originalContext Context, _ *Exp
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidateNode := el.Value.(*CandidateNode)
+ if len(candidateNode.Content) < len(first.Content) {
+ return Context{}, fmt.Errorf("CollectObject: mismatching node sizes; are you creating a map with mismatching key value pairs?")
+ }
for i := 0; i < len(first.Content); i++ {
log.Debugf("rotate[%v] = %v", i, NodeToString(candidateNode.Content[i]))
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go
index fa07d33fe4e..dc7be8c86ec 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go
@@ -46,9 +46,9 @@ func containsObject(lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
rhsKey := rhs.Content[index]
rhsValue := rhs.Content[index+1]
log.Debugf("Looking for %v in the lhs", rhsKey.Value)
- lhsKeyIndex := findInArray(lhs, rhsKey)
+ lhsKeyIndex := findKeyInMap(lhs, rhsKey)
log.Debugf("index is %v", lhsKeyIndex)
- if lhsKeyIndex < 0 || lhsKeyIndex%2 != 0 {
+ if lhsKeyIndex < 0 {
return false, nil
}
lhsValue := lhs.Content[lhsKeyIndex+1]
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go
index 65a1acb2154..9312d14efb0 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go
@@ -80,7 +80,7 @@ func formatDateTime(d *dataTreeNavigator, context Context, expressionNode *Expre
node, errorReading := parseSnippet(formattedTimeStr)
if errorReading != nil {
- log.Debugf("could not parse %v - lets just leave it as a string: %w", formattedTimeStr, errorReading)
+ log.Debugf("could not parse %v - lets just leave it as a string: %v", formattedTimeStr, errorReading)
node = &CandidateNode{
Kind: ScalarNode,
Tag: "!!str",
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go
index 63f05f81d8a..b0a2f14e4b8 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go
@@ -26,11 +26,12 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *
candidatePath := candidate.GetPath()
childPath := candidatePath[len(candidatePath)-1]
- if parentNode.Kind == MappingNode {
+ switch parentNode.Kind {
+ case MappingNode:
deleteFromMap(candidate.Parent, childPath)
- } else if parentNode.Kind == SequenceNode {
+ case SequenceNode:
deleteFromArray(candidate.Parent, childPath)
- } else {
+ default:
return Context{}, fmt.Errorf("cannot delete nodes from parent of tag %v", parentNode.Tag)
}
}
@@ -44,7 +45,7 @@ func removeFromContext(context Context, candidate *CandidateNode) (Context, erro
if nodeInContext != candidate {
newResults.PushBack(nodeInContext)
} else {
- log.Info("Need to delete this %v", NodeToString(nodeInContext))
+ log.Infof("Need to delete this %v", NodeToString(nodeInContext))
}
}
return context.ChildContext(newResults), nil
@@ -81,6 +82,7 @@ func deleteFromArray(node *CandidateNode, childPath interface{}) {
shouldDelete := fmt.Sprintf("%v", index) == fmt.Sprintf("%v", childPath)
if !shouldDelete {
+ value.Key.Value = fmt.Sprintf("%v", len(newContents))
newContents = append(newContents, value)
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go
index 35336573d55..4724fdbc7f6 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go
@@ -33,7 +33,7 @@ func configureEncoder(format *Format, indent int) Encoder {
func encodeToString(candidate *CandidateNode, prefs encoderPreferences) (string, error) {
var output bytes.Buffer
- log.Debug("printing with indent: %v", prefs.indent)
+ log.Debugf("printing with indent: %v", prefs.indent)
encoder := configureEncoder(prefs.format, prefs.indent)
if encoder == nil {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go
index b4ccb9075a5..764fcecadf8 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go
@@ -157,10 +157,10 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
if err != nil {
return Context{}, err
}
- log.Debug("candidate %v", NodeToString(candidate))
- log.Debug("candidate leading content: %v", candidate.LeadingContent)
+ log.Debugf("candidate %v", NodeToString(candidate))
+ log.Debugf("candidate leading content: %v", candidate.LeadingContent)
collected.LeadingContent = candidate.LeadingContent
- log.Debug("candidate FootComment: [%v]", candidate.FootComment)
+ log.Debugf("candidate FootComment: [%v]", candidate.FootComment)
collected.HeadComment = candidate.HeadComment
collected.FootComment = candidate.FootComment
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go
index d4ffa983b93..65a2510f0ed 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go
@@ -17,8 +17,11 @@ type envOpPreferences struct {
}
func envOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
+ if ConfiguredSecurityPreferences.DisableEnvOps {
+ return Context{}, fmt.Errorf("env operations have been disabled")
+ }
envName := expressionNode.Operation.CandidateNode.Value
- log.Debug("EnvOperator, env name:", envName)
+ log.Debugf("EnvOperator, env name: %v", envName)
rawValue := os.Getenv(envName)
@@ -46,14 +49,17 @@ func envOperator(_ *dataTreeNavigator, context Context, expressionNode *Expressi
}
}
- log.Debug("ENV tag", node.Tag)
- log.Debug("ENV value", node.Value)
- log.Debug("ENV Kind", node.Kind)
+ log.Debugf("ENV tag: %v", node.Tag)
+ log.Debugf("ENV value: %v", node.Value)
+ log.Debugf("ENV Kind: %v", node.Kind)
return context.SingleChildContext(node), nil
}
func envsubstOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
+ if ConfiguredSecurityPreferences.DisableEnvOps {
+ return Context{}, fmt.Errorf("env operations have been disabled")
+ }
var results = list.New()
preferences := envOpPreferences{}
if expressionNode.Operation.Preferences != nil {
@@ -72,7 +78,7 @@ func envsubstOperator(_ *dataTreeNavigator, context Context, expressionNode *Exp
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
if node.Tag != "!!str" {
- log.Warning("EnvSubstOperator, env name:", node.Tag, node.Value)
+ log.Warningf("EnvSubstOperator, env name: %v %v", node.Tag, node.Value)
return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_first.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_first.go
new file mode 100644
index 00000000000..cdc4d28901c
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_first.go
@@ -0,0 +1,51 @@
+package yqlib
+
+import "container/list"
+
+func firstOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
+ results := list.New()
+
+ for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
+ candidate := el.Value.(*CandidateNode)
+
+ // If no RHS expression is provided, simply return the first entry in candidate.Content
+ if expressionNode == nil || expressionNode.RHS == nil {
+ if len(candidate.Content) > 0 {
+ results.PushBack(candidate.Content[0])
+ }
+ continue
+ }
+
+ splatted, err := splat(context.SingleChildContext(candidate), traversePreferences{})
+ if err != nil {
+ return Context{}, err
+ }
+
+ for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
+ splatCandidate := splatEl.Value.(*CandidateNode)
+ // Create a new context for this splatted candidate
+ splatContext := context.SingleChildContext(splatCandidate)
+ // Evaluate the RHS expression against this splatted candidate
+ rhs, err := d.GetMatchingNodes(splatContext, expressionNode.RHS)
+ if err != nil {
+ return Context{}, err
+ }
+
+ includeResult := false
+
+ for resultEl := rhs.MatchingNodes.Front(); resultEl != nil; resultEl = resultEl.Next() {
+ result := resultEl.Value.(*CandidateNode)
+ includeResult = isTruthyNode(result)
+ if includeResult {
+ break
+ }
+ }
+ if includeResult {
+ results.PushBack(splatCandidate)
+ break
+ }
+ }
+
+ }
+ return context.ChildContext(results), nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go
index 1e58ed1ce22..bdcd1250f1f 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go
@@ -45,12 +45,13 @@ func keysOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Con
candidate := el.Value.(*CandidateNode)
var targetNode *CandidateNode
- if candidate.Kind == MappingNode {
+ switch candidate.Kind {
+ case MappingNode:
targetNode = getMapKeys(candidate)
- } else if candidate.Kind == SequenceNode {
+ case SequenceNode:
targetNode = getIndices(candidate)
- } else {
- return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", candidate.Tag)
+ default:
+ return Context{}, fmt.Errorf("cannot get keys of %v, keys only works for maps and arrays", candidate.Tag)
}
results.PushBack(targetNode)
@@ -64,19 +65,20 @@ func getMapKeys(node *CandidateNode) *CandidateNode {
for index := 0; index < len(node.Content); index = index + 2 {
contents = append(contents, node.Content[index])
}
- return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
+
+ seq := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
+ seq.AddChildren(contents)
+ return seq
}
func getIndices(node *CandidateNode) *CandidateNode {
var contents = make([]*CandidateNode, len(node.Content))
for index := range node.Content {
- contents[index] = &CandidateNode{
- Kind: ScalarNode,
- Tag: "!!int",
- Value: fmt.Sprintf("%v", index),
- }
+ contents[index] = createScalarNode(index, fmt.Sprintf("%v", index))
}
- return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
+ seq := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
+ seq.AddChildren(contents)
+ return seq
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go
index f30ee352ee5..a4a2e50600c 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go
@@ -63,6 +63,9 @@ func loadWithDecoder(filename string, decoder Decoder) (*CandidateNode, error) {
func loadStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("loadString")
+ if ConfiguredSecurityPreferences.DisableFileOps {
+ return Context{}, fmt.Errorf("file operations have been disabled")
+ }
var results = list.New()
@@ -82,7 +85,7 @@ func loadStringOperator(d *dataTreeNavigator, context Context, expressionNode *E
contentsCandidate, err := loadString(filename)
if err != nil {
- return Context{}, fmt.Errorf("Failed to load %v: %w", filename, err)
+ return Context{}, fmt.Errorf("failed to load %v: %w", filename, err)
}
results.PushBack(contentsCandidate)
@@ -94,6 +97,9 @@ func loadStringOperator(d *dataTreeNavigator, context Context, expressionNode *E
func loadOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("loadOperator")
+ if ConfiguredSecurityPreferences.DisableFileOps {
+ return Context{}, fmt.Errorf("file operations have been disabled")
+ }
loadPrefs := expressionNode.Operation.Preferences.(loadPrefs)
@@ -118,7 +124,7 @@ func loadOperator(d *dataTreeNavigator, context Context, expressionNode *Express
contentsCandidate, err := loadWithDecoder(filename, loadPrefs.decoder)
if err != nil {
- return Context{}, fmt.Errorf("Failed to load %v: %w", filename, err)
+ return Context{}, fmt.Errorf("failed to load %v: %w", filename, err)
}
results.PushBack(contentsCandidate)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go
index 216d78ae66f..0d98ddcd829 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go
@@ -41,10 +41,14 @@ func mapOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
if err != nil {
return Context{}, err
}
+ if splatted.MatchingNodes.Len() == 0 {
+ results.PushBack(candidate.Copy())
+ continue
+ }
result, err := d.GetMatchingNodes(splatted, expressionNode.RHS)
- log.Debug("expressionNode.Rhs %v", expressionNode.RHS.Operation.OperationType)
- log.Debug("result %v", result)
+ log.Debugf("expressionNode.Rhs %v", expressionNode.RHS.Operation.OperationType)
+ log.Debugf("result %v", result)
if err != nil {
return Context{}, err
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go
index 64922c72407..9db2c4f5abe 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go
@@ -30,7 +30,7 @@ func multiplyAssignOperator(d *dataTreeNavigator, context Context, expressionNod
func multiplyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("MultiplyOperator")
- return crossFunction(d, context, expressionNode, multiply(expressionNode.Operation.Preferences.(multiplyPreferences)), false)
+ return crossFunction(d, context.ReadOnlyClone(), expressionNode, multiply(expressionNode.Operation.Preferences.(multiplyPreferences)), false)
}
func getComments(lhs *CandidateNode, rhs *CandidateNode) (leadingContent string, headComment string, footComment string) {
@@ -153,6 +153,12 @@ func repeatString(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error
count, err := parseInt(intNode.Value)
if err != nil {
return nil, err
+ } else if count < 0 {
+ return nil, fmt.Errorf("cannot repeat string by a negative number (%v)", count)
+ }
+ maxResultLen := 10 * 1024 * 1024 // 10 MiB
+ if count > 0 && len(stringNode.Value) > maxResultLen/count {
+ return nil, fmt.Errorf("result of repeating string (%v bytes) by %v would exceed %v bytes", len(stringNode.Value), count, maxResultLen)
}
target.Value = strings.Repeat(stringNode.Value, count)
@@ -164,7 +170,7 @@ func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs
// only need to recurse the array if we are doing a deep merge
prefs := recursiveDescentPreferences{RecurseArray: preferences.DeepMergeArrays,
- TraversePreferences: traversePreferences{DontFollowAlias: true, IncludeMapKeys: true}}
+ TraversePreferences: traversePreferences{DontFollowAlias: true, IncludeMapKeys: true, ExactKeyMatch: true}}
log.Debugf("merge - preferences.DeepMergeArrays %v", preferences.DeepMergeArrays)
log.Debugf("merge - preferences.AppendArrays %v", preferences.AppendArrays)
err := recursiveDecent(results, context.SingleChildContext(rhs), prefs)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_omit.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_omit.go
index 45ad7ce9e0c..36549362be7 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_omit.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_omit.go
@@ -58,11 +58,12 @@ func omitOperator(d *dataTreeNavigator, context Context, expressionNode *Express
var replacement *CandidateNode
- if node.Kind == MappingNode {
+ switch node.Kind {
+ case MappingNode:
replacement = omitMap(node, indicesToOmit)
- } else if node.Kind == SequenceNode {
+ case SequenceNode:
replacement = omitSequence(node, indicesToOmit)
- } else {
+ default:
log.Debugf("Omit from type %v (%v) is noop", node.Tag, node.GetNicePath())
return context, nil
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go
index 3133d8436cd..3644db0f53c 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go
@@ -6,6 +6,26 @@ type parentOpPreferences struct {
Level int
}
+func getParentsOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Context, error) {
+ log.Debugf("getParentsOperator")
+
+ var results = list.New()
+
+ for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
+ candidate := el.Value.(*CandidateNode)
+ parentsList := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
+ parent := candidate.Parent
+ for parent != nil {
+ parentsList.AddChild(parent)
+ parent = parent.Parent
+ }
+ results.PushBack(parentsList)
+ }
+
+ return context.ChildContext(results), nil
+
+}
+
func getParentOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("getParentOperator")
@@ -15,9 +35,28 @@ func getParentOperator(_ *dataTreeNavigator, context Context, expressionNode *Ex
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
+
+ // Handle negative levels: count total parents first
+ levelsToGoUp := prefs.Level
+ if prefs.Level < 0 {
+ // Count all parents
+ totalParents := 0
+ temp := candidate.Parent
+ for temp != nil {
+ totalParents++
+ temp = temp.Parent
+ }
+ // Convert negative index to positive
+ // -1 means last parent (root), -2 means second to last, etc.
+ levelsToGoUp = totalParents + prefs.Level + 1
+ if levelsToGoUp < 0 {
+ levelsToGoUp = 0
+ }
+ }
+
currentLevel := 0
- for currentLevel < prefs.Level && candidate != nil {
- log.Debugf("currentLevel: %v, desired: %v", currentLevel, prefs.Level)
+ for currentLevel < levelsToGoUp && candidate != nil {
+ log.Debugf("currentLevel: %v, desired: %v", currentLevel, levelsToGoUp)
log.Debugf("candidate: %v", NodeToString(candidate))
candidate = candidate.Parent
currentLevel++
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go
index a3a687c354b..3fb8f8da9de 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go
@@ -22,15 +22,16 @@ func getPathArrayFromNode(funcName string, node *CandidateNode) ([]interface{},
path := make([]interface{}, len(node.Content))
for i, childNode := range node.Content {
- if childNode.Tag == "!!str" {
+ switch childNode.Tag {
+ case "!!str":
path[i] = childNode.Value
- } else if childNode.Tag == "!!int" {
+ case "!!int":
number, err := parseInt(childNode.Value)
if err != nil {
return nil, fmt.Errorf("%v: could not parse %v as an int: %w", funcName, childNode.Value, err)
}
path[i] = number
- } else {
+ default:
return nil, fmt.Errorf("%v: expected either a !!str or !!int in the path, found %v instead", funcName, childNode.Tag)
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go
index 2e223ea0e64..04700435c9a 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go
@@ -64,15 +64,16 @@ func pickOperator(d *dataTreeNavigator, context Context, expressionNode *Express
node := el.Value.(*CandidateNode)
var replacement *CandidateNode
- if node.Kind == MappingNode {
+ switch node.Kind {
+ case MappingNode:
replacement = pickMap(node, indicesToPick)
- } else if node.Kind == SequenceNode {
+ case SequenceNode:
replacement, err = pickSequence(node, indicesToPick)
if err != nil {
return Context{}, err
}
- } else {
+ default:
return Context{}, fmt.Errorf("cannot pick indices from type %v (%v)", node.Tag, node.GetNicePath())
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go
index 9ccad23d263..b1ff051607b 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go
@@ -26,7 +26,12 @@ func shuffleOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (
a := result.Content
- myRand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
+ myRand.Shuffle(len(a), func(i, j int) {
+ a[i], a[j] = a[j], a[i]
+ oldIndex := a[i].Key.Value
+ a[i].Key.Value = a[j].Key.Value
+ a[j].Key.Value = oldIndex
+ })
results.PushBack(result)
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go
index e4c3906c1d3..1f3bfdd3cda 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go
@@ -16,11 +16,44 @@ func getSliceNumber(d *dataTreeNavigator, context Context, node *CandidateNode,
return parseInt(result.MatchingNodes.Front().Value.(*CandidateNode).Value)
}
+// clampSliceIndex resolves a possibly-negative slice index against
+// length and clamps the result to [0, length].
+func clampSliceIndex(index, length int) int {
+ if index < 0 {
+ index += length
+ }
+ if index < 0 {
+ return 0
+ }
+ if index > length {
+ return length
+ }
+ return index
+}
+
+func sliceStringNode(lhsNode *CandidateNode, firstNumber int, secondNumber int) *CandidateNode {
+ runes := []rune(lhsNode.Value)
+ length := len(runes)
+
+ relativeFirstNumber := clampSliceIndex(firstNumber, length)
+ relativeSecondNumber := clampSliceIndex(secondNumber, length)
+ if relativeSecondNumber < relativeFirstNumber {
+ relativeSecondNumber = relativeFirstNumber
+ }
+
+ log.Debugf("sliceStringNode: slice from %v to %v", relativeFirstNumber, relativeSecondNumber)
+
+ slicedString := string(runes[relativeFirstNumber:relativeSecondNumber])
+ replacement := lhsNode.CreateReplacement(ScalarNode, lhsNode.Tag, slicedString)
+ replacement.Style = lhsNode.Style
+ return replacement
+}
+
func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debug("slice array operator!")
- log.Debug("lhs: %v", expressionNode.LHS.Operation.toString())
- log.Debug("rhs: %v", expressionNode.RHS.Operation.toString())
+ log.Debugf("lhs: %v", expressionNode.LHS.Operation.toString())
+ log.Debugf("rhs: %v", expressionNode.RHS.Operation.toString())
results := list.New()
@@ -28,28 +61,24 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E
lhsNode := el.Value.(*CandidateNode)
firstNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.LHS)
-
if err != nil {
return Context{}, err
}
- relativeFirstNumber := firstNumber
- if relativeFirstNumber < 0 {
- relativeFirstNumber = len(lhsNode.Content) + firstNumber
- }
secondNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.RHS)
if err != nil {
return Context{}, err
}
- relativeSecondNumber := secondNumber
- if relativeSecondNumber < 0 {
- relativeSecondNumber = len(lhsNode.Content) + secondNumber
- } else if relativeSecondNumber > len(lhsNode.Content) {
- relativeSecondNumber = len(lhsNode.Content)
+ if lhsNode.Kind == ScalarNode && lhsNode.guessTagFromCustomType() == "!!str" {
+ results.PushBack(sliceStringNode(lhsNode, firstNumber, secondNumber))
+ continue
}
- log.Debug("calculateIndicesToTraverse: slice from %v to %v", relativeFirstNumber, relativeSecondNumber)
+ relativeFirstNumber := clampSliceIndex(firstNumber, len(lhsNode.Content))
+ relativeSecondNumber := clampSliceIndex(secondNumber, len(lhsNode.Content))
+
+ log.Debugf("calculateIndicesToTraverse: slice from %v to %v", relativeFirstNumber, relativeSecondNumber)
var newResults []*CandidateNode
for i := relativeFirstNumber; i < relativeSecondNumber; i++ {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go
index 942ef46a8c7..2bcf21575b9 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go
@@ -24,30 +24,41 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- if candidate.Kind != SequenceNode {
- return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.Tag)
- }
-
- sortableArray := make(sortableNodeArray, len(candidate.Content))
-
- for i, originalNode := range candidate.Content {
-
- compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(originalNode), expressionNode.RHS)
- if err != nil {
- return Context{}, err
+ var sortableArray sortableNodeArray
+
+ if candidate.CanVisitValues() {
+ sortableArray = make(sortableNodeArray, 0)
+ visitor := func(valueNode *CandidateNode) error {
+ compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(valueNode), expressionNode.RHS)
+ if err != nil {
+ return err
+ }
+ sortableNode := sortableNode{Node: valueNode, CompareContext: compareContext, dateTimeLayout: context.GetDateTimeLayout()}
+ sortableArray = append(sortableArray, sortableNode)
+ return nil
}
-
- sortableArray[i] = sortableNode{Node: originalNode, CompareContext: compareContext, dateTimeLayout: context.GetDateTimeLayout()}
-
+ if err := candidate.VisitValues(visitor); err != nil {
+ return context, err
+ }
+ } else {
+ return context, fmt.Errorf("node at path [%v] is not an array or map (it's a %v)", candidate.GetNicePath(), candidate.Tag)
}
sort.Stable(sortableArray)
- sortedList := candidate.CreateReplacementWithComments(SequenceNode, "!!seq", candidate.Style)
-
- for _, sortedNode := range sortableArray {
- sortedList.AddChild(sortedNode.Node)
+ sortedList := candidate.CopyWithoutContent()
+ switch candidate.Kind {
+ case MappingNode:
+ for _, sortedNode := range sortableArray {
+ sortedList.AddKeyValueChild(sortedNode.Node.Key, sortedNode.Node)
+ }
+ case SequenceNode:
+ for _, sortedNode := range sortableArray {
+ sortedList.AddChild(sortedNode.Node)
+ }
}
+
+ // convert array of value nodes back to map
results.PushBack(sortedList)
}
return context.ChildContext(results), nil
@@ -131,12 +142,12 @@ func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateT
} else if isDateTime {
lhsTime, err := parseDateTime(layout, lhs.Value)
if err != nil {
- log.Warningf("Could not parse time %v with layout %v for sort, sorting by string instead: %w", lhs.Value, layout, err)
+ log.Warningf("Could not parse time %v with layout %v for sort, sorting by string instead: %v", lhs.Value, layout, err)
return strings.Compare(lhs.Value, rhs.Value)
}
rhsTime, err := parseDateTime(layout, rhs.Value)
if err != nil {
- log.Warningf("Could not parse time %v with layout %v for sort, sorting by string instead: %w", rhs.Value, layout, err)
+ log.Warningf("Could not parse time %v with layout %v for sort, sorting by string instead: %v", rhs.Value, layout, err)
return strings.Compare(lhs.Value, rhs.Value)
}
if lhsTime.Equal(rhsTime) {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go
index c9bb9e4a6a1..3ab79b0dbf5 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go
@@ -220,7 +220,7 @@ func getSubstituteParameters(d *dataTreeNavigator, block *ExpressionNode, contex
regEx = regExNodes.MatchingNodes.Front().Value.(*CandidateNode).Value
}
- log.Debug("regEx %v", regEx)
+ log.Debugf("regEx %v", regEx)
replacementNodes, err := d.GetMatchingNodes(context, block.RHS)
if err != nil {
@@ -318,7 +318,7 @@ func getMatches(matchPrefs matchPreferences, regEx *regexp.Regexp, value string)
allIndices = [][]int{regEx.FindStringSubmatchIndex(value)}
}
- log.Debug("allMatches, %v", allMatches)
+ log.Debugf("allMatches, %v", allMatches)
return allMatches, allIndices
}
@@ -410,7 +410,7 @@ func extractMatchArguments(d *dataTreeNavigator, context Context, expressionNode
return nil, matchPrefs, fmt.Errorf(`'i' is not a valid option for match. To ignore case, use an expression like match("(?i)cat")`)
}
if len(paramText) > 0 {
- return nil, matchPrefs, fmt.Errorf(`Unrecognised match params '%v', please see docs at https://mikefarah.gitbook.io/yq/operators/string-operators`, paramText)
+ return nil, matchPrefs, fmt.Errorf(`unrecognised match params '%v', please see docs at https://mikefarah.gitbook.io/yq/operators/string-operators`, paramText)
}
}
@@ -423,7 +423,7 @@ func extractMatchArguments(d *dataTreeNavigator, context Context, expressionNode
if regExNodes.MatchingNodes.Front() != nil {
regExStr = regExNodes.MatchingNodes.Front().Value.(*CandidateNode).Value
}
- log.Debug("regEx %v", regExStr)
+ log.Debugf("regEx %v", regExStr)
regEx, err := regexp.Compile(regExStr)
return regEx, matchPrefs, err
}
@@ -564,7 +564,7 @@ func split(value string, spltStr string) (Kind, string, []*CandidateNode) {
var contents []*CandidateNode
if value != "" {
- log.Debug("going to spltStr[%v]", spltStr)
+ log.Debugf("going to spltStr[%v]", spltStr)
var newStrings = strings.Split(value, spltStr)
contents = make([]*CandidateNode, len(newStrings))
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go
index 37aad8656c9..805b0657ad5 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go
@@ -19,14 +19,14 @@ func parseStyle(customStyle string) (Style, error) {
} else if customStyle == "flow" {
return FlowStyle, nil
} else if customStyle != "" {
- return 0, fmt.Errorf("Unknown style %v", customStyle)
+ return 0, fmt.Errorf("unknown style %v", customStyle)
}
return 0, nil
}
func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- log.Debugf("AssignStyleOperator: %v")
+ log.Debugf("AssignStyleOperator")
var style Style
if !expressionNode.Operation.UpdateAssign {
rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_system.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_system.go
new file mode 100644
index 00000000000..c9937957e0b
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_system.go
@@ -0,0 +1,146 @@
+package yqlib
+
+import (
+ "bytes"
+ "container/list"
+ "fmt"
+ "os/exec"
+ "strings"
+)
+
+func resolveSystemArgs(argsNode *CandidateNode) ([]string, error) {
+ if argsNode == nil {
+ return nil, nil
+ }
+
+ if argsNode.Kind == SequenceNode {
+ args := make([]string, 0, len(argsNode.Content))
+ for _, child := range argsNode.Content {
+ // Only non-null scalar children are valid arguments.
+ if child == nil {
+ continue
+ }
+ if child.Kind != ScalarNode || child.Tag == "!!null" {
+ return nil, fmt.Errorf("system operator: argument must be a non-null scalar; got kind=%v tag=%v", child.Kind, child.Tag)
+ }
+ args = append(args, child.Value)
+ }
+ if len(args) == 0 {
+ return nil, nil
+ }
+ return args, nil
+ }
+
+ // Single-argument case: only accept a non-null scalar node.
+ if argsNode.Tag == "!!null" {
+ return nil, nil
+ }
+ if argsNode.Kind != ScalarNode {
+ return nil, fmt.Errorf("system operator: args must be a non-null scalar or sequence of non-null scalars; got kind=%v tag=%v", argsNode.Kind, argsNode.Tag)
+ }
+ return []string{argsNode.Value}, nil
+}
+
+func resolveCommandNode(commandNodes Context) (string, error) {
+ if commandNodes.MatchingNodes.Front() == nil {
+ return "", fmt.Errorf("system operator: command expression returned no results")
+ }
+ if commandNodes.MatchingNodes.Len() > 1 {
+ log.Debugf("system operator: command expression returned %d results, using first", commandNodes.MatchingNodes.Len())
+ }
+ cmdNode := commandNodes.MatchingNodes.Front().Value.(*CandidateNode)
+ if cmdNode.Kind != ScalarNode || cmdNode.guessTagFromCustomType() != "!!str" {
+ return "", fmt.Errorf("system operator: command must be a string scalar")
+ }
+ if cmdNode.Value == "" {
+ return "", fmt.Errorf("system operator: command must be a non-empty string")
+ }
+ return cmdNode.Value, nil
+}
+
+func systemOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
+ if !ConfiguredSecurityPreferences.EnableSystemOps {
+ return Context{}, fmt.Errorf("system operations are disabled, use --security-enable-system-operator to enable")
+ }
+
+ // determine at parse time whether we have (command; args) or just (command)
+ hasArgs := expressionNode.RHS.Operation.OperationType == blockOpType
+
+ var results = list.New()
+
+ for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
+ candidate := el.Value.(*CandidateNode)
+ nodeContext := context.SingleReadonlyChildContext(candidate)
+
+ var command string
+ var args []string
+
+ if hasArgs {
+ block := expressionNode.RHS
+ commandNodes, err := d.GetMatchingNodes(nodeContext, block.LHS)
+ if err != nil {
+ return Context{}, err
+ }
+ command, err = resolveCommandNode(commandNodes)
+ if err != nil {
+ return Context{}, err
+ }
+
+ argsNodes, err := d.GetMatchingNodes(nodeContext, block.RHS)
+ if err != nil {
+ return Context{}, err
+ }
+ if argsNodes.MatchingNodes.Len() > 1 {
+ log.Debugf("system operator: args expression returned %d results, using first", argsNodes.MatchingNodes.Len())
+ }
+ if argsNodes.MatchingNodes.Front() != nil {
+ args, err = resolveSystemArgs(argsNodes.MatchingNodes.Front().Value.(*CandidateNode))
+ if err != nil {
+ return Context{}, err
+ }
+ }
+ } else {
+ commandNodes, err := d.GetMatchingNodes(nodeContext, expressionNode.RHS)
+ if err != nil {
+ return Context{}, err
+ }
+ command, err = resolveCommandNode(commandNodes)
+ if err != nil {
+ return Context{}, err
+ }
+ }
+
+ var stdin bytes.Buffer
+ encoded, err := encodeToYamlString(candidate)
+ if err != nil {
+ return Context{}, err
+ }
+ stdin.WriteString(encoded)
+
+ // #nosec G204 - intentional: user must explicitly enable this operator
+ cmd := exec.Command(command, args...)
+ cmd.Stdin = &stdin
+ var stderr bytes.Buffer
+ cmd.Stderr = &stderr
+
+ output, err := cmd.Output()
+ if err != nil {
+ stderrStr := strings.TrimSpace(stderr.String())
+ if stderrStr != "" {
+ return Context{}, fmt.Errorf("system command '%v' failed: %w\nstderr: %v", command, err, stderrStr)
+ }
+ return Context{}, fmt.Errorf("system command '%v' failed: %w", command, err)
+ }
+
+ result := string(output)
+ if strings.HasSuffix(result, "\r\n") {
+ result = result[:len(result)-2]
+ } else if strings.HasSuffix(result, "\n") {
+ result = result[:len(result)-1]
+ }
+ newNode := candidate.CreateReplacement(ScalarNode, "!!str", result)
+ results.PushBack(newNode)
+ }
+
+ return context.ChildContext(results), nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go
index 81b5eaf1170..b95f78f0ae1 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go
@@ -6,7 +6,7 @@ import (
func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- log.Debugf("AssignTagOperator: %v")
+ log.Debugf("AssignTagOperator")
tag := ""
if !expressionNode.Operation.UpdateAssign {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go
index aef22ce712b..1ed07572462 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go
@@ -3,6 +3,7 @@ package yqlib
import (
"container/list"
"fmt"
+ "slices"
"github.com/elliotchance/orderedmap"
)
@@ -13,6 +14,7 @@ type traversePreferences struct {
DontAutoCreate bool // by default, we automatically create entries on the fly.
DontIncludeMapValues bool
OptionalTraverse bool // e.g. .adf?
+ ExactKeyMatch bool // by default we let wild/glob patterns. Don't do that for merge though.
}
func splat(context Context, prefs traversePreferences) (Context, error) {
@@ -34,8 +36,32 @@ func traversePathOperator(_ *dataTreeNavigator, context Context, expressionNode
return context.ChildContext(matches), nil
}
+// resolveAliasChain follows an alias chain iteratively, returning the
+// first non-alias node. Returns an error if a cycle is detected.
+func resolveAliasChain(node *CandidateNode) (*CandidateNode, error) {
+ if node.Kind != AliasNode {
+ return node, nil
+ }
+ visited := map[*CandidateNode]bool{}
+ for node.Kind == AliasNode {
+ if visited[node] {
+ return nil, fmt.Errorf("alias cycle detected")
+ }
+ visited[node] = true
+ log.Debug("its an alias!")
+ node = node.Alias
+ }
+ return node, nil
+}
+
func traverse(context Context, matchingNode *CandidateNode, operation *Operation) (*list.List, error) {
- log.Debug("Traversing %v", NodeToString(matchingNode))
+ log.Debugf("Traversing %v", NodeToString(matchingNode))
+
+ var err error
+ matchingNode, err = resolveAliasChain(matchingNode)
+ if err != nil {
+ return nil, err
+ }
if matchingNode.Tag == "!!null" && operation.Value != "[]" && !context.DontAutoCreate {
log.Debugf("Guessing kind")
@@ -53,17 +79,13 @@ func traverse(context Context, matchingNode *CandidateNode, operation *Operation
switch matchingNode.Kind {
case MappingNode:
- log.Debug("its a map with %v entries", len(matchingNode.Content)/2)
+ log.Debugf("its a map with %v entries", len(matchingNode.Content)/2)
return traverseMap(context, matchingNode, createStringScalarNode(operation.StringValue), operation.Preferences.(traversePreferences), false)
case SequenceNode:
- log.Debug("its a sequence of %v things!", len(matchingNode.Content))
+ log.Debugf("its a sequence of %v things!", len(matchingNode.Content))
return traverseArray(matchingNode, operation, operation.Preferences.(traversePreferences))
- case AliasNode:
- log.Debug("its an alias!")
- matchingNode = matchingNode.Alias
- return traverse(context, matchingNode, operation)
default:
return list.New(), nil
}
@@ -77,7 +99,11 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
log.Debugf("--traverseArrayOperator")
if expressionNode.RHS != nil && expressionNode.RHS.RHS != nil && expressionNode.RHS.RHS.Operation.OperationType == createMapOpType {
- return sliceArrayOperator(d, context, expressionNode.RHS.RHS)
+ lhsContext, err := d.GetMatchingNodes(context, expressionNode.LHS)
+ if err != nil {
+ return Context{}, err
+ }
+ return sliceArrayOperator(d, lhsContext, expressionNode.RHS.RHS)
}
lhs, err := d.GetMatchingNodes(context, expressionNode.LHS)
@@ -123,7 +149,13 @@ func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*Candida
return context.ChildContext(matchingNodeMap), nil
}
-func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*CandidateNode, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse
+func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*CandidateNode, prefs traversePreferences) (*list.List, error) {
+ var err error
+ matchingNode, err = resolveAliasChain(matchingNode)
+ if err != nil {
+ return nil, err
+ }
+
if matchingNode.Tag == "!!null" {
log.Debugf("OperatorArrayTraverse got a null - turning it into an empty array")
// auto vivification
@@ -135,12 +167,10 @@ func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesT
}
}
- if matchingNode.Kind == AliasNode {
- matchingNode = matchingNode.Alias
- return traverseArrayIndices(context, matchingNode, indicesToTraverse, prefs)
- } else if matchingNode.Kind == SequenceNode {
+ switch matchingNode.Kind {
+ case SequenceNode:
return traverseArrayWithIndices(matchingNode, indicesToTraverse, prefs)
- } else if matchingNode.Kind == MappingNode {
+ case MappingNode:
return traverseMapWithIndices(context, matchingNode, indicesToTraverse, prefs)
}
log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, matchingNode.Tag)
@@ -155,7 +185,7 @@ func traverseMapWithIndices(context Context, candidate *CandidateNode, indices [
var matchingNodeMap = list.New()
for _, indexNode := range indices {
- log.Debug("traverseMapWithIndices: %v", indexNode.Value)
+ log.Debugf("traverseMapWithIndices: %v", indexNode.Value)
newNodes, err := traverseMap(context, candidate, indexNode, prefs, false)
if err != nil {
return nil, err
@@ -180,7 +210,7 @@ func traverseArrayWithIndices(node *CandidateNode, indices []*CandidateNode, pre
}
for _, indexNode := range indices {
- log.Debug("traverseArrayWithIndices: '%v'", indexNode.Value)
+ log.Debugf("traverseArrayWithIndices: '%v'", indexNode.Value)
index, err := parseInt(indexNode.Value)
if err != nil && prefs.OptionalTraverse {
continue
@@ -214,7 +244,11 @@ func traverseArrayWithIndices(node *CandidateNode, indices []*CandidateNode, pre
return newMatches, nil
}
-func keyMatches(key *CandidateNode, wantedKey string) bool {
+func keyMatches(key *CandidateNode, wantedKey string, exactKeyMatch bool) bool {
+ if exactKeyMatch {
+ // this is used for merge
+ return key.Value == wantedKey
+ }
return matchKey(key.Value, wantedKey)
}
@@ -264,26 +298,58 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, node *CandidateNode, wante
// if we don't find a match directly on this node first.
var contents = node.Content
- for index := 0; index < len(contents); index = index + 2 {
+
+ if !prefs.DontFollowAlias {
+ if ConfiguredYamlPreferences.FixMergeAnchorToSpec {
+ // First evaluate merge keys to make explicit keys take precedence, following spec
+ // We also iterate in reverse to make earlier merge keys take precedence,
+ // although normally there's just one '<<'
+ for index := len(node.Content) - 2; index >= 0; index -= 2 {
+ keyNode := node.Content[index]
+ valueNode := node.Content[index+1]
+ if keyNode.Tag == "!!merge" {
+ log.Debug("Merge anchor")
+ err := traverseMergeAnchor(newMatches, valueNode, wantedKey, prefs, splat)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+
+ for index := 0; index+1 < len(contents); index = index + 2 {
key := contents[index]
value := contents[index+1]
//skip the 'merge' tag, find a direct match first
- if key.Tag == "!!merge" && !prefs.DontFollowAlias && wantedKey != "<<" {
- log.Debug("Merge anchor")
- err := traverseMergeAnchor(newMatches, value, wantedKey, prefs, splat)
- if err != nil {
- return err
+ if key.Tag == "!!merge" && !prefs.DontFollowAlias && wantedKey != key.Value {
+ if !ConfiguredYamlPreferences.FixMergeAnchorToSpec {
+ log.Debug("Merge anchor")
+ if showMergeAnchorToSpecWarning {
+ log.Warning("--yaml-fix-merge-anchor-to-spec is false; causing merge anchors to override the existing values which isn't to the yaml spec. This flag will default to true in late 2025. See https://mikefarah.gitbook.io/yq/operators/traverse-read for more details.")
+ showMergeAnchorToSpecWarning = false
+ }
+ err := traverseMergeAnchor(newMatches, value, wantedKey, prefs, splat)
+ if err != nil {
+ return err
+ }
}
- } else if splat || keyMatches(key, wantedKey) {
+ } else if splat || keyMatches(key, wantedKey, prefs.ExactKeyMatch) {
log.Debug("MATCHED")
if prefs.IncludeMapKeys {
log.Debug("including key")
- newMatches.Set(key.GetKey(), key)
+ keyName := key.GetKey()
+ if !newMatches.Set(keyName, key) {
+ log.Debug("overwriting existing key")
+ }
}
if !prefs.DontIncludeMapValues {
log.Debug("including value")
- newMatches.Set(value.GetKey(), value)
+ valueName := value.GetKey()
+ if !newMatches.Set(valueName, value) {
+ log.Debug("overwriting existing value")
+ }
}
}
}
@@ -291,26 +357,43 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, node *CandidateNode, wante
return nil
}
-func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, value *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
- switch value.Kind {
- case AliasNode:
- if value.Alias.Kind != MappingNode {
- return fmt.Errorf("can only use merge anchors with maps (!!map), but got %v", value.Alias.Tag)
- }
- return doTraverseMap(newMatches, value.Alias, wantedKey, prefs, splat)
+func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, merge *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
+ if merge.Kind == AliasNode {
+ merge = merge.Alias
+ }
+ switch merge.Kind {
+ case MappingNode:
+ return doTraverseMap(newMatches, merge, wantedKey, prefs, splat)
case SequenceNode:
- for _, childValue := range value.Content {
- err := traverseMergeAnchor(newMatches, childValue, wantedKey, prefs, splat)
+ content := slices.All(merge.Content)
+ if ConfiguredYamlPreferences.FixMergeAnchorToSpec {
+ // Reverse to make earlier values take precedence, following spec
+ content = slices.Backward(merge.Content)
+ }
+ for _, childValue := range content {
+ if childValue.Kind == AliasNode {
+ childValue = childValue.Alias
+ }
+ if childValue.Kind != MappingNode {
+ log.Debugf(
+ "can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got sequence containing %v",
+ childValue.Tag)
+ return nil
+ }
+ err := doTraverseMap(newMatches, childValue, wantedKey, prefs, splat)
if err != nil {
return err
}
}
+ return nil
+ default:
+ log.Debugf("can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got %v", merge.Tag)
+ return nil
}
- return nil
}
func traverseArray(candidate *CandidateNode, operation *Operation, prefs traversePreferences) (*list.List, error) {
- log.Debug("operation Value %v", operation.Value)
+ log.Debugf("operation Value %v", operation.Value)
indices := []*CandidateNode{{Value: operation.StringValue}}
return traverseArrayWithIndices(candidate, indices, prefs)
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go
index 7190504cc13..a9976e6e39e 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go
@@ -4,21 +4,21 @@ import "container/list"
func unionOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debug("unionOperator--")
- log.Debug("unionOperator: context: %v", NodesToString(context.MatchingNodes))
+ log.Debugf("unionOperator: context: %v", NodesToString(context.MatchingNodes))
lhs, err := d.GetMatchingNodes(context, expressionNode.LHS)
if err != nil {
return Context{}, err
}
- log.Debug("unionOperator: lhs: %v", NodesToString(lhs.MatchingNodes))
- log.Debug("unionOperator: rhs input: %v", NodesToString(context.MatchingNodes))
- log.Debug("unionOperator: rhs: %v", expressionNode.RHS.Operation.toString())
+ log.Debugf("unionOperator: lhs: %v", NodesToString(lhs.MatchingNodes))
+ log.Debugf("unionOperator: rhs input: %v", NodesToString(context.MatchingNodes))
+ log.Debugf("unionOperator: rhs: %v", expressionNode.RHS.Operation.toString())
rhs, err := d.GetMatchingNodes(context, expressionNode.RHS)
if err != nil {
return Context{}, err
}
- log.Debug("unionOperator: lhs: %v", lhs.ToString())
- log.Debug("unionOperator: rhs: %v", rhs.ToString())
+ log.Debugf("unionOperator: lhs: %v", lhs.ToString())
+ log.Debugf("unionOperator: rhs: %v", rhs.ToString())
results := lhs.ChildContext(list.New())
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
@@ -33,11 +33,11 @@ func unionOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
- log.Debug("union operator rhs: processing %v", NodeToString(node))
+ log.Debugf("union operator rhs: processing %v", NodeToString(node))
results.MatchingNodes.PushBack(node)
}
}
- log.Debug("union operator: all together: %v", results.ToString())
+ log.Debugf("union operator: all together: %v", results.ToString())
return results, nil
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go
index 65438e8240e..e3e3cd86e0e 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go
@@ -7,7 +7,7 @@ func referenceOperator(_ *dataTreeNavigator, context Context, expressionNode *Ex
}
func valueOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- log.Debug("value = %v", expressionNode.Operation.CandidateNode.Value)
+ log.Debugf("value = %v", expressionNode.Operation.CandidateNode.Value)
if context.MatchingNodes.Len() == 0 {
clone := expressionNode.Operation.CandidateNode.Copy()
return context.SingleChildContext(clone), nil
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go
index d1c9c20ff96..0ba1bd62382 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go
@@ -7,7 +7,7 @@ import (
func getVariableOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
variableName := expressionNode.Operation.StringValue
- log.Debug("getVariableOperator %v", variableName)
+ log.Debugf("getVariableOperator %v", variableName)
result := context.GetVariable(variableName)
if result == nil {
result = list.New()
@@ -67,7 +67,7 @@ func variableLoopSingleChild(d *dataTreeNavigator, context Context, originalExp
// now we loop over lhs, set variable to each result and calculate originalExp.Rhs
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
- log.Debug("PROCESSING VARIABLE: ", NodeToString(el.Value.(*CandidateNode)))
+ log.Debugf("PROCESSING VARIABLE: %v", NodeToString(el.Value.(*CandidateNode)))
var variableValue = list.New()
if prefs.IsReference {
variableValue.PushBack(el.Value)
@@ -83,7 +83,7 @@ func variableLoopSingleChild(d *dataTreeNavigator, context Context, originalExp
if err != nil {
return Context{}, err
}
- log.Debug("PROCESSING VARIABLE DONE, got back: ", rhs.MatchingNodes.Len())
+ log.Debugf("PROCESSING VARIABLE DONE, got back: %v", rhs.MatchingNodes.Len())
results.PushBackList(rhs.MatchingNodes)
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operators.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operators.go
index 994a87673bd..35afe06d9d0 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operators.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/operators.go
@@ -3,9 +3,9 @@ package yqlib
import (
"container/list"
"fmt"
+ "log/slog"
"github.com/jinzhu/copier"
- logging "gopkg.in/op/go-logging.v1"
)
type operatorHandler func(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error)
@@ -88,7 +88,7 @@ func resultsForRHS(d *dataTreeNavigator, context Context, lhsCandidate *Candidat
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
rhsCandidate := rightEl.Value.(*CandidateNode)
- if !log.IsEnabledFor(logging.DEBUG) {
+ if !log.IsEnabledFor(slog.LevelDebug) {
log.Debugf("Applying lhs: %v, rhsCandidate, %v", NodeToString(lhsCandidate), NodeToString(rhsCandidate))
}
resultCandidate, err := prefs.Calculation(d, context, lhsCandidate, rhsCandidate)
@@ -118,7 +118,7 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
}
log.Debugf("crossFunction LHS len: %v", lhs.MatchingNodes.Len())
- if prefs.CalcWhenEmpty && lhs.MatchingNodes.Len() == 0 {
+ if prefs.CalcWhenEmpty && context.MatchingNodes.Len() > 0 && lhs.MatchingNodes.Len() == 0 {
err := resultsForRHS(d, context, nil, prefs, expressionNode.RHS, results)
if err != nil {
return Context{}, err
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer.go
index 61f653a88e8..19b66e18c6b 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer.go
@@ -70,7 +70,7 @@ func removeLastEOL(b *bytes.Buffer) {
}
func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
- log.Debug("PrintResults for %v matches", matchingNodes.Len())
+ log.Debugf("PrintResults for %v matches", matchingNodes.Len())
if matchingNodes.Len() == 0 {
log.Debug("no matching results, nothing to print")
@@ -97,8 +97,8 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
for el := matchingNodes.Front(); el != nil; el = el.Next() {
mappedDoc := el.Value.(*CandidateNode)
- log.Debug("print sep logic: p.firstTimePrinting: %v, previousDocIndex: %v", p.firstTimePrinting, p.previousDocIndex)
- log.Debug("%v", NodeToString(mappedDoc))
+ log.Debugf("print sep logic: p.firstTimePrinting: %v, previousDocIndex: %v", p.firstTimePrinting, p.previousDocIndex)
+ log.Debugf("%v", NodeToString(mappedDoc))
writer, errorWriting := p.printerWriter.GetWriter(mappedDoc)
if errorWriting != nil {
return errorWriting
@@ -132,7 +132,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
tempBufferBytes := tempBuffer.Bytes()
if bytes.IndexByte(tempBufferBytes, 0) != -1 {
return fmt.Errorf(
- "Can't serialize value because it contains NUL char and you are using NUL separated output",
+ "can't serialise value because it contains NUL char and you are using NUL separated output",
)
}
if _, err := writer.Write(tempBufferBytes); err != nil {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_node_info.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_node_info.go
new file mode 100644
index 00000000000..0bc8b09af23
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_node_info.go
@@ -0,0 +1,76 @@
+package yqlib
+
+import (
+ "bufio"
+ "container/list"
+ "io"
+
+ "go.yaml.in/yaml/v4"
+)
+
+type nodeInfoPrinter struct {
+ printerWriter PrinterWriter
+ appendixReader io.Reader
+ printedMatches bool
+}
+
+func NewNodeInfoPrinter(printerWriter PrinterWriter) Printer {
+ return &nodeInfoPrinter{
+ printerWriter: printerWriter,
+ }
+}
+
+func (p *nodeInfoPrinter) SetNulSepOutput(_ bool) {
+}
+
+func (p *nodeInfoPrinter) SetAppendix(reader io.Reader) {
+ p.appendixReader = reader
+}
+
+func (p *nodeInfoPrinter) PrintedAnything() bool {
+ return p.printedMatches
+}
+
+func (p *nodeInfoPrinter) PrintResults(matchingNodes *list.List) error {
+
+ for el := matchingNodes.Front(); el != nil; el = el.Next() {
+ mappedDoc := el.Value.(*CandidateNode)
+ writer, errorWriting := p.printerWriter.GetWriter(mappedDoc)
+ if errorWriting != nil {
+ return errorWriting
+ }
+ bytes, err := yaml.Marshal(mappedDoc.ConvertToNodeInfo())
+ if err != nil {
+ return err
+ }
+ if _, err := writer.Write(bytes); err != nil {
+ return err
+ }
+ if _, err := writer.Write([]byte("\n")); err != nil {
+ return err
+ }
+ p.printedMatches = true
+ if err := writer.Flush(); err != nil {
+ return err
+ }
+ }
+
+ if p.appendixReader != nil {
+ writer, err := p.printerWriter.GetWriter(nil)
+ if err != nil {
+ return err
+ }
+
+ log.Debug("Piping appendix reader...")
+ betterReader := bufio.NewReader(p.appendixReader)
+ _, err = io.Copy(writer, betterReader)
+ if err != nil {
+ return err
+ }
+ if err := writer.Flush(); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go
index b3e894663d3..88d60a0ff3b 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
+ "path/filepath"
"regexp"
)
@@ -70,6 +71,10 @@ func (sp *multiPrintWriter) GetWriter(node *CandidateNode) (*bufio.Writer, error
name = fmt.Sprintf("%v.%v", name, sp.extension)
}
+ err = os.MkdirAll(filepath.Dir(name), 0750)
+ if err != nil {
+ return nil, err
+ }
f, err := os.Create(name)
if err != nil {
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/security_prefs.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/security_prefs.go
new file mode 100644
index 00000000000..3c203014f2b
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/security_prefs.go
@@ -0,0 +1,13 @@
+package yqlib
+
+type SecurityPreferences struct {
+ DisableEnvOps bool
+ DisableFileOps bool
+ EnableSystemOps bool
+}
+
+var ConfiguredSecurityPreferences = SecurityPreferences{
+ DisableEnvOps: false,
+ DisableFileOps: false,
+ EnableSystemOps: false,
+}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/shellvariables.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/shellvariables.go
new file mode 100644
index 00000000000..d111a98ab8b
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/shellvariables.go
@@ -0,0 +1,15 @@
+package yqlib
+
+type ShellVariablesPreferences struct {
+ KeySeparator string
+ UnwrapScalar bool
+}
+
+func NewDefaultShellVariablesPreferences() ShellVariablesPreferences {
+ return ShellVariablesPreferences{
+ KeySeparator: "_",
+ UnwrapScalar: false,
+ }
+}
+
+var ConfiguredShellVariablesPreferences = NewDefaultShellVariablesPreferences()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go
index 0c9ad6dd4cf..ad1478941f0 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go
@@ -76,6 +76,7 @@ func (s *streamEvaluator) EvaluateFiles(expression string, filenames []string, p
}
func (s *streamEvaluator) Evaluate(filename string, reader io.Reader, node *ExpressionNode, printer Printer, decoder Decoder) (uint, error) {
+ filename = resolveFilename(filename)
var currentIndex uint
err := decoder.Init(reader)
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/toml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/toml.go
new file mode 100644
index 00000000000..4147954caa8
--- /dev/null
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/toml.go
@@ -0,0 +1,15 @@
+package yqlib
+
+type TomlPreferences struct {
+ ColorsEnabled bool
+}
+
+func NewDefaultTomlPreferences() TomlPreferences {
+ return TomlPreferences{ColorsEnabled: false}
+}
+
+func (p *TomlPreferences) Copy() TomlPreferences {
+ return TomlPreferences{ColorsEnabled: p.ColorsEnabled}
+}
+
+var ConfiguredTomlPreferences = NewDefaultTomlPreferences()
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/utils.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/utils.go
index 4424582ae0c..2843e42d283 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/utils.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/utils.go
@@ -9,6 +9,29 @@ import (
"os"
)
+// filenameAliases maps real file paths to display names.
+// Used by front matter handling to preserve original filenames
+// when the actual content is read from temporary files.
+var filenameAliases = map[string]string{}
+
+// SetFilenameAlias registers a display name for a file path so that
+// the filename operator returns the original name instead of a temp path.
+func SetFilenameAlias(realPath string, displayName string) {
+ filenameAliases[realPath] = displayName
+}
+
+// ClearFilenameAliases removes all filename aliases.
+func ClearFilenameAliases() {
+ filenameAliases = map[string]string{}
+}
+
+func resolveFilename(filename string) string {
+ if alias, ok := filenameAliases[filename]; ok {
+ return alias
+ }
+ return filename
+}
+
func readStream(filename string) (io.Reader, error) {
var reader *bufio.Reader
if filename == "-" {
@@ -36,6 +59,7 @@ func ReadDocuments(reader io.Reader, decoder Decoder) (*list.List, error) {
}
func readDocuments(reader io.Reader, filename string, fileIndex int, decoder Decoder) (*list.List, error) {
+ filename = resolveFilename(filename)
err := decoder.Init(reader)
if err != nil {
return nil, err
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go
index 83d42134963..1ca2d5dbab9 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go
@@ -38,13 +38,13 @@ func (w *writeInPlaceHandlerImpl) CreateTempFile() (*os.File, error) {
if err = changeOwner(info, file); err != nil {
return nil, err
}
- log.Debug("WriteInPlaceHandler: writing to tempfile: %v", file.Name())
+ log.Debugf("WriteInPlaceHandler: writing to tempfile: %v", file.Name())
w.tempFile = file
return file, err
}
func (w *writeInPlaceHandlerImpl) FinishWriteInPlace(evaluatedSuccessfully bool) error {
- log.Debug("Going to write in place, evaluatedSuccessfully=%v, target=%v", evaluatedSuccessfully, w.inputFilename)
+ log.Debugf("Going to write in place, evaluatedSuccessfully=%v, target=%v", evaluatedSuccessfully, w.inputFilename)
safelyCloseFile(w.tempFile)
if evaluatedSuccessfully {
log.Debug("Moving temp file to target")
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/yaml.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/yaml.go
index 079bc7495cb..9a185419a32 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/yaml.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/pkg/yqlib/yaml.go
@@ -7,6 +7,8 @@ type YamlPreferences struct {
PrintDocSeparators bool
UnwrapScalar bool
EvaluateTogether bool
+ FixMergeAnchorToSpec bool
+ CompactSequenceIndent bool
}
func NewDefaultYamlPreferences() YamlPreferences {
@@ -17,6 +19,8 @@ func NewDefaultYamlPreferences() YamlPreferences {
PrintDocSeparators: true,
UnwrapScalar: true,
EvaluateTogether: false,
+ FixMergeAnchorToSpec: false,
+ CompactSequenceIndent: false,
}
}
@@ -28,6 +32,8 @@ func (p *YamlPreferences) Copy() YamlPreferences {
PrintDocSeparators: p.PrintDocSeparators,
UnwrapScalar: p.UnwrapScalar,
EvaluateTogether: p.EvaluateTogether,
+ FixMergeAnchorToSpec: p.FixMergeAnchorToSpec,
+ CompactSequenceIndent: p.CompactSequenceIndent,
}
}
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/project-words.txt b/hack/tools/vendor/github.com/mikefarah/yq/v4/project-words.txt
index 808da2146f5..8f2fcf9e165 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/project-words.txt
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/project-words.txt
@@ -38,6 +38,8 @@ cleanup
cmlu
colorise
colors
+Colors
+colourize
compinit
coolioo
coverprofile
@@ -107,6 +109,7 @@ hostpath
hotdog
howdy
incase
+Infof
inlinetables
inplace
ints
@@ -189,8 +192,11 @@ risentveber
rmescandon
Rosey
roundtrip
+roundtrips
Roundtrip
roundtripping
+Interp
+interp
runningvms
sadface
selfupdate
@@ -255,4 +261,46 @@ zabbix
tonumber
noyaml
nolint
-shortfile
\ No newline at end of file
+shortfile
+Unmarshalling
+noini
+nocsv
+nobase64
+nouri
+noprops
+nosh
+noshell
+tinygo
+nonexistent
+hclsyntax
+hclwrite
+nohcl
+zclconf
+cty
+go-cty
+Colorisation
+goimports
+errorlint
+RDBMS
+expeñded
+bananabananabananabanana
+edwinjhlee
+flox
+unlabelled
+kyaml
+KYAML
+nokyaml
+buildvcs
+behaviour
+GOFLAGS
+gocache
+subsubarray
+Ffile
+Fquery
+coverpkg
+gsub
+ralia
+Austr
+ustrali
+héllo
+alia
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/release_instructions.txt b/hack/tools/vendor/github.com/mikefarah/yq/v4/release_instructions.txt
index 6b2fdf9d264..a32e1714e18 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/release_instructions.txt
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/release_instructions.txt
@@ -8,6 +8,15 @@
- git push --tags
- use github actions to publish docker and make github release
- check github updated yq action in marketplace
+- update github-action/Dockerfile to pin the newly published docker image digest:
+ skopeo inspect docker://docker.io/mikefarah/yq:4 | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['Digest'])"
+ then update the FROM line in github-action/Dockerfile with the new digest:
+ FROM mikefarah/yq:4@sha256:
+
+// release artifacts are signed with cosign keyless signing (Sigstore)
+// users can verify with:
+// cosign verify-blob --bundle checksums.bundle checksums
+// install cosign: brew install cosign OR go install github.com/sigstore/cosign/v2/cmd/cosign@latest
- snapcraft
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/release_notes.txt b/hack/tools/vendor/github.com/mikefarah/yq/v4/release_notes.txt
index a8700f1783c..12983f6e21d 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/release_notes.txt
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/release_notes.txt
@@ -1,3 +1,128 @@
+4.53.1:
+ - Releases now signed and immutable!
+ - Add system(command; args) operator (disabled by default) (#2640)
+ - TOML encoder: prefer readable table sections over inline tables (#2649)
+ - Fix TOML encoder to quote keys containing special characters (#2648)
+ - Add string slicing support (#2639)
+ - Fix findInArray misuse on MappingNodes in equality and contains (#2645) Thanks @jandubois!
+ - Fix panic on negative slice indices that underflow after adjustment (#2646) Thanks @jandubois!
+ - Fix stack overflow from circular alias in traverse (#2647) Thanks @jandubois!
+ - Fix panic and OOM in repeatString for large repeat counts (#2644) Thanks @jandubois!
+ - Bumped dependencies
+
+
+4.52.5:
+ - Fix: reset TOML decoder state between files (#2634) thanks @terminalchai
+ - Fix: preserve original filename when using --front-matter (#2613) thanks @cobyfrombrooklyn-bot
+ - Fix typo in filename (#2611) thanks @alexandear
+ - Bumped dependencies
+
+4.52.4:
+ - Dropping windows/arm - no longer supported in cross-compile
+
+4.52.3:
+ - Fixing comments in TOML arrays (#2592)
+ - Bumped dependencies
+
+
+4.52.2:
+ - Fixed bad instructions file breaking go-install (#2587) Thanks @theyoprst
+ - Fixed TOML table scope after comments (#2588) Thanks @tomers
+ - Multiply uses a readonly context (#2558)
+ - Fixed merge globbing wildcards in keys (#2564)
+ - Fixing TOML subarray parsing issue (#2581)
+
+4.52.1:
+ - TOML encoder support - you can now roundtrip! #1364
+ - Parent now supports negative indices, and added a 'root' command for referencing the top level document
+ - Fixed scalar encoding for HCL
+ - Add --yaml-compact-seq-indent / -c flag for compact sequence indentation (#2583) Thanks @jfenal
+ - Add symlink check to file rename util (#2576) Thanks @Elias-elastisys
+ - Powershell fixed default command used for __completeNoDesc alias (#2568) Thanks @teejaded
+ - Unwrap scalars in shell output mode. (#2548) Thanks @flintwinters
+ - Added K8S KYAML output format support (#2560) Thanks @robbat2
+
+ - Bumped dependencies
+ - Special shout out to @ccoVeille for reviewing my PRs!
+
+4.50.1:
+ - Added HCL support!
+ - Fixing handling of CRLF #2352
+ - Bumped dependencies
+
+4.49.2:
+ - Fixing escape character bugs :sweat: #2517
+ - Fixing snap release pipeline #2518 Thanks @aalexjo
+
+
+4.49.1:
+ - Added `--security` flags to disable env and file ops #2515
+ - Fixing TOML ArrayTable parsing issues #1758
+ - Fixing parsing of escaped characters #2506
+
+4.48.2:
+ - Strip whitespace when decoding base64 #2507
+ - Upgraded to go-yaml v4! (thanks @ccoVeille, @ingydotnet)
+ - Add linux/loong64 to release target (thanks @znley)
+ - Added --shell-key-separator flag for customizable shell output format #2497 (thanks @rsleedbx)
+ - Bumped dependencies
+
+4.48.1:
+ - Added 'parents' operator, to return a list of all the hierarchical parents of a node
+ - Added 'first(exp)' operator, to return the first entry matching an expression in an array
+ - Fixed xml namespace prefixes #1730 (thanks @baodrate)
+ - Fixed out of range panic in yaml decoder #2460 (thanks @n471d)
+ - Bumped dependencies
+
+4.47.2:
+ - Conversion from TOML to JSON no longer omits empty tables #2459 (thanks @louislouislouislouis)
+ - Bumped dependencies
+
+4.47.1:
+ - Fixed merge anchor behaviour (`<<`); #2404, #2110, #2386, #2178 Huge thanks to @stevenwdv!
+ Note that you will need to set --yaml-fix-merge-anchor-to-spec to see the fixes
+ - Fixed panic for syntax error when creating a map #2423
+ - Bumped dependencies
+
+4.46.1:
+ - Added INI support
+ - Fixed 'add' operator when piped in with no data #2378, #2383, #2384
+ - Fixed delete after slice problem (bad node path) #2387 Thanks @antoinedeschenes
+ - Fixed yq small build Thanks @imzue
+ - Switched to YAML org supported go-yaml!
+ - Bumped dependencies
+
+
+4.45.4:
+ - Fixing wrong map() behaviour on empty map #2359
+ - Bumped dependencies
+
+4.45.3:
+ - Fixing regression introduced with in 4.45.2 with #2325 fix :sweat: sorry folks!
+ - Bumped dependencies
+
+4.45.2:
+ - Added windows arm builds (Thanks @albertocavalcante, @ShukantPal)
+ - Added s390x platform support (Thanks @ashokpariya0)
+ - Additionally push docker images to ghcr.io (Thanks @reegnz)
+ - Fixing add when there is no node match #2325
+ - sort_by works on maps
+ - Bumped dependencies
+
+4.45.1:
+ - Create parent directories when --split-exp is used, Thanks @rudo-thomas
+ - Bumped dependencies
+
+4.44.6:
+ - Fixed deleting items in array bug #2027, #2172; Thanks @jandubois
+ - Docker image for armv7 / raspberry pi3, Thanks @brianegge
+ - Fixed no-colors regression #2218
+ - Fixed various panic scenarios #2211
+ - Bumped dependencies
+
+4.44.5:
+ - Fixing release pipeline
+
4.44.4:
- Format comments with a gray foreground (Thanks @gabe565)
- Fixed handling of nulls with sort_by expressions #2164
diff --git a/hack/tools/vendor/github.com/mikefarah/yq/v4/yq.go b/hack/tools/vendor/github.com/mikefarah/yq/v4/yq.go
index 239ff0fdca5..4572622a110 100644
--- a/hack/tools/vendor/github.com/mikefarah/yq/v4/yq.go
+++ b/hack/tools/vendor/github.com/mikefarah/yq/v4/yq.go
@@ -12,7 +12,7 @@ func main() {
args := os.Args[1:]
_, _, err := cmd.Find(args)
- if err != nil && args[0] != "__complete" {
+ if err != nil && args[0] != "__complete" && args[0] != "__completeNoDesc" {
// default command when nothing matches...
newArgs := []string{"eval"}
cmd.SetArgs(append(newArgs, os.Args[1:]...))
diff --git a/hack/tools/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md b/hack/tools/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md
new file mode 100644
index 00000000000..22985159044
--- /dev/null
+++ b/hack/tools/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mitchell Hashimoto
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/hack/tools/vendor/github.com/mitchellh/go-wordwrap/README.md b/hack/tools/vendor/github.com/mitchellh/go-wordwrap/README.md
new file mode 100644
index 00000000000..60ae3117008
--- /dev/null
+++ b/hack/tools/vendor/github.com/mitchellh/go-wordwrap/README.md
@@ -0,0 +1,39 @@
+# go-wordwrap
+
+`go-wordwrap` (Golang package: `wordwrap`) is a package for Go that
+automatically wraps words into multiple lines. The primary use case for this
+is in formatting CLI output, but of course word wrapping is a generally useful
+thing to do.
+
+## Installation and Usage
+
+Install using `go get github.com/mitchellh/go-wordwrap`.
+
+Full documentation is available at
+http://godoc.org/github.com/mitchellh/go-wordwrap
+
+Below is an example of its usage ignoring errors:
+
+```go
+wrapped := wordwrap.WrapString("foo bar baz", 3)
+fmt.Println(wrapped)
+```
+
+Would output:
+
+```
+foo
+bar
+baz
+```
+
+## Word Wrap Algorithm
+
+This library doesn't use any clever algorithm for word wrapping. The wrapping
+is actually very naive: whenever there is whitespace or an explicit linebreak.
+The goal of this library is for word wrapping CLI output, so the input is
+typically pretty well controlled human language. Because of this, the naive
+approach typically works just fine.
+
+In the future, we'd like to make the algorithm more advanced. We would do
+so without breaking the API.
diff --git a/hack/tools/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go b/hack/tools/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go
new file mode 100644
index 00000000000..f7bedda3882
--- /dev/null
+++ b/hack/tools/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go
@@ -0,0 +1,83 @@
+package wordwrap
+
+import (
+ "bytes"
+ "unicode"
+)
+
+const nbsp = 0xA0
+
+// WrapString wraps the given string within lim width in characters.
+//
+// Wrapping is currently naive and only happens at white-space. A future
+// version of the library will implement smarter wrapping. This means that
+// pathological cases can dramatically reach past the limit, such as a very
+// long word.
+func WrapString(s string, lim uint) string {
+ // Initialize a buffer with a slightly larger size to account for breaks
+ init := make([]byte, 0, len(s))
+ buf := bytes.NewBuffer(init)
+
+ var current uint
+ var wordBuf, spaceBuf bytes.Buffer
+ var wordBufLen, spaceBufLen uint
+
+ for _, char := range s {
+ if char == '\n' {
+ if wordBuf.Len() == 0 {
+ if current+spaceBufLen > lim {
+ current = 0
+ } else {
+ current += spaceBufLen
+ spaceBuf.WriteTo(buf)
+ }
+ spaceBuf.Reset()
+ spaceBufLen = 0
+ } else {
+ current += spaceBufLen + wordBufLen
+ spaceBuf.WriteTo(buf)
+ spaceBuf.Reset()
+ spaceBufLen = 0
+ wordBuf.WriteTo(buf)
+ wordBuf.Reset()
+ wordBufLen = 0
+ }
+ buf.WriteRune(char)
+ current = 0
+ } else if unicode.IsSpace(char) && char != nbsp {
+ if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
+ current += spaceBufLen + wordBufLen
+ spaceBuf.WriteTo(buf)
+ spaceBuf.Reset()
+ spaceBufLen = 0
+ wordBuf.WriteTo(buf)
+ wordBuf.Reset()
+ wordBufLen = 0
+ }
+
+ spaceBuf.WriteRune(char)
+ spaceBufLen++
+ } else {
+ wordBuf.WriteRune(char)
+ wordBufLen++
+
+ if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim {
+ buf.WriteRune('\n')
+ current = 0
+ spaceBuf.Reset()
+ spaceBufLen = 0
+ }
+ }
+ }
+
+ if wordBuf.Len() == 0 {
+ if current+spaceBufLen <= lim {
+ spaceBuf.WriteTo(buf)
+ }
+ } else {
+ spaceBuf.WriteTo(buf)
+ wordBuf.WriteTo(buf)
+ }
+
+ return buf.String()
+}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/.gitignore b/hack/tools/vendor/github.com/muesli/cancelreader/.gitignore
similarity index 100%
rename from hack/tools/vendor/github.com/muesli/termenv/.gitignore
rename to hack/tools/vendor/github.com/muesli/cancelreader/.gitignore
diff --git a/hack/tools/vendor/github.com/muesli/termenv/.golangci-soft.yml b/hack/tools/vendor/github.com/muesli/cancelreader/.golangci-soft.yml
similarity index 89%
rename from hack/tools/vendor/github.com/muesli/termenv/.golangci-soft.yml
rename to hack/tools/vendor/github.com/muesli/cancelreader/.golangci-soft.yml
index 84e3d41deb6..ef456e06059 100644
--- a/hack/tools/vendor/github.com/muesli/termenv/.golangci-soft.yml
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/.golangci-soft.yml
@@ -20,9 +20,10 @@ linters:
- goconst
- godot
- godox
- - mnd
+ - gomnd
- gomoddirectives
- goprintffuncname
+ - ifshort
# - lll
- misspell
- nakedret
@@ -34,10 +35,13 @@ linters:
# disable default linters, they are already enabled in .golangci.yml
disable:
+ - deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
+ - structcheck
- typecheck
- unused
+ - varcheck
diff --git a/hack/tools/vendor/github.com/muesli/termenv/.golangci.yml b/hack/tools/vendor/github.com/muesli/cancelreader/.golangci.yml
similarity index 94%
rename from hack/tools/vendor/github.com/muesli/termenv/.golangci.yml
rename to hack/tools/vendor/github.com/muesli/cancelreader/.golangci.yml
index 684d54bfa05..a5a91d0d913 100644
--- a/hack/tools/vendor/github.com/muesli/termenv/.golangci.yml
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/.golangci.yml
@@ -15,6 +15,7 @@ issues:
linters:
enable:
- bodyclose
+ - exportloopref
- goimports
- gosec
- nilerr
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/LICENSE b/hack/tools/vendor/github.com/muesli/cancelreader/LICENSE
new file mode 100644
index 00000000000..4b19b92d51f
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Erik Geiser and Christian Muehlhaeuser
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/README.md b/hack/tools/vendor/github.com/muesli/cancelreader/README.md
new file mode 100644
index 00000000000..83609fbc722
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/README.md
@@ -0,0 +1,64 @@
+# CancelReader
+
+[](https://github.com/muesli/cancelreader/releases)
+[](https://pkg.go.dev/github.com/muesli/cancelreader)
+[](/LICENSE)
+[](https://github.com/muesli/cancelreader/actions)
+[](https://goreportcard.com/report/muesli/cancelreader)
+
+A cancelable reader for Go
+
+This package is based on the fantastic work of [Erik Geiser](https://github.com/erikgeiser)
+in Charm's [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework.
+
+## Usage
+
+`NewReader` returns a reader with a `Cancel` function. If the input reader is a
+`File`, the cancel function can be used to interrupt a blocking `Read` call.
+In this case, the cancel function returns true if the call was canceled
+successfully. If the input reader is not a `File`, the cancel function does
+nothing and always returns false.
+
+```go
+r, err := cancelreader.NewReader(file)
+if err != nil {
+ // handle error
+ ...
+}
+
+// cancel after five seconds
+go func() {
+ time.Sleep(5 * time.Second)
+ r.Cancel()
+}()
+
+// keep reading
+for {
+ var buf [1024]byte
+ _, err := r.Read(buf[:])
+
+ if errors.Is(err, cancelreader.ErrCanceled) {
+ fmt.Println("canceled!")
+ break
+ }
+ if err != nil {
+ // handle other errors
+ ...
+ }
+
+ // handle data
+ ...
+}
+```
+
+## Implementations
+
+- The Linux implementation is based on the epoll mechanism
+- The BSD and macOS implementation is based on the kqueue mechanism
+- The generic Unix implementation is based on the posix select syscall
+
+## Caution
+
+The Windows implementation is based on WaitForMultipleObject with overlapping
+reads from CONIN$. At this point it only supports canceling reads from
+`os.Stdin`.
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader.go
new file mode 100644
index 00000000000..18d38255318
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader.go
@@ -0,0 +1,93 @@
+package cancelreader
+
+import (
+ "fmt"
+ "io"
+ "sync"
+)
+
+// ErrCanceled gets returned when trying to read from a canceled reader.
+var ErrCanceled = fmt.Errorf("read canceled")
+
+// CancelReader is a io.Reader whose Read() calls can be canceled without data
+// being consumed. The cancelReader has to be closed.
+type CancelReader interface {
+ io.ReadCloser
+
+ // Cancel cancels ongoing and future reads an returns true if it succeeded.
+ Cancel() bool
+}
+
+// File represents an input/output resource with a file descriptor.
+type File interface {
+ io.ReadWriteCloser
+
+ // Fd returns its file descriptor
+ Fd() uintptr
+
+ // Name returns its file name.
+ Name() string
+}
+
+// fallbackCancelReader implements cancelReader but does not actually support
+// cancelation during an ongoing Read() call. Thus, Cancel() always returns
+// false. However, after calling Cancel(), new Read() calls immediately return
+// errCanceled and don't consume any data anymore.
+type fallbackCancelReader struct {
+ r io.Reader
+ cancelMixin
+}
+
+// newFallbackCancelReader is a fallback for NewReader that cannot actually
+// cancel an ongoing read but will immediately return on future reads if it has
+// been canceled.
+func newFallbackCancelReader(reader io.Reader) (CancelReader, error) {
+ return &fallbackCancelReader{r: reader}, nil
+}
+
+func (r *fallbackCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ n, err := r.r.Read(data)
+ /*
+ If the underlying reader is a blocking reader (e.g. an open connection),
+ it might happen that 1 goroutine cancels the reader while its stuck in
+ the read call waiting for something.
+ If that happens, we should still cancel the read.
+ */
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+ return n, err // nolint: wrapcheck
+}
+
+func (r *fallbackCancelReader) Cancel() bool {
+ r.setCanceled()
+ return false
+}
+
+func (r *fallbackCancelReader) Close() error {
+ return nil
+}
+
+// cancelMixin represents a goroutine-safe cancelation status.
+type cancelMixin struct {
+ unsafeCanceled bool
+ lock sync.Mutex
+}
+
+func (c *cancelMixin) isCanceled() bool {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ return c.unsafeCanceled
+}
+
+func (c *cancelMixin) setCanceled() {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ c.unsafeCanceled = true
+}
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go
new file mode 100644
index 00000000000..3ddb6cff0b3
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go
@@ -0,0 +1,146 @@
+//go:build darwin || freebsd || netbsd || openbsd || dragonfly
+// +build darwin freebsd netbsd openbsd dragonfly
+
+package cancelreader
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File, the cancel function can be used to interrupt a blocking read call.
+// In this case, the cancel function returns true if the call was canceled
+// successfully. If the input reader is not a File, the cancel function
+// does nothing and always returns false. The BSD and macOS implementation is
+// based on the kqueue mechanism.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ file, ok := reader.(File)
+ if !ok {
+ return newFallbackCancelReader(reader)
+ }
+
+ // kqueue returns instantly when polling /dev/tty so fallback to select
+ if file.Name() == "/dev/tty" {
+ return newSelectCancelReader(reader)
+ }
+
+ kQueue, err := unix.Kqueue()
+ if err != nil {
+ return nil, fmt.Errorf("create kqueue: %w", err)
+ }
+
+ r := &kqueueCancelReader{
+ file: file,
+ kQueue: kQueue,
+ }
+
+ r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe()
+ if err != nil {
+ _ = unix.Close(kQueue)
+ return nil, err
+ }
+
+ unix.SetKevent(&r.kQueueEvents[0], int(file.Fd()), unix.EVFILT_READ, unix.EV_ADD)
+ unix.SetKevent(&r.kQueueEvents[1], int(r.cancelSignalReader.Fd()), unix.EVFILT_READ, unix.EV_ADD)
+
+ return r, nil
+}
+
+type kqueueCancelReader struct {
+ file File
+ cancelSignalReader File
+ cancelSignalWriter File
+ cancelMixin
+ kQueue int
+ kQueueEvents [2]unix.Kevent_t
+}
+
+func (r *kqueueCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ err := r.wait()
+ if err != nil {
+ if errors.Is(err, ErrCanceled) {
+ // remove signal from pipe
+ var b [1]byte
+ _, errRead := r.cancelSignalReader.Read(b[:])
+ if errRead != nil {
+ return 0, fmt.Errorf("reading cancel signal: %w", errRead)
+ }
+ }
+
+ return 0, err
+ }
+
+ return r.file.Read(data)
+}
+
+func (r *kqueueCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ // send cancel signal
+ _, err := r.cancelSignalWriter.Write([]byte{'c'})
+ return err == nil
+}
+
+func (r *kqueueCancelReader) Close() error {
+ var errMsgs []string
+
+ // close kqueue
+ err := unix.Close(r.kQueue)
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing kqueue: %v", err))
+ }
+
+ // close pipe
+ err = r.cancelSignalWriter.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err))
+ }
+
+ err = r.cancelSignalReader.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err))
+ }
+
+ if len(errMsgs) > 0 {
+ return fmt.Errorf(strings.Join(errMsgs, ", "))
+ }
+
+ return nil
+}
+
+func (r *kqueueCancelReader) wait() error {
+ events := make([]unix.Kevent_t, 1)
+
+ for {
+ _, err := unix.Kevent(r.kQueue, r.kQueueEvents[:], events, nil)
+ if errors.Is(err, unix.EINTR) {
+ continue // try again if the syscall was interrupted
+ }
+
+ if err != nil {
+ return fmt.Errorf("kevent: %w", err)
+ }
+
+ break
+ }
+
+ ident := uint64(events[0].Ident)
+ switch ident {
+ case uint64(r.file.Fd()):
+ return nil
+ case uint64(r.cancelSignalReader.Fd()):
+ return ErrCanceled
+ }
+
+ return fmt.Errorf("unknown error")
+}
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_default.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_default.go
new file mode 100644
index 00000000000..8e275fa4411
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_default.go
@@ -0,0 +1,12 @@
+//go:build !darwin && !windows && !linux && !solaris && !freebsd && !netbsd && !openbsd && !dragonfly
+// +build !darwin,!windows,!linux,!solaris,!freebsd,!netbsd,!openbsd,!dragonfly
+
+package cancelreader
+
+import "io"
+
+// NewReader returns a fallbackCancelReader that satisfies the CancelReader but
+// does not actually support cancellation.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ return newFallbackCancelReader(reader)
+}
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_linux.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_linux.go
new file mode 100644
index 00000000000..09f7369f31a
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_linux.go
@@ -0,0 +1,154 @@
+//go:build linux
+// +build linux
+
+package cancelreader
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File, the cancel function can be used to interrupt a blocking read call.
+// In this case, the cancel function returns true if the call was canceled
+// successfully. If the input reader is not a File, the cancel function
+// does nothing and always returns false. The Linux implementation is based on
+// the epoll mechanism.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ file, ok := reader.(File)
+ if !ok {
+ return newFallbackCancelReader(reader)
+ }
+
+ epoll, err := unix.EpollCreate1(0)
+ if err != nil {
+ return nil, fmt.Errorf("create epoll: %w", err)
+ }
+
+ r := &epollCancelReader{
+ file: file,
+ epoll: epoll,
+ }
+
+ r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe()
+ if err != nil {
+ _ = unix.Close(epoll)
+ return nil, err
+ }
+
+ err = unix.EpollCtl(epoll, unix.EPOLL_CTL_ADD, int(file.Fd()), &unix.EpollEvent{
+ Events: unix.EPOLLIN,
+ Fd: int32(file.Fd()),
+ })
+ if err != nil {
+ _ = unix.Close(epoll)
+ return nil, fmt.Errorf("add reader to epoll interest list")
+ }
+
+ err = unix.EpollCtl(epoll, unix.EPOLL_CTL_ADD, int(r.cancelSignalReader.Fd()), &unix.EpollEvent{
+ Events: unix.EPOLLIN,
+ Fd: int32(r.cancelSignalReader.Fd()),
+ })
+ if err != nil {
+ _ = unix.Close(epoll)
+ return nil, fmt.Errorf("add reader to epoll interest list")
+ }
+
+ return r, nil
+}
+
+type epollCancelReader struct {
+ file File
+ cancelSignalReader File
+ cancelSignalWriter File
+ cancelMixin
+ epoll int
+}
+
+func (r *epollCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ err := r.wait()
+ if err != nil {
+ if errors.Is(err, ErrCanceled) {
+ // remove signal from pipe
+ var b [1]byte
+ _, readErr := r.cancelSignalReader.Read(b[:])
+ if readErr != nil {
+ return 0, fmt.Errorf("reading cancel signal: %w", readErr)
+ }
+ }
+
+ return 0, err
+ }
+
+ return r.file.Read(data)
+}
+
+func (r *epollCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ // send cancel signal
+ _, err := r.cancelSignalWriter.Write([]byte{'c'})
+ return err == nil
+}
+
+func (r *epollCancelReader) Close() error {
+ var errMsgs []string
+
+ // close kqueue
+ err := unix.Close(r.epoll)
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing epoll: %v", err))
+ }
+
+ // close pipe
+ err = r.cancelSignalWriter.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err))
+ }
+
+ err = r.cancelSignalReader.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err))
+ }
+
+ if len(errMsgs) > 0 {
+ return fmt.Errorf(strings.Join(errMsgs, ", "))
+ }
+
+ return nil
+}
+
+func (r *epollCancelReader) wait() error {
+ events := make([]unix.EpollEvent, 1)
+
+ for {
+ _, err := unix.EpollWait(r.epoll, events, -1)
+ if errors.Is(err, unix.EINTR) {
+ continue // try again if the syscall was interrupted
+ }
+
+ if err != nil {
+ return fmt.Errorf("kevent: %w", err)
+ }
+
+ break
+ }
+
+ switch events[0].Fd {
+ case int32(r.file.Fd()):
+ return nil
+ case int32(r.cancelSignalReader.Fd()):
+ return ErrCanceled
+ }
+
+ return fmt.Errorf("unknown error")
+}
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_select.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_select.go
new file mode 100644
index 00000000000..03f2a3e1e95
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_select.go
@@ -0,0 +1,136 @@
+//go:build solaris || darwin || freebsd || netbsd || openbsd || dragonfly
+// +build solaris darwin freebsd netbsd openbsd dragonfly
+
+package cancelreader
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+// newSelectCancelReader returns a reader and a cancel function. If the input
+// reader is a File, the cancel function can be used to interrupt a
+// blocking call read call. In this case, the cancel function returns true if
+// the call was canceled successfully. If the input reader is not a File or
+// the file descriptor is 1024 or larger, the cancel function does nothing and
+// always returns false. The generic unix implementation is based on the posix
+// select syscall.
+func newSelectCancelReader(reader io.Reader) (CancelReader, error) {
+ file, ok := reader.(File)
+ if !ok || file.Fd() >= unix.FD_SETSIZE {
+ return newFallbackCancelReader(reader)
+ }
+ r := &selectCancelReader{file: file}
+
+ var err error
+
+ r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe()
+ if err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
+
+type selectCancelReader struct {
+ file File
+ cancelSignalReader File
+ cancelSignalWriter File
+ cancelMixin
+}
+
+func (r *selectCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ for {
+ err := waitForRead(r.file, r.cancelSignalReader)
+ if err != nil {
+ if errors.Is(err, unix.EINTR) {
+ continue // try again if the syscall was interrupted
+ }
+
+ if errors.Is(err, ErrCanceled) {
+ // remove signal from pipe
+ var b [1]byte
+ _, readErr := r.cancelSignalReader.Read(b[:])
+ if readErr != nil {
+ return 0, fmt.Errorf("reading cancel signal: %w", readErr)
+ }
+ }
+
+ return 0, err
+ }
+
+ return r.file.Read(data)
+ }
+}
+
+func (r *selectCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ // send cancel signal
+ _, err := r.cancelSignalWriter.Write([]byte{'c'})
+ return err == nil
+}
+
+func (r *selectCancelReader) Close() error {
+ var errMsgs []string
+
+ // close pipe
+ err := r.cancelSignalWriter.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err))
+ }
+
+ err = r.cancelSignalReader.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err))
+ }
+
+ if len(errMsgs) > 0 {
+ return fmt.Errorf(strings.Join(errMsgs, ", "))
+ }
+
+ return nil
+}
+
+func waitForRead(reader, abort File) error {
+ readerFd := int(reader.Fd())
+ abortFd := int(abort.Fd())
+
+ maxFd := readerFd
+ if abortFd > maxFd {
+ maxFd = abortFd
+ }
+
+ // this is a limitation of the select syscall
+ if maxFd >= unix.FD_SETSIZE {
+ return fmt.Errorf("cannot select on file descriptor %d which is larger than 1024", maxFd)
+ }
+
+ fdSet := &unix.FdSet{}
+ fdSet.Set(int(reader.Fd()))
+ fdSet.Set(int(abort.Fd()))
+
+ _, err := unix.Select(maxFd+1, fdSet, nil, nil, nil)
+ if err != nil {
+ return fmt.Errorf("select: %w", err)
+ }
+
+ if fdSet.IsSet(abortFd) {
+ return ErrCanceled
+ }
+
+ if fdSet.IsSet(readerFd) {
+ return nil
+ }
+
+ return fmt.Errorf("select returned without setting a file descriptor")
+}
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_unix.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_unix.go
new file mode 100644
index 00000000000..3c10ee09e24
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_unix.go
@@ -0,0 +1,18 @@
+//go:build solaris
+// +build solaris
+
+package cancelreader
+
+import (
+ "io"
+)
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File, the cancel function can be used to interrupt a blocking read call.
+// In this case, the cancel function returns true if the call was canceled
+// successfully. If the input reader is not a File or the file descriptor
+// is 1024 or larger, the cancel function does nothing and always returns false.
+// The generic unix implementation is based on the posix select syscall.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ return newSelectCancelReader(reader)
+}
diff --git a/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_windows.go b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_windows.go
new file mode 100644
index 00000000000..c1dc8d500cc
--- /dev/null
+++ b/hack/tools/vendor/github.com/muesli/cancelreader/cancelreader_windows.go
@@ -0,0 +1,244 @@
+//go:build windows
+// +build windows
+
+package cancelreader
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "syscall"
+ "time"
+ "unicode/utf16"
+
+ "golang.org/x/sys/windows"
+)
+
+var fileShareValidFlags uint32 = 0x00000007
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File with the same file descriptor as os.Stdin, the cancel function can
+// be used to interrupt a blocking read call. In this case, the cancel function
+// returns true if the call was canceled successfully. If the input reader is
+// not a File with the same file descriptor as os.Stdin, the cancel
+// function does nothing and always returns false. The Windows implementation
+// is based on WaitForMultipleObject with overlapping reads from CONIN$.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ if f, ok := reader.(File); !ok || f.Fd() != os.Stdin.Fd() {
+ return newFallbackCancelReader(reader)
+ }
+
+ // it is necessary to open CONIN$ (NOT windows.STD_INPUT_HANDLE) in
+ // overlapped mode to be able to use it with WaitForMultipleObjects.
+ conin, err := windows.CreateFile(
+ &(utf16.Encode([]rune("CONIN$\x00"))[0]), windows.GENERIC_READ|windows.GENERIC_WRITE,
+ fileShareValidFlags, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0)
+ if err != nil {
+ return nil, fmt.Errorf("open CONIN$ in overlapping mode: %w", err)
+ }
+
+ resetConsole, err := prepareConsole(conin)
+ if err != nil {
+ return nil, fmt.Errorf("prepare console: %w", err)
+ }
+
+ // flush input, otherwise it can contain events which trigger
+ // WaitForMultipleObjects but which ReadFile cannot read, resulting in an
+ // un-cancelable read
+ err = flushConsoleInputBuffer(conin)
+ if err != nil {
+ return nil, fmt.Errorf("flush console input buffer: %w", err)
+ }
+
+ cancelEvent, err := windows.CreateEvent(nil, 0, 0, nil)
+ if err != nil {
+ return nil, fmt.Errorf("create stop event: %w", err)
+ }
+
+ return &winCancelReader{
+ conin: conin,
+ cancelEvent: cancelEvent,
+ resetConsole: resetConsole,
+ blockingReadSignal: make(chan struct{}, 1),
+ }, nil
+}
+
+type winCancelReader struct {
+ conin windows.Handle
+ cancelEvent windows.Handle
+ cancelMixin
+
+ resetConsole func() error
+ blockingReadSignal chan struct{}
+}
+
+func (r *winCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ err := r.wait()
+ if err != nil {
+ return 0, err
+ }
+
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ // windows.Read does not work on overlapping windows.Handles
+ return r.readAsync(data)
+}
+
+// Cancel cancels ongoing and future Read() calls and returns true if the
+// cancelation of the ongoing Read() was successful. On Windows Terminal,
+// WaitForMultipleObjects sometimes immediately returns without input being
+// available. In this case, graceful cancelation is not possible and Cancel()
+// returns false.
+func (r *winCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ select {
+ case r.blockingReadSignal <- struct{}{}:
+ err := windows.SetEvent(r.cancelEvent)
+ if err != nil {
+ return false
+ }
+ <-r.blockingReadSignal
+ case <-time.After(100 * time.Millisecond):
+ // Read() hangs in a GetOverlappedResult which is likely due to
+ // WaitForMultipleObjects returning without input being available
+ // so we cannot cancel this ongoing read.
+ return false
+ }
+
+ return true
+}
+
+func (r *winCancelReader) Close() error {
+ err := windows.CloseHandle(r.cancelEvent)
+ if err != nil {
+ return fmt.Errorf("closing cancel event handle: %w", err)
+ }
+
+ err = r.resetConsole()
+ if err != nil {
+ return err
+ }
+
+ err = windows.Close(r.conin)
+ if err != nil {
+ return fmt.Errorf("closing CONIN$")
+ }
+
+ return nil
+}
+
+func (r *winCancelReader) wait() error {
+ event, err := windows.WaitForMultipleObjects([]windows.Handle{r.conin, r.cancelEvent}, false, windows.INFINITE)
+ switch {
+ case windows.WAIT_OBJECT_0 <= event && event < windows.WAIT_OBJECT_0+2:
+ if event == windows.WAIT_OBJECT_0+1 {
+ return ErrCanceled
+ }
+
+ if event == windows.WAIT_OBJECT_0 {
+ return nil
+ }
+
+ return fmt.Errorf("unexpected wait object is ready: %d", event-windows.WAIT_OBJECT_0)
+ case windows.WAIT_ABANDONED <= event && event < windows.WAIT_ABANDONED+2:
+ return fmt.Errorf("abandoned")
+ case event == uint32(windows.WAIT_TIMEOUT):
+ return fmt.Errorf("timeout")
+ case event == windows.WAIT_FAILED:
+ return fmt.Errorf("failed")
+ default:
+ return fmt.Errorf("unexpected error: %w", error(err))
+ }
+}
+
+// readAsync is necessary to read from a windows.Handle in overlapping mode.
+func (r *winCancelReader) readAsync(data []byte) (int, error) {
+ hevent, err := windows.CreateEvent(nil, 0, 0, nil)
+ if err != nil {
+ return 0, fmt.Errorf("create event: %w", err)
+ }
+
+ overlapped := windows.Overlapped{
+ HEvent: hevent,
+ }
+
+ var n uint32
+
+ err = windows.ReadFile(r.conin, data, &n, &overlapped)
+ if err != nil && err != windows.ERROR_IO_PENDING {
+ return int(n), err
+ }
+
+ r.blockingReadSignal <- struct{}{}
+ err = windows.GetOverlappedResult(r.conin, &overlapped, &n, true)
+ if err != nil {
+ return int(n), nil
+ }
+ <-r.blockingReadSignal
+
+ return int(n), nil
+}
+
+func prepareConsole(input windows.Handle) (reset func() error, err error) {
+ var originalMode uint32
+
+ err = windows.GetConsoleMode(input, &originalMode)
+ if err != nil {
+ return nil, fmt.Errorf("get console mode: %w", err)
+ }
+
+ var newMode uint32
+ newMode &^= windows.ENABLE_ECHO_INPUT
+ newMode &^= windows.ENABLE_LINE_INPUT
+ newMode &^= windows.ENABLE_MOUSE_INPUT
+ newMode &^= windows.ENABLE_WINDOW_INPUT
+ newMode &^= windows.ENABLE_PROCESSED_INPUT
+
+ newMode |= windows.ENABLE_EXTENDED_FLAGS
+ newMode |= windows.ENABLE_INSERT_MODE
+ newMode |= windows.ENABLE_QUICK_EDIT_MODE
+
+ // Enabling virtual terminal input is necessary for processing certain
+ // types of input like X10 mouse events and arrows keys with the current
+ // bytes-based input reader. It does, however, prevent cancelReader from
+ // being able to cancel input. The planned solution for this is to read
+ // Windows events in a more native fashion, rather than the current simple
+ // bytes-based input reader which works well on unix systems.
+ newMode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
+
+ err = windows.SetConsoleMode(input, newMode)
+ if err != nil {
+ return nil, fmt.Errorf("set console mode: %w", err)
+ }
+
+ return func() error {
+ err := windows.SetConsoleMode(input, originalMode)
+ if err != nil {
+ return fmt.Errorf("reset console mode: %w", err)
+ }
+
+ return nil
+ }, nil
+}
+
+var (
+ modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
+ procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
+)
+
+func flushConsoleInputBuffer(consoleInput windows.Handle) error {
+ r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1,
+ uintptr(consoleInput), 0, 0)
+ if r == 0 {
+ return error(e)
+ }
+
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/README.md b/hack/tools/vendor/github.com/muesli/termenv/README.md
deleted file mode 100644
index fa7929d4e9c..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/README.md
+++ /dev/null
@@ -1,431 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-`termenv` lets you safely use advanced styling options on the terminal. It
-gathers information about the terminal environment in terms of its ANSI & color
-support and offers you convenient methods to colorize and style your output,
-without you having to deal with all kinds of weird ANSI escape sequences and
-color conversions.
-
-## Features
-
-- RGB/TrueColor support
-- Detects the supported color range of your terminal
-- Automatically converts colors to the best matching, available colors
-- Terminal theme (light/dark) detection
-- Chainable syntax
-- Nested styles
-
-## Installation
-
-```bash
-go get github.com/muesli/termenv
-```
-
-## Usage
-
-```go
-output := termenv.NewOutput(os.Stdout)
-```
-
-`termenv` queries the terminal's capabilities it is running in, so you can
-safely use advanced features, like RGB colors or ANSI styles. `output.Profile`
-returns the supported profile:
-
-- `termenv.Ascii` - no ANSI support detected, ASCII only
-- `termenv.ANSI` - 16 color ANSI support
-- `termenv.ANSI256` - Extended 256 color ANSI support
-- `termenv.TrueColor` - RGB/TrueColor support
-
-Alternatively, you can use `termenv.EnvColorProfile` which evaluates the
-terminal like `ColorProfile`, but also respects the `NO_COLOR` and
-`CLICOLOR_FORCE` environment variables.
-
-You can also query the terminal for its color scheme, so you know whether your
-app is running in a light- or dark-themed environment:
-
-```go
-// Returns terminal's foreground color
-color := output.ForegroundColor()
-
-// Returns terminal's background color
-color := output.BackgroundColor()
-
-// Returns whether terminal uses a dark-ish background
-darkTheme := output.HasDarkBackground()
-```
-
-### Manual Profile Selection
-
-If you don't want to rely on the automatic detection, you can manually select
-the profile you want to use:
-
-```go
-output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor))
-```
-
-## Colors
-
-`termenv` supports multiple color profiles: Ascii (black & white only),
-ANSI (16 colors), ANSI Extended (256 colors), and TrueColor (24-bit RGB). Colors
-will automatically be degraded to the best matching available color in the
-desired profile:
-
-`TrueColor` => `ANSI 256 Colors` => `ANSI 16 Colors` => `Ascii`
-
-```go
-s := output.String("Hello World")
-
-// Supports hex values
-// Will automatically degrade colors on terminals not supporting RGB
-s.Foreground(output.Color("#abcdef"))
-// but also supports ANSI colors (0-255)
-s.Background(output.Color("69"))
-// ...or the color.Color interface
-s.Foreground(output.FromColor(color.RGBA{255, 128, 0, 255}))
-
-// Combine fore- & background colors
-s.Foreground(output.Color("#ffffff")).Background(output.Color("#0000ff"))
-
-// Supports the fmt.Stringer interface
-fmt.Println(s)
-```
-
-## Styles
-
-You can use a chainable syntax to compose your own styles:
-
-```go
-s := output.String("foobar")
-
-// Text styles
-s.Bold()
-s.Faint()
-s.Italic()
-s.CrossOut()
-s.Underline()
-s.Overline()
-
-// Reverse swaps current fore- & background colors
-s.Reverse()
-
-// Blinking text
-s.Blink()
-
-// Combine multiple options
-s.Bold().Underline()
-```
-
-## Template Helpers
-
-`termenv` provides a set of helper functions to style your Go templates:
-
-```go
-// load template helpers
-f := output.TemplateFuncs()
-tpl := template.New("tpl").Funcs(f)
-
-// apply bold style in a template
-bold := `{{ Bold "Hello World" }}`
-
-// examples for colorized templates
-col := `{{ Color "#ff0000" "#0000ff" "Red on Blue" }}`
-fg := `{{ Foreground "#ff0000" "Red Foreground" }}`
-bg := `{{ Background "#0000ff" "Blue Background" }}`
-
-// wrap styles
-wrap := `{{ Bold (Underline "Hello World") }}`
-
-// parse and render
-tpl, err = tpl.Parse(bold)
-
-var buf bytes.Buffer
-tpl.Execute(&buf, nil)
-fmt.Println(&buf)
-```
-
-Other available helper functions are: `Faint`, `Italic`, `CrossOut`,
-`Underline`, `Overline`, `Reverse`, and `Blink`.
-
-## Positioning
-
-```go
-// Move the cursor to a given position
-output.MoveCursor(row, column)
-
-// Save the cursor position
-output.SaveCursorPosition()
-
-// Restore a saved cursor position
-output.RestoreCursorPosition()
-
-// Move the cursor up a given number of lines
-output.CursorUp(n)
-
-// Move the cursor down a given number of lines
-output.CursorDown(n)
-
-// Move the cursor up a given number of lines
-output.CursorForward(n)
-
-// Move the cursor backwards a given number of cells
-output.CursorBack(n)
-
-// Move the cursor down a given number of lines and place it at the beginning
-// of the line
-output.CursorNextLine(n)
-
-// Move the cursor up a given number of lines and place it at the beginning of
-// the line
-output.CursorPrevLine(n)
-```
-
-## Screen
-
-```go
-// Reset the terminal to its default style, removing any active styles
-output.Reset()
-
-// RestoreScreen restores a previously saved screen state
-output.RestoreScreen()
-
-// SaveScreen saves the screen state
-output.SaveScreen()
-
-// Switch to the altscreen. The former view can be restored with ExitAltScreen()
-output.AltScreen()
-
-// Exit the altscreen and return to the former terminal view
-output.ExitAltScreen()
-
-// Clear the visible portion of the terminal
-output.ClearScreen()
-
-// Clear the current line
-output.ClearLine()
-
-// Clear a given number of lines
-output.ClearLines(n)
-
-// Set the scrolling region of the terminal
-output.ChangeScrollingRegion(top, bottom)
-
-// Insert the given number of lines at the top of the scrollable region, pushing
-// lines below down
-output.InsertLines(n)
-
-// Delete the given number of lines, pulling any lines in the scrollable region
-// below up
-output.DeleteLines(n)
-```
-
-## Session
-
-```go
-// SetWindowTitle sets the terminal window title
-output.SetWindowTitle(title)
-
-// SetForegroundColor sets the default foreground color
-output.SetForegroundColor(color)
-
-// SetBackgroundColor sets the default background color
-output.SetBackgroundColor(color)
-
-// SetCursorColor sets the cursor color
-output.SetCursorColor(color)
-
-// Hide the cursor
-output.HideCursor()
-
-// Show the cursor
-output.ShowCursor()
-
-// Copy to clipboard
-output.Copy(message)
-
-// Copy to primary clipboard (X11)
-output.CopyPrimary(message)
-
-// Trigger notification
-output.Notify(title, body)
-```
-
-## Mouse
-
-```go
-// Enable X10 mouse mode, only button press events are sent
-output.EnableMousePress()
-
-// Disable X10 mouse mode
-output.DisableMousePress()
-
-// Enable Mouse Tracking mode
-output.EnableMouse()
-
-// Disable Mouse Tracking mode
-output.DisableMouse()
-
-// Enable Hilite Mouse Tracking mode
-output.EnableMouseHilite()
-
-// Disable Hilite Mouse Tracking mode
-output.DisableMouseHilite()
-
-// Enable Cell Motion Mouse Tracking mode
-output.EnableMouseCellMotion()
-
-// Disable Cell Motion Mouse Tracking mode
-output.DisableMouseCellMotion()
-
-// Enable All Motion Mouse mode
-output.EnableMouseAllMotion()
-
-// Disable All Motion Mouse mode
-output.DisableMouseAllMotion()
-```
-
-## Bracketed Paste
-
-```go
-// Enables bracketed paste mode
-termenv.EnableBracketedPaste()
-
-// Disables bracketed paste mode
-termenv.DisableBracketedPaste()
-```
-
-## Terminal Feature Support
-
-### Color Support
-
-- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Ghostty, Windows Terminal
-- 8-bit (256): rxvt, screen, xterm, Apple Terminal
-- 4-bit (16): Linux Console
-
-### Control Sequences
-
-
-Click to show feature matrix
-
-| Terminal | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Bracketed Paste | Extended Mouse (SGR) | Pixels Mouse (SGR-Pixels) |
-| ---------------- | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :-------------: | :------------------: | :-----------------------: |
-| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
-| urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| screen | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
-| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| tmux | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
-| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
-| Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
-| Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
-| Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
-| Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-
-[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal.
-[^mux]: Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time.
-
-You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request.
-
-
-
-### System Commands
-
-
-Click to show feature matrix
-
-| Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) |
-| ---------------- | :-----------------------: | :---------------: | :--------------------: |
-| alacritty | ✅ | ✅[^alacritty] | ❌ |
-| foot | ✅ | ✅ | ✅ |
-| kitty | ✅ | ✅ | ✅ |
-| Konsole | ❌[^konsole] | ✅ | ❌ |
-| rxvt | ❌ | ❌ | ❌ |
-| urxvt | ✅[^urxvt] | ❌ | ✅ |
-| screen | ✅ | ❌[^screen] | ❌ |
-| st | ✅ | ❌ | ❌ |
-| tmux | ✅ | ❌[^tmux] | ❌ |
-| vte-based[^vte] | ❌[^vte] | ✅ | ❌ |
-| wezterm | ✅ | ✅ | ❌ |
-| xterm | ✅ | ❌ | ❌ |
-| Linux Console | ⛔ | ⛔ | ❌ |
-| Apple Terminal | ✅[^apple] | ❌ | ❌ |
-| iTerm | ✅ | ✅ | ❌ |
-| Windows cmd | ❌ | ❌ | ❌ |
-| Windows Terminal | ✅ | ✅ | ❌ |
-
-[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. OSC52 is not supported, see [issue#2495](https://gitlab.gnome.org/GNOME/vte/-/issues/2495).
-[^urxvt]: Workaround for urxvt not supporting OSC52. See [this](https://unix.stackexchange.com/a/629485) for more information.
-[^konsole]: OSC52 is not supported, for more info see [bug#372116](https://bugs.kde.org/show_bug.cgi?id=372116).
-[^apple]: OSC52 works with a [workaround](https://github.com/roy2220/osc52pty).
-[^tmux]: OSC8 is not supported, for more info see [issue#911](https://github.com/tmux/tmux/issues/911).
-[^screen]: OSC8 is not supported, for more info see [bug#50952](https://savannah.gnu.org/bugs/index.php?50952).
-[^alacritty]: OSC8 is supported since [v0.11.0](https://github.com/alacritty/alacritty/releases/tag/v0.11.0)
-
-
-
-## Platform Support
-
-`termenv` works on Unix systems (like Linux, macOS, or BSD) and Windows. While
-terminal applications on Unix support ANSI styling out-of-the-box, on Windows
-you need to enable ANSI processing in your application first:
-
-```go
- restoreConsole, err := termenv.EnableVirtualTerminalProcessing(termenv.DefaultOutput())
- if err != nil {
- panic(err)
- }
- defer restoreConsole()
-```
-
-The above code is safe to include on non-Windows systems or when os.Stdout does
-not refer to a terminal (e.g. in tests).
-
-## Color Chart
-
-
-
-You can find the source code used to create this chart in `termenv`'s examples.
-
-## Related Projects
-
-- [reflow](https://github.com/muesli/reflow) - ANSI-aware text operations
-- [Lip Gloss](https://github.com/charmbracelet/lipgloss) - style definitions for nice terminal layouts 👄
-- [ansi](https://github.com/muesli/ansi) - ANSI sequence helpers
-
-## termenv in the Wild
-
-Need some inspiration or just want to see how others are using `termenv`? Check
-out these projects:
-
-- [Bubble Tea](https://github.com/charmbracelet/bubbletea) - a powerful little TUI framework 🏗
-- [Glamour](https://github.com/charmbracelet/glamour) - stylesheet-based markdown rendering for your CLI apps 💇🏻♀️
-- [Glow](https://github.com/charmbracelet/glow) - a markdown renderer for the command-line 💅🏻
-- [duf](https://github.com/muesli/duf) - Disk Usage/Free Utility - a better 'df' alternative
-- [gitty](https://github.com/muesli/gitty) - contextual information about your git projects
-- [slides](https://github.com/maaslalani/slides) - terminal-based presentation tool
-
-## Feedback
-
-Got some feedback or suggestions? Please open an issue or drop me a note!
-
-- [Twitter](https://twitter.com/mueslix)
-- [The Fediverse](https://mastodon.social/@fribbledom)
-
-## License
-
-[MIT](https://github.com/muesli/termenv/raw/master/LICENSE)
diff --git a/hack/tools/vendor/github.com/muesli/termenv/ansi_compat.md b/hack/tools/vendor/github.com/muesli/termenv/ansi_compat.md
deleted file mode 100644
index 6b68a3a9ad1..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/ansi_compat.md
+++ /dev/null
@@ -1,65 +0,0 @@
-## Change Foreground Color
-
-This command should enable a blue foreground color:
-
-```bash
-echo -ne "\033]10;#0000ff\007"
-```
-
-## Change Background Color
-
-This command should enable a green background color:
-
-```bash
-echo -ne "\033]11;#00ff00\007"
-```
-
-## Change Cursor Color
-
-This command should enable a red cursor color:
-
-```bash
-echo -ne "\033]12;#ff0000\007"
-```
-
-## Query Color Scheme
-
-These two commands should print out the currently active color scheme:
-
-```bash
-echo -ne "\033]10;?\033\\"
-echo -ne "\033]11;?\033\\"
-```
-
-## Query Cursor Position
-
-This command should print out the current cursor position:
-
-```bash
-echo -ne "\033[6n"
-```
-
-## Set Window Title
-
-This command should set the window title to "Test":
-
-```bash
-echo -ne "\033]2;Test\007" && sleep 10
-```
-
-## Bracketed paste
-
-Enter this command, then paste a word from the clipboard. The text
-displayed on the terminal should contain the codes `200~` and `201~`:
-
-```bash
-echo -ne "\033[?2004h" && sleep 10
-```
-
-## Trigger Notification
-
-This command should trigger a notification:
-
-```bash
-echo -ne "\033]777;notify;Title;Body\033\\"
-```
diff --git a/hack/tools/vendor/github.com/muesli/termenv/ansicolors.go b/hack/tools/vendor/github.com/muesli/termenv/ansicolors.go
deleted file mode 100644
index 1a301b0fe74..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/ansicolors.go
+++ /dev/null
@@ -1,281 +0,0 @@
-package termenv
-
-// ANSI color codes.
-const (
- ANSIBlack ANSIColor = iota
- ANSIRed
- ANSIGreen
- ANSIYellow
- ANSIBlue
- ANSIMagenta
- ANSICyan
- ANSIWhite
- ANSIBrightBlack
- ANSIBrightRed
- ANSIBrightGreen
- ANSIBrightYellow
- ANSIBrightBlue
- ANSIBrightMagenta
- ANSIBrightCyan
- ANSIBrightWhite
-)
-
-// RGB values of ANSI colors (0-255).
-var ansiHex = []string{
- "#000000",
- "#800000",
- "#008000",
- "#808000",
- "#000080",
- "#800080",
- "#008080",
- "#c0c0c0",
- "#808080",
- "#ff0000",
- "#00ff00",
- "#ffff00",
- "#0000ff",
- "#ff00ff",
- "#00ffff",
- "#ffffff",
- "#000000",
- "#00005f",
- "#000087",
- "#0000af",
- "#0000d7",
- "#0000ff",
- "#005f00",
- "#005f5f",
- "#005f87",
- "#005faf",
- "#005fd7",
- "#005fff",
- "#008700",
- "#00875f",
- "#008787",
- "#0087af",
- "#0087d7",
- "#0087ff",
- "#00af00",
- "#00af5f",
- "#00af87",
- "#00afaf",
- "#00afd7",
- "#00afff",
- "#00d700",
- "#00d75f",
- "#00d787",
- "#00d7af",
- "#00d7d7",
- "#00d7ff",
- "#00ff00",
- "#00ff5f",
- "#00ff87",
- "#00ffaf",
- "#00ffd7",
- "#00ffff",
- "#5f0000",
- "#5f005f",
- "#5f0087",
- "#5f00af",
- "#5f00d7",
- "#5f00ff",
- "#5f5f00",
- "#5f5f5f",
- "#5f5f87",
- "#5f5faf",
- "#5f5fd7",
- "#5f5fff",
- "#5f8700",
- "#5f875f",
- "#5f8787",
- "#5f87af",
- "#5f87d7",
- "#5f87ff",
- "#5faf00",
- "#5faf5f",
- "#5faf87",
- "#5fafaf",
- "#5fafd7",
- "#5fafff",
- "#5fd700",
- "#5fd75f",
- "#5fd787",
- "#5fd7af",
- "#5fd7d7",
- "#5fd7ff",
- "#5fff00",
- "#5fff5f",
- "#5fff87",
- "#5fffaf",
- "#5fffd7",
- "#5fffff",
- "#870000",
- "#87005f",
- "#870087",
- "#8700af",
- "#8700d7",
- "#8700ff",
- "#875f00",
- "#875f5f",
- "#875f87",
- "#875faf",
- "#875fd7",
- "#875fff",
- "#878700",
- "#87875f",
- "#878787",
- "#8787af",
- "#8787d7",
- "#8787ff",
- "#87af00",
- "#87af5f",
- "#87af87",
- "#87afaf",
- "#87afd7",
- "#87afff",
- "#87d700",
- "#87d75f",
- "#87d787",
- "#87d7af",
- "#87d7d7",
- "#87d7ff",
- "#87ff00",
- "#87ff5f",
- "#87ff87",
- "#87ffaf",
- "#87ffd7",
- "#87ffff",
- "#af0000",
- "#af005f",
- "#af0087",
- "#af00af",
- "#af00d7",
- "#af00ff",
- "#af5f00",
- "#af5f5f",
- "#af5f87",
- "#af5faf",
- "#af5fd7",
- "#af5fff",
- "#af8700",
- "#af875f",
- "#af8787",
- "#af87af",
- "#af87d7",
- "#af87ff",
- "#afaf00",
- "#afaf5f",
- "#afaf87",
- "#afafaf",
- "#afafd7",
- "#afafff",
- "#afd700",
- "#afd75f",
- "#afd787",
- "#afd7af",
- "#afd7d7",
- "#afd7ff",
- "#afff00",
- "#afff5f",
- "#afff87",
- "#afffaf",
- "#afffd7",
- "#afffff",
- "#d70000",
- "#d7005f",
- "#d70087",
- "#d700af",
- "#d700d7",
- "#d700ff",
- "#d75f00",
- "#d75f5f",
- "#d75f87",
- "#d75faf",
- "#d75fd7",
- "#d75fff",
- "#d78700",
- "#d7875f",
- "#d78787",
- "#d787af",
- "#d787d7",
- "#d787ff",
- "#d7af00",
- "#d7af5f",
- "#d7af87",
- "#d7afaf",
- "#d7afd7",
- "#d7afff",
- "#d7d700",
- "#d7d75f",
- "#d7d787",
- "#d7d7af",
- "#d7d7d7",
- "#d7d7ff",
- "#d7ff00",
- "#d7ff5f",
- "#d7ff87",
- "#d7ffaf",
- "#d7ffd7",
- "#d7ffff",
- "#ff0000",
- "#ff005f",
- "#ff0087",
- "#ff00af",
- "#ff00d7",
- "#ff00ff",
- "#ff5f00",
- "#ff5f5f",
- "#ff5f87",
- "#ff5faf",
- "#ff5fd7",
- "#ff5fff",
- "#ff8700",
- "#ff875f",
- "#ff8787",
- "#ff87af",
- "#ff87d7",
- "#ff87ff",
- "#ffaf00",
- "#ffaf5f",
- "#ffaf87",
- "#ffafaf",
- "#ffafd7",
- "#ffafff",
- "#ffd700",
- "#ffd75f",
- "#ffd787",
- "#ffd7af",
- "#ffd7d7",
- "#ffd7ff",
- "#ffff00",
- "#ffff5f",
- "#ffff87",
- "#ffffaf",
- "#ffffd7",
- "#ffffff",
- "#080808",
- "#121212",
- "#1c1c1c",
- "#262626",
- "#303030",
- "#3a3a3a",
- "#444444",
- "#4e4e4e",
- "#585858",
- "#626262",
- "#6c6c6c",
- "#767676",
- "#808080",
- "#8a8a8a",
- "#949494",
- "#9e9e9e",
- "#a8a8a8",
- "#b2b2b2",
- "#bcbcbc",
- "#c6c6c6",
- "#d0d0d0",
- "#dadada",
- "#e4e4e4",
- "#eeeeee",
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/color.go b/hack/tools/vendor/github.com/muesli/termenv/color.go
deleted file mode 100644
index 59e639b1133..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/color.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package termenv
-
-import (
- "errors"
- "fmt"
- "math"
- "strings"
-
- "github.com/lucasb-eyer/go-colorful"
-)
-
-// ErrInvalidColor gets returned when a color is invalid.
-var ErrInvalidColor = errors.New("invalid color")
-
-// Foreground and Background sequence codes.
-const (
- Foreground = "38"
- Background = "48"
-)
-
-// Color is an interface implemented by all colors that can be converted to an
-// ANSI sequence.
-type Color interface {
- // Sequence returns the ANSI Sequence for the color.
- Sequence(bg bool) string
-}
-
-// NoColor is a nop for terminals that don't support colors.
-type NoColor struct{}
-
-func (c NoColor) String() string {
- return ""
-}
-
-// ANSIColor is a color (0-15) as defined by the ANSI Standard.
-type ANSIColor int
-
-func (c ANSIColor) String() string {
- return ansiHex[c]
-}
-
-// ANSI256Color is a color (16-255) as defined by the ANSI Standard.
-type ANSI256Color int
-
-func (c ANSI256Color) String() string {
- return ansiHex[c]
-}
-
-// RGBColor is a hex-encoded color, e.g. "#abcdef".
-type RGBColor string
-
-// ConvertToRGB converts a Color to a colorful.Color.
-func ConvertToRGB(c Color) colorful.Color {
- var hex string
- switch v := c.(type) {
- case RGBColor:
- hex = string(v)
- case ANSIColor:
- hex = ansiHex[v]
- case ANSI256Color:
- hex = ansiHex[v]
- }
-
- ch, _ := colorful.Hex(hex)
- return ch
-}
-
-// Sequence returns the ANSI Sequence for the color.
-func (c NoColor) Sequence(_ bool) string {
- return ""
-}
-
-// Sequence returns the ANSI Sequence for the color.
-//
-//nolint:mnd
-func (c ANSIColor) Sequence(bg bool) string {
- col := int(c)
- bgMod := func(c int) int {
- if bg {
- return c + 10
- }
- return c
- }
-
- if col < 8 {
- return fmt.Sprintf("%d", bgMod(col)+30) //nolint:mnd
- }
- return fmt.Sprintf("%d", bgMod(col-8)+90) //nolint:mnd
-}
-
-// Sequence returns the ANSI Sequence for the color.
-func (c ANSI256Color) Sequence(bg bool) string {
- prefix := Foreground
- if bg {
- prefix = Background
- }
- return fmt.Sprintf("%s;5;%d", prefix, c)
-}
-
-// Sequence returns the ANSI Sequence for the color.
-func (c RGBColor) Sequence(bg bool) string {
- f, err := colorful.Hex(string(c))
- if err != nil {
- return ""
- }
-
- prefix := Foreground
- if bg {
- prefix = Background
- }
- return fmt.Sprintf("%s;2;%d;%d;%d", prefix, uint8(f.R*255), uint8(f.G*255), uint8(f.B*255)) //nolint:mnd
-}
-
-func xTermColor(s string) (RGBColor, error) {
- if len(s) < 24 || len(s) > 25 {
- return RGBColor(""), ErrInvalidColor
- }
-
- switch {
- case strings.HasSuffix(s, string(BEL)):
- s = strings.TrimSuffix(s, string(BEL))
- case strings.HasSuffix(s, string(ESC)):
- s = strings.TrimSuffix(s, string(ESC))
- case strings.HasSuffix(s, ST):
- s = strings.TrimSuffix(s, ST)
- default:
- return RGBColor(""), ErrInvalidColor
- }
-
- s = s[4:]
-
- prefix := ";rgb:"
- if !strings.HasPrefix(s, prefix) {
- return RGBColor(""), ErrInvalidColor
- }
- s = strings.TrimPrefix(s, prefix)
-
- h := strings.Split(s, "/")
- hex := fmt.Sprintf("#%s%s%s", h[0][:2], h[1][:2], h[2][:2])
- return RGBColor(hex), nil
-}
-
-func ansi256ToANSIColor(c ANSI256Color) ANSIColor {
- var r int
- md := math.MaxFloat64
-
- h, _ := colorful.Hex(ansiHex[c])
- for i := 0; i <= 15; i++ {
- hb, _ := colorful.Hex(ansiHex[i])
- d := h.DistanceHSLuv(hb)
-
- if d < md {
- md = d
- r = i
- }
- }
-
- return ANSIColor(r)
-}
-
-//nolint:mnd
-func hexToANSI256Color(c colorful.Color) ANSI256Color {
- v2ci := func(v float64) int {
- if v < 48 {
- return 0
- }
- if v < 115 {
- return 1
- }
- return int((v - 35) / 40)
- }
-
- // Calculate the nearest 0-based color index at 16..231
- r := v2ci(c.R * 255.0) // 0..5 each
- g := v2ci(c.G * 255.0)
- b := v2ci(c.B * 255.0)
- ci := 36*r + 6*g + b /* 0..215 */
-
- // Calculate the represented colors back from the index
- i2cv := [6]int{0, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
- cr := i2cv[r] // r/g/b, 0..255 each
- cg := i2cv[g]
- cb := i2cv[b]
-
- // Calculate the nearest 0-based gray index at 232..255
- var grayIdx int
- average := (r + g + b) / 3
- if average > 238 {
- grayIdx = 23
- } else {
- grayIdx = (average - 3) / 10 // 0..23
- }
- gv := 8 + 10*grayIdx // same value for r/g/b, 0..255
-
- // Return the one which is nearer to the original input rgb value
- c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0}
- g2 := colorful.Color{R: float64(gv) / 255.0, G: float64(gv) / 255.0, B: float64(gv) / 255.0}
- colorDist := c.DistanceHSLuv(c2)
- grayDist := c.DistanceHSLuv(g2)
-
- if colorDist <= grayDist {
- return ANSI256Color(16 + ci)
- }
- return ANSI256Color(232 + grayIdx)
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/constants_linux.go b/hack/tools/vendor/github.com/muesli/termenv/constants_linux.go
deleted file mode 100644
index 4262f03b94b..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/constants_linux.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TCGETS
- tcsetattr = unix.TCSETS
-)
diff --git a/hack/tools/vendor/github.com/muesli/termenv/constants_solaris.go b/hack/tools/vendor/github.com/muesli/termenv/constants_solaris.go
deleted file mode 100644
index 4262f03b94b..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/constants_solaris.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TCGETS
- tcsetattr = unix.TCSETS
-)
diff --git a/hack/tools/vendor/github.com/muesli/termenv/constants_unix.go b/hack/tools/vendor/github.com/muesli/termenv/constants_unix.go
deleted file mode 100644
index 5d664245eae..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/constants_unix.go
+++ /dev/null
@@ -1,13 +0,0 @@
-//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && !solaris && !illumos
-// +build darwin dragonfly freebsd netbsd openbsd
-// +build !solaris
-// +build !illumos
-
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TIOCGETA
- tcsetattr = unix.TIOCSETA
-)
diff --git a/hack/tools/vendor/github.com/muesli/termenv/constants_zos.go b/hack/tools/vendor/github.com/muesli/termenv/constants_zos.go
deleted file mode 100644
index 4262f03b94b..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/constants_zos.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TCGETS
- tcsetattr = unix.TCSETS
-)
diff --git a/hack/tools/vendor/github.com/muesli/termenv/copy.go b/hack/tools/vendor/github.com/muesli/termenv/copy.go
deleted file mode 100644
index 4bf5c9fea45..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/copy.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package termenv
-
-import (
- "strings"
-
- "github.com/aymanbagabas/go-osc52/v2"
-)
-
-// Copy copies text to clipboard using OSC 52 escape sequence.
-func (o Output) Copy(str string) {
- s := osc52.New(str)
- if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") {
- s = s.Screen()
- }
- _, _ = s.WriteTo(o)
-}
-
-// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
-// sequence.
-func (o Output) CopyPrimary(str string) {
- s := osc52.New(str).Primary()
- if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") {
- s = s.Screen()
- }
- _, _ = s.WriteTo(o)
-}
-
-// Copy copies text to clipboard using OSC 52 escape sequence.
-func Copy(str string) {
- output.Copy(str)
-}
-
-// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
-// sequence.
-func CopyPrimary(str string) {
- output.CopyPrimary(str)
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/hyperlink.go b/hack/tools/vendor/github.com/muesli/termenv/hyperlink.go
deleted file mode 100644
index 97e760a3bfc..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/hyperlink.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package termenv
-
-// Hyperlink creates a hyperlink using OSC8.
-func Hyperlink(link, name string) string {
- return output.Hyperlink(link, name)
-}
-
-// Hyperlink creates a hyperlink using OSC8.
-func (o *Output) Hyperlink(link, name string) string {
- return OSC + "8;;" + link + ST + name + OSC + "8;;" + ST
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/notification.go b/hack/tools/vendor/github.com/muesli/termenv/notification.go
deleted file mode 100644
index 2a8cf06a9d5..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/notification.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package termenv
-
-// Notify triggers a notification using OSC777.
-func Notify(title, body string) {
- output.Notify(title, body)
-}
-
-// Notify triggers a notification using OSC777.
-func (o *Output) Notify(title, body string) {
- _, _ = o.WriteString(OSC + "777;notify;" + title + ";" + body + ST)
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/output.go b/hack/tools/vendor/github.com/muesli/termenv/output.go
deleted file mode 100644
index e4434de0344..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/output.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package termenv
-
-import (
- "io"
- "os"
- "sync"
-)
-
-// output is the default global output.
-var output = NewOutput(os.Stdout)
-
-// File represents a file descriptor.
-//
-// Deprecated: Use *os.File instead.
-type File interface {
- io.ReadWriter
- Fd() uintptr
-}
-
-// OutputOption sets an option on Output.
-type OutputOption = func(*Output)
-
-// Output is a terminal output.
-type Output struct {
- Profile
- w io.Writer
- environ Environ
-
- assumeTTY bool
- unsafe bool
- cache bool
- fgSync *sync.Once
- fgColor Color
- bgSync *sync.Once
- bgColor Color
-}
-
-// Environ is an interface for getting environment variables.
-type Environ interface {
- Environ() []string
- Getenv(string) string
-}
-
-type osEnviron struct{}
-
-func (oe *osEnviron) Environ() []string {
- return os.Environ()
-}
-
-func (oe *osEnviron) Getenv(key string) string {
- return os.Getenv(key)
-}
-
-// DefaultOutput returns the default global output.
-func DefaultOutput() *Output {
- return output
-}
-
-// SetDefaultOutput sets the default global output.
-func SetDefaultOutput(o *Output) {
- output = o
-}
-
-// NewOutput returns a new Output for the given writer.
-func NewOutput(w io.Writer, opts ...OutputOption) *Output {
- o := &Output{
- w: w,
- environ: &osEnviron{},
- Profile: -1,
- fgSync: &sync.Once{},
- fgColor: NoColor{},
- bgSync: &sync.Once{},
- bgColor: NoColor{},
- }
-
- if o.w == nil {
- o.w = os.Stdout
- }
- for _, opt := range opts {
- opt(o)
- }
- if o.Profile < 0 {
- o.Profile = o.EnvColorProfile()
- }
-
- return o
-}
-
-// WithEnvironment returns a new OutputOption for the given environment.
-func WithEnvironment(environ Environ) OutputOption {
- return func(o *Output) {
- o.environ = environ
- }
-}
-
-// WithProfile returns a new OutputOption for the given profile.
-func WithProfile(profile Profile) OutputOption {
- return func(o *Output) {
- o.Profile = profile
- }
-}
-
-// WithColorCache returns a new OutputOption with fore- and background color values
-// pre-fetched and cached.
-func WithColorCache(v bool) OutputOption {
- return func(o *Output) {
- o.cache = v
-
- // cache the values now
- _ = o.ForegroundColor()
- _ = o.BackgroundColor()
- }
-}
-
-// WithTTY returns a new OutputOption to assume whether or not the output is a TTY.
-// This is useful when mocking console output.
-func WithTTY(v bool) OutputOption {
- return func(o *Output) {
- o.assumeTTY = v
- }
-}
-
-// WithUnsafe returns a new OutputOption with unsafe mode enabled. Unsafe mode doesn't
-// check whether or not the terminal is a TTY.
-//
-// This option supersedes WithTTY.
-//
-// This is useful when mocking console output and enforcing ANSI escape output
-// e.g. on SSH sessions.
-func WithUnsafe() OutputOption {
- return func(o *Output) {
- o.unsafe = true
- }
-}
-
-// ForegroundColor returns the terminal's default foreground color.
-func (o *Output) ForegroundColor() Color {
- f := func() {
- if !o.isTTY() {
- return
- }
-
- o.fgColor = o.foregroundColor()
- }
-
- if o.cache {
- o.fgSync.Do(f)
- } else {
- f()
- }
-
- return o.fgColor
-}
-
-// BackgroundColor returns the terminal's default background color.
-func (o *Output) BackgroundColor() Color {
- f := func() {
- if !o.isTTY() {
- return
- }
-
- o.bgColor = o.backgroundColor()
- }
-
- if o.cache {
- o.bgSync.Do(f)
- } else {
- f()
- }
-
- return o.bgColor
-}
-
-// HasDarkBackground returns whether terminal uses a dark-ish background.
-func (o *Output) HasDarkBackground() bool {
- c := ConvertToRGB(o.BackgroundColor())
- _, _, l := c.Hsl()
- return l < 0.5 //nolint:mnd
-}
-
-// TTY returns the terminal's file descriptor. This may be nil if the output is
-// not a terminal.
-//
-// Deprecated: Use Writer() instead.
-func (o Output) TTY() File {
- if f, ok := o.w.(File); ok {
- return f
- }
- return nil
-}
-
-// Writer returns the underlying writer. This may be of type io.Writer,
-// io.ReadWriter, or *os.File.
-func (o Output) Writer() io.Writer {
- return o.w
-}
-
-func (o Output) Write(p []byte) (int, error) {
- return o.w.Write(p) //nolint:wrapcheck
-}
-
-// WriteString writes the given string to the output.
-func (o Output) WriteString(s string) (int, error) {
- return o.Write([]byte(s))
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/profile.go b/hack/tools/vendor/github.com/muesli/termenv/profile.go
deleted file mode 100644
index 7d38f5fb06b..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/profile.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package termenv
-
-import (
- "image/color"
- "strconv"
- "strings"
-
- "github.com/lucasb-eyer/go-colorful"
-)
-
-// Profile is a color profile: Ascii, ANSI, ANSI256, or TrueColor.
-type Profile int
-
-const (
- // TrueColor, 24-bit color profile.
- TrueColor = Profile(iota)
- // ANSI256, 8-bit color profile.
- ANSI256
- // ANSI, 4-bit color profile.
- ANSI
- // Ascii, uncolored profile.
- Ascii //nolint:revive
-)
-
-// Name returns the profile name as a string.
-func (p Profile) Name() string {
- switch p {
- case Ascii:
- return "Ascii"
- case ANSI:
- return "ANSI"
- case ANSI256:
- return "ANSI256"
- case TrueColor:
- return "TrueColor"
- }
- return "Unknown"
-}
-
-// String returns a new Style.
-func (p Profile) String(s ...string) Style {
- return Style{
- profile: p,
- string: strings.Join(s, " "),
- }
-}
-
-// Convert transforms a given Color to a Color supported within the Profile.
-func (p Profile) Convert(c Color) Color {
- if p == Ascii {
- return NoColor{}
- }
-
- switch v := c.(type) {
- case ANSIColor:
- return v
-
- case ANSI256Color:
- if p == ANSI {
- return ansi256ToANSIColor(v)
- }
- return v
-
- case RGBColor:
- h, err := colorful.Hex(string(v))
- if err != nil {
- return nil
- }
- if p != TrueColor {
- ac := hexToANSI256Color(h)
- if p == ANSI {
- return ansi256ToANSIColor(ac)
- }
- return ac
- }
- return v
- }
-
- return c
-}
-
-// Color creates a Color from a string. Valid inputs are hex colors, as well as
-// ANSI color codes (0-15, 16-255).
-func (p Profile) Color(s string) Color {
- if len(s) == 0 {
- return nil
- }
-
- var c Color
- if strings.HasPrefix(s, "#") {
- c = RGBColor(s)
- } else {
- i, err := strconv.Atoi(s)
- if err != nil {
- return nil
- }
-
- if i < 16 { //nolint:mnd
- c = ANSIColor(i)
- } else {
- c = ANSI256Color(i)
- }
- }
-
- return p.Convert(c)
-}
-
-// FromColor creates a Color from a color.Color.
-func (p Profile) FromColor(c color.Color) Color {
- col, _ := colorful.MakeColor(c)
- return p.Color(col.Hex())
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/screen.go b/hack/tools/vendor/github.com/muesli/termenv/screen.go
deleted file mode 100644
index 75c11d01183..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/screen.go
+++ /dev/null
@@ -1,590 +0,0 @@
-package termenv
-
-import (
- "fmt"
- "strings"
-)
-
-// Sequence definitions.
-const (
- // Cursor positioning.
- CursorUpSeq = "%dA"
- CursorDownSeq = "%dB"
- CursorForwardSeq = "%dC"
- CursorBackSeq = "%dD"
- CursorNextLineSeq = "%dE"
- CursorPreviousLineSeq = "%dF"
- CursorHorizontalSeq = "%dG"
- CursorPositionSeq = "%d;%dH"
- EraseDisplaySeq = "%dJ"
- EraseLineSeq = "%dK"
- ScrollUpSeq = "%dS"
- ScrollDownSeq = "%dT"
- SaveCursorPositionSeq = "s"
- RestoreCursorPositionSeq = "u"
- ChangeScrollingRegionSeq = "%d;%dr"
- InsertLineSeq = "%dL"
- DeleteLineSeq = "%dM"
-
- // Explicit values for EraseLineSeq.
- EraseLineRightSeq = "0K"
- EraseLineLeftSeq = "1K"
- EraseEntireLineSeq = "2K"
-
- // Mouse.
- EnableMousePressSeq = "?9h" // press only (X10)
- DisableMousePressSeq = "?9l"
- EnableMouseSeq = "?1000h" // press, release, wheel
- DisableMouseSeq = "?1000l"
- EnableMouseHiliteSeq = "?1001h" // highlight
- DisableMouseHiliteSeq = "?1001l"
- EnableMouseCellMotionSeq = "?1002h" // press, release, move on pressed, wheel
- DisableMouseCellMotionSeq = "?1002l"
- EnableMouseAllMotionSeq = "?1003h" // press, release, move, wheel
- DisableMouseAllMotionSeq = "?1003l"
- EnableMouseExtendedModeSeq = "?1006h" // press, release, move, wheel, extended coordinates
- DisableMouseExtendedModeSeq = "?1006l"
- EnableMousePixelsModeSeq = "?1016h" // press, release, move, wheel, extended pixel coordinates
- DisableMousePixelsModeSeq = "?1016l"
-
- // Screen.
- RestoreScreenSeq = "?47l"
- SaveScreenSeq = "?47h"
- AltScreenSeq = "?1049h"
- ExitAltScreenSeq = "?1049l"
-
- // Bracketed paste.
- // https://en.wikipedia.org/wiki/Bracketed-paste
- EnableBracketedPasteSeq = "?2004h"
- DisableBracketedPasteSeq = "?2004l"
- StartBracketedPasteSeq = "200~"
- EndBracketedPasteSeq = "201~"
-
- // Session.
- SetWindowTitleSeq = "2;%s" + string(BEL)
- SetForegroundColorSeq = "10;%s" + string(BEL)
- SetBackgroundColorSeq = "11;%s" + string(BEL)
- SetCursorColorSeq = "12;%s" + string(BEL)
- ShowCursorSeq = "?25h"
- HideCursorSeq = "?25l"
-)
-
-// Reset the terminal to its default style, removing any active styles.
-func (o Output) Reset() {
- fmt.Fprint(o.w, CSI+ResetSeq+"m") //nolint:errcheck
-}
-
-// SetForegroundColor sets the default foreground color.
-func (o Output) SetForegroundColor(color Color) {
- fmt.Fprintf(o.w, OSC+SetForegroundColorSeq, color) //nolint:errcheck
-}
-
-// SetBackgroundColor sets the default background color.
-func (o Output) SetBackgroundColor(color Color) {
- fmt.Fprintf(o.w, OSC+SetBackgroundColorSeq, color) //nolint:errcheck
-}
-
-// SetCursorColor sets the cursor color.
-func (o Output) SetCursorColor(color Color) {
- fmt.Fprintf(o.w, OSC+SetCursorColorSeq, color) //nolint:errcheck
-}
-
-// RestoreScreen restores a previously saved screen state.
-func (o Output) RestoreScreen() {
- fmt.Fprint(o.w, CSI+RestoreScreenSeq) //nolint:errcheck
-}
-
-// SaveScreen saves the screen state.
-func (o Output) SaveScreen() {
- fmt.Fprint(o.w, CSI+SaveScreenSeq) //nolint:errcheck
-}
-
-// AltScreen switches to the alternate screen buffer. The former view can be
-// restored with ExitAltScreen().
-func (o Output) AltScreen() {
- fmt.Fprint(o.w, CSI+AltScreenSeq) //nolint:errcheck
-}
-
-// ExitAltScreen exits the alternate screen buffer and returns to the former
-// terminal view.
-func (o Output) ExitAltScreen() {
- fmt.Fprint(o.w, CSI+ExitAltScreenSeq) //nolint:errcheck
-}
-
-// ClearScreen clears the visible portion of the terminal.
-func (o Output) ClearScreen() {
- fmt.Fprintf(o.w, CSI+EraseDisplaySeq, 2) //nolint:errcheck,mnd
- o.MoveCursor(1, 1)
-}
-
-// MoveCursor moves the cursor to a given position.
-func (o Output) MoveCursor(row int, column int) {
- fmt.Fprintf(o.w, CSI+CursorPositionSeq, row, column) //nolint:errcheck
-}
-
-// HideCursor hides the cursor.
-func (o Output) HideCursor() {
- fmt.Fprint(o.w, CSI+HideCursorSeq) //nolint:errcheck
-}
-
-// ShowCursor shows the cursor.
-func (o Output) ShowCursor() {
- fmt.Fprint(o.w, CSI+ShowCursorSeq) //nolint:errcheck
-}
-
-// SaveCursorPosition saves the cursor position.
-func (o Output) SaveCursorPosition() {
- fmt.Fprint(o.w, CSI+SaveCursorPositionSeq) //nolint:errcheck
-}
-
-// RestoreCursorPosition restores a saved cursor position.
-func (o Output) RestoreCursorPosition() {
- fmt.Fprint(o.w, CSI+RestoreCursorPositionSeq) //nolint:errcheck
-}
-
-// CursorUp moves the cursor up a given number of lines.
-func (o Output) CursorUp(n int) {
- fmt.Fprintf(o.w, CSI+CursorUpSeq, n) //nolint:errcheck
-}
-
-// CursorDown moves the cursor down a given number of lines.
-func (o Output) CursorDown(n int) {
- fmt.Fprintf(o.w, CSI+CursorDownSeq, n) //nolint:errcheck
-}
-
-// CursorForward moves the cursor up a given number of lines.
-func (o Output) CursorForward(n int) {
- fmt.Fprintf(o.w, CSI+CursorForwardSeq, n) //nolint:errcheck
-}
-
-// CursorBack moves the cursor backwards a given number of cells.
-func (o Output) CursorBack(n int) {
- fmt.Fprintf(o.w, CSI+CursorBackSeq, n) //nolint:errcheck
-}
-
-// CursorNextLine moves the cursor down a given number of lines and places it at
-// the beginning of the line.
-func (o Output) CursorNextLine(n int) {
- fmt.Fprintf(o.w, CSI+CursorNextLineSeq, n) //nolint:errcheck
-}
-
-// CursorPrevLine moves the cursor up a given number of lines and places it at
-// the beginning of the line.
-func (o Output) CursorPrevLine(n int) {
- fmt.Fprintf(o.w, CSI+CursorPreviousLineSeq, n) //nolint:errcheck
-}
-
-// ClearLine clears the current line.
-func (o Output) ClearLine() {
- fmt.Fprint(o.w, CSI+EraseEntireLineSeq) //nolint:errcheck
-}
-
-// ClearLineLeft clears the line to the left of the cursor.
-func (o Output) ClearLineLeft() {
- fmt.Fprint(o.w, CSI+EraseLineLeftSeq) //nolint:errcheck
-}
-
-// ClearLineRight clears the line to the right of the cursor.
-func (o Output) ClearLineRight() {
- fmt.Fprint(o.w, CSI+EraseLineRightSeq) //nolint:errcheck
-}
-
-// ClearLines clears a given number of lines.
-func (o Output) ClearLines(n int) {
- clearLine := fmt.Sprintf(CSI+EraseLineSeq, 2) //nolint:mnd
- cursorUp := fmt.Sprintf(CSI+CursorUpSeq, 1)
- fmt.Fprint(o.w, clearLine+strings.Repeat(cursorUp+clearLine, n)) //nolint:errcheck
-}
-
-// ChangeScrollingRegion sets the scrolling region of the terminal.
-func (o Output) ChangeScrollingRegion(top, bottom int) {
- fmt.Fprintf(o.w, CSI+ChangeScrollingRegionSeq, top, bottom) //nolint:errcheck
-}
-
-// InsertLines inserts the given number of lines at the top of the scrollable
-// region, pushing lines below down.
-func (o Output) InsertLines(n int) {
- fmt.Fprintf(o.w, CSI+InsertLineSeq, n) //nolint:errcheck
-}
-
-// DeleteLines deletes the given number of lines, pulling any lines in
-// the scrollable region below up.
-func (o Output) DeleteLines(n int) {
- fmt.Fprintf(o.w, CSI+DeleteLineSeq, n) //nolint:errcheck
-}
-
-// EnableMousePress enables X10 mouse mode. Button press events are sent only.
-func (o Output) EnableMousePress() {
- fmt.Fprint(o.w, CSI+EnableMousePressSeq) //nolint:errcheck
-}
-
-// DisableMousePress disables X10 mouse mode.
-func (o Output) DisableMousePress() {
- fmt.Fprint(o.w, CSI+DisableMousePressSeq) //nolint:errcheck
-}
-
-// EnableMouse enables Mouse Tracking mode.
-func (o Output) EnableMouse() {
- fmt.Fprint(o.w, CSI+EnableMouseSeq) //nolint:errcheck
-}
-
-// DisableMouse disables Mouse Tracking mode.
-func (o Output) DisableMouse() {
- fmt.Fprint(o.w, CSI+DisableMouseSeq) //nolint:errcheck
-}
-
-// EnableMouseHilite enables Hilite Mouse Tracking mode.
-func (o Output) EnableMouseHilite() {
- fmt.Fprint(o.w, CSI+EnableMouseHiliteSeq) //nolint:errcheck
-}
-
-// DisableMouseHilite disables Hilite Mouse Tracking mode.
-func (o Output) DisableMouseHilite() {
- fmt.Fprint(o.w, CSI+DisableMouseHiliteSeq) //nolint:errcheck
-}
-
-// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode.
-func (o Output) EnableMouseCellMotion() {
- fmt.Fprint(o.w, CSI+EnableMouseCellMotionSeq) //nolint:errcheck
-}
-
-// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode.
-func (o Output) DisableMouseCellMotion() {
- fmt.Fprint(o.w, CSI+DisableMouseCellMotionSeq) //nolint:errcheck
-}
-
-// EnableMouseAllMotion enables All Motion Mouse mode.
-func (o Output) EnableMouseAllMotion() {
- fmt.Fprint(o.w, CSI+EnableMouseAllMotionSeq) //nolint:errcheck
-}
-
-// DisableMouseAllMotion disables All Motion Mouse mode.
-func (o Output) DisableMouseAllMotion() {
- fmt.Fprint(o.w, CSI+DisableMouseAllMotionSeq) //nolint:errcheck
-}
-
-// EnableMouseExtendedMotion enables Extended Mouse mode (SGR). This should be
-// enabled in conjunction with EnableMouseCellMotion, and EnableMouseAllMotion.
-func (o Output) EnableMouseExtendedMode() {
- fmt.Fprint(o.w, CSI+EnableMouseExtendedModeSeq) //nolint:errcheck
-}
-
-// DisableMouseExtendedMotion disables Extended Mouse mode (SGR).
-func (o Output) DisableMouseExtendedMode() {
- fmt.Fprint(o.w, CSI+DisableMouseExtendedModeSeq) //nolint:errcheck
-}
-
-// EnableMousePixelsMotion enables Pixel Motion Mouse mode (SGR-Pixels). This
-// should be enabled in conjunction with EnableMouseCellMotion, and
-// EnableMouseAllMotion.
-func (o Output) EnableMousePixelsMode() {
- fmt.Fprint(o.w, CSI+EnableMousePixelsModeSeq) //nolint:errcheck
-}
-
-// DisableMousePixelsMotion disables Pixel Motion Mouse mode (SGR-Pixels).
-func (o Output) DisableMousePixelsMode() {
- fmt.Fprint(o.w, CSI+DisableMousePixelsModeSeq) //nolint:errcheck
-}
-
-// SetWindowTitle sets the terminal window title.
-func (o Output) SetWindowTitle(title string) {
- fmt.Fprintf(o.w, OSC+SetWindowTitleSeq, title) //nolint:errcheck
-}
-
-// EnableBracketedPaste enables bracketed paste.
-func (o Output) EnableBracketedPaste() {
- fmt.Fprintf(o.w, CSI+EnableBracketedPasteSeq) //nolint:errcheck
-}
-
-// DisableBracketedPaste disables bracketed paste.
-func (o Output) DisableBracketedPaste() {
- fmt.Fprintf(o.w, CSI+DisableBracketedPasteSeq) //nolint:errcheck
-}
-
-// Legacy functions.
-
-// Reset the terminal to its default style, removing any active styles.
-//
-// Deprecated: please use termenv.Output instead.
-func Reset() {
- output.Reset()
-}
-
-// SetForegroundColor sets the default foreground color.
-//
-// Deprecated: please use termenv.Output instead.
-func SetForegroundColor(color Color) {
- output.SetForegroundColor(color)
-}
-
-// SetBackgroundColor sets the default background color.
-//
-// Deprecated: please use termenv.Output instead.
-func SetBackgroundColor(color Color) {
- output.SetBackgroundColor(color)
-}
-
-// SetCursorColor sets the cursor color.
-//
-// Deprecated: please use termenv.Output instead.
-func SetCursorColor(color Color) {
- output.SetCursorColor(color)
-}
-
-// RestoreScreen restores a previously saved screen state.
-//
-// Deprecated: please use termenv.Output instead.
-func RestoreScreen() {
- output.RestoreScreen()
-}
-
-// SaveScreen saves the screen state.
-//
-// Deprecated: please use termenv.Output instead.
-func SaveScreen() {
- output.SaveScreen()
-}
-
-// AltScreen switches to the alternate screen buffer. The former view can be
-// restored with ExitAltScreen().
-//
-// Deprecated: please use termenv.Output instead.
-func AltScreen() {
- output.AltScreen()
-}
-
-// ExitAltScreen exits the alternate screen buffer and returns to the former
-// terminal view.
-//
-// Deprecated: please use termenv.Output instead.
-func ExitAltScreen() {
- output.ExitAltScreen()
-}
-
-// ClearScreen clears the visible portion of the terminal.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearScreen() {
- output.ClearScreen()
-}
-
-// MoveCursor moves the cursor to a given position.
-//
-// Deprecated: please use termenv.Output instead.
-func MoveCursor(row int, column int) {
- output.MoveCursor(row, column)
-}
-
-// HideCursor hides the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func HideCursor() {
- output.HideCursor()
-}
-
-// ShowCursor shows the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func ShowCursor() {
- output.ShowCursor()
-}
-
-// SaveCursorPosition saves the cursor position.
-//
-// Deprecated: please use termenv.Output instead.
-func SaveCursorPosition() {
- output.SaveCursorPosition()
-}
-
-// RestoreCursorPosition restores a saved cursor position.
-//
-// Deprecated: please use termenv.Output instead.
-func RestoreCursorPosition() {
- output.RestoreCursorPosition()
-}
-
-// CursorUp moves the cursor up a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorUp(n int) {
- output.CursorUp(n)
-}
-
-// CursorDown moves the cursor down a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorDown(n int) {
- output.CursorDown(n)
-}
-
-// CursorForward moves the cursor up a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorForward(n int) {
- output.CursorForward(n)
-}
-
-// CursorBack moves the cursor backwards a given number of cells.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorBack(n int) {
- output.CursorBack(n)
-}
-
-// CursorNextLine moves the cursor down a given number of lines and places it at
-// the beginning of the line.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorNextLine(n int) {
- output.CursorNextLine(n)
-}
-
-// CursorPrevLine moves the cursor up a given number of lines and places it at
-// the beginning of the line.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorPrevLine(n int) {
- output.CursorPrevLine(n)
-}
-
-// ClearLine clears the current line.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLine() {
- output.ClearLine()
-}
-
-// ClearLineLeft clears the line to the left of the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLineLeft() {
- output.ClearLineLeft()
-}
-
-// ClearLineRight clears the line to the right of the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLineRight() {
- output.ClearLineRight()
-}
-
-// ClearLines clears a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLines(n int) {
- output.ClearLines(n)
-}
-
-// ChangeScrollingRegion sets the scrolling region of the terminal.
-//
-// Deprecated: please use termenv.Output instead.
-func ChangeScrollingRegion(top, bottom int) {
- output.ChangeScrollingRegion(top, bottom)
-}
-
-// InsertLines inserts the given number of lines at the top of the scrollable
-// region, pushing lines below down.
-//
-// Deprecated: please use termenv.Output instead.
-func InsertLines(n int) {
- output.InsertLines(n)
-}
-
-// DeleteLines deletes the given number of lines, pulling any lines in
-// the scrollable region below up.
-//
-// Deprecated: please use termenv.Output instead.
-func DeleteLines(n int) {
- output.DeleteLines(n)
-}
-
-// EnableMousePress enables X10 mouse mode. Button press events are sent only.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMousePress() {
- output.EnableMousePress()
-}
-
-// DisableMousePress disables X10 mouse mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMousePress() {
- output.DisableMousePress()
-}
-
-// EnableMouse enables Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouse() {
- output.EnableMouse()
-}
-
-// DisableMouse disables Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouse() {
- output.DisableMouse()
-}
-
-// EnableMouseHilite enables Hilite Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouseHilite() {
- output.EnableMouseHilite()
-}
-
-// DisableMouseHilite disables Hilite Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouseHilite() {
- output.DisableMouseHilite()
-}
-
-// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouseCellMotion() {
- output.EnableMouseCellMotion()
-}
-
-// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouseCellMotion() {
- output.DisableMouseCellMotion()
-}
-
-// EnableMouseAllMotion enables All Motion Mouse mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouseAllMotion() {
- output.EnableMouseAllMotion()
-}
-
-// DisableMouseAllMotion disables All Motion Mouse mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouseAllMotion() {
- output.DisableMouseAllMotion()
-}
-
-// SetWindowTitle sets the terminal window title.
-//
-// Deprecated: please use termenv.Output instead.
-func SetWindowTitle(title string) {
- output.SetWindowTitle(title)
-}
-
-// EnableBracketedPaste enables bracketed paste.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableBracketedPaste() {
- output.EnableBracketedPaste()
-}
-
-// DisableBracketedPaste disables bracketed paste.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableBracketedPaste() {
- output.DisableBracketedPaste()
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/style.go b/hack/tools/vendor/github.com/muesli/termenv/style.go
deleted file mode 100644
index dedc1f9fdf5..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/style.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package termenv
-
-import (
- "fmt"
- "strings"
-
- "github.com/rivo/uniseg"
-)
-
-// Sequence definitions.
-const (
- ResetSeq = "0"
- BoldSeq = "1"
- FaintSeq = "2"
- ItalicSeq = "3"
- UnderlineSeq = "4"
- BlinkSeq = "5"
- ReverseSeq = "7"
- CrossOutSeq = "9"
- OverlineSeq = "53"
-)
-
-// Style is a string that various rendering styles can be applied to.
-type Style struct {
- profile Profile
- string
- styles []string
-}
-
-// String returns a new Style.
-func String(s ...string) Style {
- return Style{
- profile: ANSI,
- string: strings.Join(s, " "),
- }
-}
-
-func (t Style) String() string {
- return t.Styled(t.string)
-}
-
-// Styled renders s with all applied styles.
-func (t Style) Styled(s string) string {
- if t.profile == Ascii {
- return s
- }
- if len(t.styles) == 0 {
- return s
- }
-
- seq := strings.Join(t.styles, ";")
- if seq == "" {
- return s
- }
-
- return fmt.Sprintf("%s%sm%s%sm", CSI, seq, s, CSI+ResetSeq)
-}
-
-// Foreground sets a foreground color.
-func (t Style) Foreground(c Color) Style {
- if c != nil {
- t.styles = append(t.styles, c.Sequence(false))
- }
- return t
-}
-
-// Background sets a background color.
-func (t Style) Background(c Color) Style {
- if c != nil {
- t.styles = append(t.styles, c.Sequence(true))
- }
- return t
-}
-
-// Bold enables bold rendering.
-func (t Style) Bold() Style {
- t.styles = append(t.styles, BoldSeq)
- return t
-}
-
-// Faint enables faint rendering.
-func (t Style) Faint() Style {
- t.styles = append(t.styles, FaintSeq)
- return t
-}
-
-// Italic enables italic rendering.
-func (t Style) Italic() Style {
- t.styles = append(t.styles, ItalicSeq)
- return t
-}
-
-// Underline enables underline rendering.
-func (t Style) Underline() Style {
- t.styles = append(t.styles, UnderlineSeq)
- return t
-}
-
-// Overline enables overline rendering.
-func (t Style) Overline() Style {
- t.styles = append(t.styles, OverlineSeq)
- return t
-}
-
-// Blink enables blink mode.
-func (t Style) Blink() Style {
- t.styles = append(t.styles, BlinkSeq)
- return t
-}
-
-// Reverse enables reverse color mode.
-func (t Style) Reverse() Style {
- t.styles = append(t.styles, ReverseSeq)
- return t
-}
-
-// CrossOut enables crossed-out rendering.
-func (t Style) CrossOut() Style {
- t.styles = append(t.styles, CrossOutSeq)
- return t
-}
-
-// Width returns the width required to print all runes in Style.
-func (t Style) Width() int {
- return uniseg.StringWidth(t.string)
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/templatehelper.go b/hack/tools/vendor/github.com/muesli/termenv/templatehelper.go
deleted file mode 100644
index 4c7c80f5b83..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/templatehelper.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package termenv
-
-import (
- "text/template"
-)
-
-// TemplateFuncs returns template helpers for the given output.
-func (o Output) TemplateFuncs() template.FuncMap {
- return TemplateFuncs(o.Profile)
-}
-
-// TemplateFuncs contains a few useful template helpers.
-//
-//nolint:mnd
-func TemplateFuncs(p Profile) template.FuncMap {
- if p == Ascii {
- return noopTemplateFuncs
- }
-
- return template.FuncMap{
- "Color": func(values ...interface{}) string {
- s := p.String(values[len(values)-1].(string))
- switch len(values) {
- case 2:
- s = s.Foreground(p.Color(values[0].(string)))
- case 3:
- s = s.
- Foreground(p.Color(values[0].(string))).
- Background(p.Color(values[1].(string)))
- }
-
- return s.String()
- },
- "Foreground": func(values ...interface{}) string {
- s := p.String(values[len(values)-1].(string))
- if len(values) == 2 {
- s = s.Foreground(p.Color(values[0].(string)))
- }
-
- return s.String()
- },
- "Background": func(values ...interface{}) string {
- s := p.String(values[len(values)-1].(string))
- if len(values) == 2 {
- s = s.Background(p.Color(values[0].(string)))
- }
-
- return s.String()
- },
- "Bold": styleFunc(p, Style.Bold),
- "Faint": styleFunc(p, Style.Faint),
- "Italic": styleFunc(p, Style.Italic),
- "Underline": styleFunc(p, Style.Underline),
- "Overline": styleFunc(p, Style.Overline),
- "Blink": styleFunc(p, Style.Blink),
- "Reverse": styleFunc(p, Style.Reverse),
- "CrossOut": styleFunc(p, Style.CrossOut),
- }
-}
-
-func styleFunc(p Profile, f func(Style) Style) func(...interface{}) string {
- return func(values ...interface{}) string {
- s := p.String(values[0].(string))
- return f(s).String()
- }
-}
-
-var noopTemplateFuncs = template.FuncMap{
- "Color": noColorFunc,
- "Foreground": noColorFunc,
- "Background": noColorFunc,
- "Bold": noStyleFunc,
- "Faint": noStyleFunc,
- "Italic": noStyleFunc,
- "Underline": noStyleFunc,
- "Overline": noStyleFunc,
- "Blink": noStyleFunc,
- "Reverse": noStyleFunc,
- "CrossOut": noStyleFunc,
-}
-
-func noColorFunc(values ...interface{}) string {
- return values[len(values)-1].(string)
-}
-
-func noStyleFunc(values ...interface{}) string {
- return values[0].(string)
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/termenv.go b/hack/tools/vendor/github.com/muesli/termenv/termenv.go
deleted file mode 100644
index d702cd55e8a..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/termenv.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package termenv
-
-import (
- "errors"
- "os"
-
- "github.com/mattn/go-isatty"
-)
-
-var (
- // ErrStatusReport gets returned when the terminal can't be queried.
- ErrStatusReport = errors.New("unable to retrieve status report")
-)
-
-const (
- // Escape character.
- ESC = '\x1b'
- // Bell.
- BEL = '\a'
- // Control Sequence Introducer.
- CSI = string(ESC) + "["
- // Operating System Command.
- OSC = string(ESC) + "]"
- // String Terminator.
- ST = string(ESC) + `\`
-)
-
-func (o *Output) isTTY() bool {
- if o.assumeTTY || o.unsafe {
- return true
- }
- if len(o.environ.Getenv("CI")) > 0 {
- return false
- }
- if f, ok := o.Writer().(*os.File); ok {
- return isatty.IsTerminal(f.Fd())
- }
-
- return false
-}
-
-// ColorProfile returns the supported color profile:
-// Ascii, ANSI, ANSI256, or TrueColor.
-func ColorProfile() Profile {
- return output.ColorProfile()
-}
-
-// ForegroundColor returns the terminal's default foreground color.
-func ForegroundColor() Color {
- return output.ForegroundColor()
-}
-
-// BackgroundColor returns the terminal's default background color.
-func BackgroundColor() Color {
- return output.BackgroundColor()
-}
-
-// HasDarkBackground returns whether terminal uses a dark-ish background.
-func HasDarkBackground() bool {
- return output.HasDarkBackground()
-}
-
-// EnvNoColor returns true if the environment variables explicitly disable color output
-// by setting NO_COLOR (https://no-color.org/)
-// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE
-// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset.
-func (o *Output) EnvNoColor() bool {
- return o.environ.Getenv("NO_COLOR") != "" || (o.environ.Getenv("CLICOLOR") == "0" && !o.cliColorForced())
-}
-
-// EnvNoColor returns true if the environment variables explicitly disable color output
-// by setting NO_COLOR (https://no-color.org/)
-// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE
-// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset.
-func EnvNoColor() bool {
- return output.EnvNoColor()
-}
-
-// EnvColorProfile returns the color profile based on environment variables set
-// Supports NO_COLOR (https://no-color.org/)
-// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If none of these environment variables are set, this behaves the same as ColorProfile()
-// It will return the Ascii color profile if EnvNoColor() returns true
-// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0"
-// then the ANSI color profile will be returned.
-func EnvColorProfile() Profile {
- return output.EnvColorProfile()
-}
-
-// EnvColorProfile returns the color profile based on environment variables set
-// Supports NO_COLOR (https://no-color.org/)
-// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If none of these environment variables are set, this behaves the same as ColorProfile()
-// It will return the Ascii color profile if EnvNoColor() returns true
-// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0"
-// then the ANSI color profile will be returned.
-func (o *Output) EnvColorProfile() Profile {
- if o.EnvNoColor() {
- return Ascii
- }
- p := o.ColorProfile()
- if o.cliColorForced() && p == Ascii {
- return ANSI
- }
- return p
-}
-
-func (o *Output) cliColorForced() bool {
- if forced := o.environ.Getenv("CLICOLOR_FORCE"); forced != "" {
- return forced != "0"
- }
- return false
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/termenv_other.go b/hack/tools/vendor/github.com/muesli/termenv/termenv_other.go
deleted file mode 100644
index 93a43b6acbf..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/termenv_other.go
+++ /dev/null
@@ -1,30 +0,0 @@
-//go:build js || plan9 || aix
-// +build js plan9 aix
-
-package termenv
-
-import "io"
-
-// ColorProfile returns the supported color profile:
-// ANSI256
-func (o Output) ColorProfile() Profile {
- return ANSI256
-}
-
-func (o Output) foregroundColor() Color {
- // default gray
- return ANSIColor(7)
-}
-
-func (o Output) backgroundColor() Color {
- // default black
- return ANSIColor(0)
-}
-
-// EnableVirtualTerminalProcessing enables virtual terminal processing on
-// Windows for w and returns a function that restores w to its previous state.
-// On non-Windows platforms, or if w does not refer to a terminal, then it
-// returns a non-nil no-op function and no error.
-func EnableVirtualTerminalProcessing(w io.Writer) (func() error, error) {
- return func() error { return nil }, nil
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/termenv_posix.go b/hack/tools/vendor/github.com/muesli/termenv/termenv_posix.go
deleted file mode 100644
index c971dd998f0..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/termenv_posix.go
+++ /dev/null
@@ -1,17 +0,0 @@
-//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos
-// +build darwin dragonfly freebsd linux netbsd openbsd zos
-
-package termenv
-
-import (
- "golang.org/x/sys/unix"
-)
-
-func isForeground(fd int) bool {
- pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP)
- if err != nil {
- return false
- }
-
- return pgrp == unix.Getpgrp()
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/termenv_solaris.go b/hack/tools/vendor/github.com/muesli/termenv/termenv_solaris.go
deleted file mode 100644
index 27a95a93e78..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/termenv_solaris.go
+++ /dev/null
@@ -1,22 +0,0 @@
-//go:build solaris || illumos
-// +build solaris illumos
-
-package termenv
-
-import (
- "golang.org/x/sys/unix"
-)
-
-func isForeground(fd int) bool {
- pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP)
- if err != nil {
- return false
- }
-
- g, err := unix.Getpgrp()
- if err != nil {
- return false
- }
-
- return pgrp == g
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/termenv_unix.go b/hack/tools/vendor/github.com/muesli/termenv/termenv_unix.go
deleted file mode 100644
index bef49ca3b23..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/termenv_unix.go
+++ /dev/null
@@ -1,301 +0,0 @@
-//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris zos
-
-package termenv
-
-import (
- "fmt"
- "io"
- "strconv"
- "strings"
- "time"
-
- "golang.org/x/sys/unix"
-)
-
-const (
- // timeout for OSC queries.
- OSCTimeout = 5 * time.Second
-)
-
-// ColorProfile returns the supported color profile:
-// Ascii, ANSI, ANSI256, or TrueColor.
-func (o *Output) ColorProfile() Profile {
- if !o.isTTY() {
- return Ascii
- }
-
- if o.environ.Getenv("GOOGLE_CLOUD_SHELL") == "true" {
- return TrueColor
- }
-
- term := o.environ.Getenv("TERM")
- colorTerm := o.environ.Getenv("COLORTERM")
-
- switch strings.ToLower(colorTerm) {
- case "24bit":
- fallthrough
- case "truecolor":
- if strings.HasPrefix(term, "screen") {
- // tmux supports TrueColor, screen only ANSI256
- if o.environ.Getenv("TERM_PROGRAM") != "tmux" {
- return ANSI256
- }
- }
- return TrueColor
- case "yes":
- fallthrough
- case "true":
- return ANSI256
- }
-
- switch term {
- case
- "alacritty",
- "contour",
- "rio",
- "wezterm",
- "xterm-ghostty",
- "xterm-kitty":
- return TrueColor
- case "linux", "xterm":
- return ANSI
- }
-
- if strings.Contains(term, "256color") {
- return ANSI256
- }
- if strings.Contains(term, "color") {
- return ANSI
- }
- if strings.Contains(term, "ansi") {
- return ANSI
- }
-
- return Ascii
-}
-
-//nolint:mnd
-func (o Output) foregroundColor() Color {
- s, err := o.termStatusReport(10)
- if err == nil {
- c, err := xTermColor(s)
- if err == nil {
- return c
- }
- }
-
- colorFGBG := o.environ.Getenv("COLORFGBG")
- if strings.Contains(colorFGBG, ";") {
- c := strings.Split(colorFGBG, ";")
- i, err := strconv.Atoi(c[0])
- if err == nil {
- return ANSIColor(i)
- }
- }
-
- // default gray
- return ANSIColor(7)
-}
-
-//nolint:mnd
-func (o Output) backgroundColor() Color {
- s, err := o.termStatusReport(11)
- if err == nil {
- c, err := xTermColor(s)
- if err == nil {
- return c
- }
- }
-
- colorFGBG := o.environ.Getenv("COLORFGBG")
- if strings.Contains(colorFGBG, ";") {
- c := strings.Split(colorFGBG, ";")
- i, err := strconv.Atoi(c[len(c)-1])
- if err == nil {
- return ANSIColor(i)
- }
- }
-
- // default black
- return ANSIColor(0)
-}
-
-func (o *Output) waitForData(timeout time.Duration) error {
- fd := o.TTY().Fd()
- tv := unix.NsecToTimeval(int64(timeout))
- var readfds unix.FdSet
- readfds.Set(int(fd)) //nolint:gosec
-
- for {
- n, err := unix.Select(int(fd)+1, &readfds, nil, nil, &tv) //nolint:gosec
- if err == unix.EINTR {
- continue
- }
- if err != nil {
- return err //nolint:wrapcheck
- }
- if n == 0 {
- return fmt.Errorf("timeout")
- }
-
- break
- }
-
- return nil
-}
-
-func (o *Output) readNextByte() (byte, error) {
- if !o.unsafe {
- if err := o.waitForData(OSCTimeout); err != nil {
- return 0, err
- }
- }
-
- var b [1]byte
- n, err := o.TTY().Read(b[:])
- if err != nil {
- return 0, err //nolint:wrapcheck
- }
-
- if n == 0 {
- panic("read returned no data")
- }
-
- return b[0], nil
-}
-
-// readNextResponse reads either an OSC response or a cursor position response:
-// - OSC response: "\x1b]11;rgb:1111/1111/1111\x1b\\"
-// - cursor position response: "\x1b[42;1R"
-func (o *Output) readNextResponse() (response string, isOSC bool, err error) {
- start, err := o.readNextByte()
- if err != nil {
- return "", false, err
- }
-
- // first byte must be ESC
- for start != ESC {
- start, err = o.readNextByte()
- if err != nil {
- return "", false, err
- }
- }
-
- response += string(start)
-
- // next byte is either '[' (cursor position response) or ']' (OSC response)
- tpe, err := o.readNextByte()
- if err != nil {
- return "", false, err
- }
-
- response += string(tpe)
-
- var oscResponse bool
- switch tpe {
- case '[':
- oscResponse = false
- case ']':
- oscResponse = true
- default:
- return "", false, ErrStatusReport
- }
-
- for {
- b, err := o.readNextByte()
- if err != nil {
- return "", false, err
- }
-
- response += string(b)
-
- if oscResponse {
- // OSC can be terminated by BEL (\a) or ST (ESC)
- if b == BEL || strings.HasSuffix(response, string(ESC)) {
- return response, true, nil
- }
- } else {
- // cursor position response is terminated by 'R'
- if b == 'R' {
- return response, false, nil
- }
- }
-
- // both responses have less than 25 bytes, so if we read more, that's an error
- if len(response) > 25 { //nolint:mnd
- break
- }
- }
-
- return "", false, ErrStatusReport
-}
-
-func (o Output) termStatusReport(sequence int) (string, error) {
- // screen/tmux can't support OSC, because they can be connected to multiple
- // terminals concurrently.
- term := o.environ.Getenv("TERM")
- if strings.HasPrefix(term, "screen") || strings.HasPrefix(term, "tmux") || strings.HasPrefix(term, "dumb") {
- return "", ErrStatusReport
- }
-
- tty := o.TTY()
- if tty == nil {
- return "", ErrStatusReport
- }
-
- if !o.unsafe {
- fd := int(tty.Fd()) //nolint:gosec
- // if in background, we can't control the terminal
- if !isForeground(fd) {
- return "", ErrStatusReport
- }
-
- t, err := unix.IoctlGetTermios(fd, tcgetattr)
- if err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
- defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck
-
- noecho := *t
- noecho.Lflag = noecho.Lflag &^ unix.ECHO
- noecho.Lflag = noecho.Lflag &^ unix.ICANON
- if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
- }
-
- // first, send OSC query, which is ignored by terminal which do not support it
- fmt.Fprintf(tty, OSC+"%d;?"+ST, sequence) //nolint:errcheck
-
- // then, query cursor position, should be supported by all terminals
- fmt.Fprintf(tty, CSI+"6n") //nolint:errcheck
-
- // read the next response
- res, isOSC, err := o.readNextResponse()
- if err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
-
- // if this is not OSC response, then the terminal does not support it
- if !isOSC {
- return "", ErrStatusReport
- }
-
- // read the cursor query response next and discard the result
- _, _, err = o.readNextResponse()
- if err != nil {
- return "", err
- }
-
- // fmt.Println("Rcvd", res[1:])
- return res, nil
-}
-
-// EnableVirtualTerminalProcessing enables virtual terminal processing on
-// Windows for w and returns a function that restores w to its previous state.
-// On non-Windows platforms, or if w does not refer to a terminal, then it
-// returns a non-nil no-op function and no error.
-func EnableVirtualTerminalProcessing(_ io.Writer) (func() error, error) {
- return func() error { return nil }, nil
-}
diff --git a/hack/tools/vendor/github.com/muesli/termenv/termenv_windows.go b/hack/tools/vendor/github.com/muesli/termenv/termenv_windows.go
deleted file mode 100644
index f9b1def0567..00000000000
--- a/hack/tools/vendor/github.com/muesli/termenv/termenv_windows.go
+++ /dev/null
@@ -1,140 +0,0 @@
-//go:build windows
-// +build windows
-
-package termenv
-
-import (
- "fmt"
- "os"
- "strconv"
-
- "golang.org/x/sys/windows"
-)
-
-func (o *Output) ColorProfile() Profile {
- if !o.isTTY() {
- return Ascii
- }
-
- if o.environ.Getenv("ConEmuANSI") == "ON" {
- return TrueColor
- }
-
- winVersion, _, buildNumber := windows.RtlGetNtVersionNumbers()
- if buildNumber < 10586 || winVersion < 10 {
- // No ANSI support before Windows 10 build 10586.
- if o.environ.Getenv("ANSICON") != "" {
- conVersion := o.environ.Getenv("ANSICON_VER")
- cv, err := strconv.ParseInt(conVersion, 10, 64)
- if err != nil || cv < 181 {
- // No 8 bit color support before v1.81 release.
- return ANSI
- }
-
- return ANSI256
- }
-
- return Ascii
- }
- if buildNumber < 14931 {
- // No true color support before build 14931.
- return ANSI256
- }
-
- return TrueColor
-}
-
-func (o Output) foregroundColor() Color {
- // default gray
- return ANSIColor(7)
-}
-
-func (o Output) backgroundColor() Color {
- // default black
- return ANSIColor(0)
-}
-
-// EnableWindowsANSIConsole enables virtual terminal processing on Windows
-// platforms. This allows the use of ANSI escape sequences in Windows console
-// applications. Ensure this gets called before anything gets rendered with
-// termenv.
-//
-// Returns the original console mode and an error if one occurred.
-func EnableWindowsANSIConsole() (uint32, error) {
- handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
- if err != nil {
- return 0, err
- }
-
- var mode uint32
- err = windows.GetConsoleMode(handle, &mode)
- if err != nil {
- return 0, err
- }
-
- // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
- if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
- vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
- if err := windows.SetConsoleMode(handle, vtpmode); err != nil {
- return 0, err
- }
- }
-
- return mode, nil
-}
-
-// RestoreWindowsConsole restores the console mode to a previous state.
-func RestoreWindowsConsole(mode uint32) error {
- handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
- if err != nil {
- return err
- }
-
- return windows.SetConsoleMode(handle, mode)
-}
-
-// EnableVirtualTerminalProcessing enables virtual terminal processing on
-// Windows for o and returns a function that restores o to its previous state.
-// On non-Windows platforms, or if o does not refer to a terminal, then it
-// returns a non-nil no-op function and no error.
-func EnableVirtualTerminalProcessing(o *Output) (restoreFunc func() error, err error) {
- // There is nothing to restore until we set the console mode.
- restoreFunc = func() error {
- return nil
- }
-
- // If o is not a tty, then there is nothing to do.
- tty, ok := o.Writer().(*os.File)
- if tty == nil || !ok {
- return
- }
-
- // Get the current console mode. If there is an error, assume that o is not
- // a terminal, discard the error, and return.
- var mode uint32
- if err2 := windows.GetConsoleMode(windows.Handle(tty.Fd()), &mode); err2 != nil {
- return
- }
-
- // If virtual terminal processing is already set, then there is nothing to
- // do and nothing to restore.
- if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING == windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
- return
- }
-
- // Enable virtual terminal processing. See
- // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
- if err2 := windows.SetConsoleMode(windows.Handle(tty.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err2 != nil {
- err = fmt.Errorf("windows.SetConsoleMode: %w", err2)
- return
- }
-
- // Set the restore function. We maintain a reference to the tty in the
- // closure (rather than just its handle) to ensure that the tty is not
- // closed by a finalizer.
- restoreFunc = func() error {
- return windows.SetConsoleMode(windows.Handle(tty.Fd()), mode)
- }
-
- return
-}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/.gitignore b/hack/tools/vendor/github.com/pelletier/go-toml/v2/.gitignore
index 4b7c4eda3a9..eaf580dfd8f 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/.gitignore
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/.gitignore
@@ -5,3 +5,4 @@ cmd/tomljson/tomljson
cmd/tomltestgen/tomltestgen
dist
tests/
+test-results
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/.golangci.toml b/hack/tools/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
index 067db551747..7d2e5b04cf8 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
@@ -1,84 +1,76 @@
-[service]
-golangci-lint-version = "1.39.0"
-
-[linters-settings.wsl]
-allow-assign-and-anything = true
-
-[linters-settings.exhaustive]
-default-signifies-exhaustive = true
+version = "2"
[linters]
-disable-all = true
+default = "none"
enable = [
"asciicheck",
"bodyclose",
- "cyclop",
- "deadcode",
- "depguard",
"dogsled",
"dupl",
"durationcheck",
"errcheck",
"errorlint",
"exhaustive",
- # "exhaustivestruct",
- "exportloopref",
"forbidigo",
- # "forcetypeassert",
- "funlen",
- "gci",
- # "gochecknoglobals",
"gochecknoinits",
- "gocognit",
"goconst",
"gocritic",
- "gocyclo",
- "godot",
- "godox",
- # "goerr113",
- "gofmt",
- "gofumpt",
+ "godoclint",
"goheader",
- "goimports",
- "golint",
- "gomnd",
- # "gomoddirectives",
"gomodguard",
"goprintffuncname",
"gosec",
- "gosimple",
"govet",
- # "ifshort",
"importas",
"ineffassign",
"lll",
"makezero",
+ "mirror",
"misspell",
"nakedret",
- "nestif",
"nilerr",
- # "nlreturn",
"noctx",
"nolintlint",
- #"paralleltest",
+ "perfsprint",
"prealloc",
"predeclared",
"revive",
"rowserrcheck",
"sqlclosecheck",
"staticcheck",
- "structcheck",
- "stylecheck",
- # "testpackage",
"thelper",
"tparallel",
- "typecheck",
"unconvert",
"unparam",
"unused",
- "varcheck",
+ "usetesting",
"wastedassign",
"whitespace",
- # "wrapcheck",
- # "wsl"
+]
+
+[linters.settings.exhaustive]
+default-signifies-exhaustive = true
+
+[linters.settings.lll]
+line-length = 150
+
+[[linters.exclusions.rules]]
+path = ".test.go"
+linters = ["goconst", "gosec"]
+
+[[linters.exclusions.rules]]
+path = "main.go"
+linters = ["forbidigo"]
+
+[[linters.exclusions.rules]]
+path = "internal"
+linters = ["revive"]
+text = "(exported|indent-error-flow): "
+
+[formatters]
+enable = [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
]
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/hack/tools/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
index 47f0f591423..3e19ea710a9 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
@@ -22,7 +22,6 @@ builds:
- linux_riscv64
- windows_amd64
- windows_arm64
- - windows_arm
- darwin_amd64
- darwin_arm64
- id: tomljson
@@ -42,7 +41,6 @@ builds:
- linux_riscv64
- windows_amd64
- windows_arm64
- - windows_arm
- darwin_amd64
- darwin_arm64
- id: jsontoml
@@ -62,7 +60,6 @@ builds:
- linux_arm
- windows_amd64
- windows_arm64
- - windows_arm
- darwin_amd64
- darwin_arm64
universal_binaries:
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/AGENTS.md b/hack/tools/vendor/github.com/pelletier/go-toml/v2/AGENTS.md
new file mode 100644
index 00000000000..dafe44d764b
--- /dev/null
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/AGENTS.md
@@ -0,0 +1,64 @@
+# Agent Guidelines for go-toml
+
+This file provides guidelines for AI agents contributing to go-toml. All agents must follow these rules derived from [CONTRIBUTING.md](./CONTRIBUTING.md).
+
+## Project Overview
+
+go-toml is a TOML library for Go. The goal is to provide an easy-to-use and efficient TOML implementation that gets the job done without getting in the way.
+
+## Code Change Rules
+
+### Backward Compatibility
+
+- **No backward-incompatible changes** unless explicitly discussed and approved
+- Avoid breaking people's programs unless absolutely necessary
+
+### Testing Requirements
+
+- **All bug fixes must include regression tests**
+- **All new code must be tested**
+- Run tests before submitting: `go test -race ./...`
+- Test coverage must not decrease. Check with:
+ ```bash
+ go test -covermode=atomic -coverprofile=coverage.out
+ go tool cover -func=coverage.out
+ ```
+- All lines of code touched by changes should be covered by tests
+
+### Performance Requirements
+
+- go-toml aims to stay efficient; avoid performance regressions
+- Run benchmarks to verify: `go test ./... -bench=. -count=10`
+- Compare results using [benchstat](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat)
+
+### Documentation
+
+- New features or feature extensions must include documentation
+- Documentation lives in [README.md](./README.md) and throughout source code
+
+### Code Style
+
+- Follow existing code format and structure
+- Code must pass `go fmt`
+- Code must pass linting with the same golangci-lint version as CI (see version in `.github/workflows/lint.yml`):
+ ```bash
+ # Install specific version (check lint.yml for current version)
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin
+ # Run linter
+ golangci-lint run ./...
+ ```
+
+### Commit Messages
+
+- Commit messages must explain **why** the change is needed
+- Keep messages clear and informative even if details are in the PR description
+
+## Pull Request Checklist
+
+Before submitting:
+
+1. Tests pass (`go test -race ./...`)
+2. No backward-incompatible changes (unless discussed)
+3. Relevant documentation added/updated
+4. No performance regression (verify with benchmarks)
+5. Title is clear and understandable for changelog
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md b/hack/tools/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
index 96ecf9e2b3a..28b88ec334b 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
@@ -33,7 +33,7 @@ The documentation is present in the [README][readme] and thorough the source
code. On release, it gets updated on [pkg.go.dev][pkg.go.dev]. To make a change
to the documentation, create a pull request with your proposed changes. For
simple changes like that, the easiest way to go is probably the "Fork this
-project and edit the file" button on Github, displayed at the top right of the
+project and edit the file" button on GitHub, displayed at the top right of the
file. Unless it's a trivial change (for example a typo), provide a little bit of
context in your pull request description or commit message.
@@ -92,6 +92,48 @@ However, given GitHub's new policy to _not_ run Actions on pull requests until a
maintainer clicks on button, it is highly recommended that you run them locally
as you make changes.
+### Test across Go versions
+
+The repository includes tooling to test go-toml across multiple Go versions
+(1.11 through 1.25) both locally and in GitHub Actions.
+
+#### Local testing with Docker
+
+Prerequisites: Docker installed and running, Bash shell, `rsync` command.
+
+```bash
+# Test all Go versions in parallel (default)
+./test-go-versions.sh
+
+# Test specific versions
+./test-go-versions.sh 1.21 1.22 1.23
+
+# Test sequentially (slower but uses less resources)
+./test-go-versions.sh --sequential
+
+# Verbose output with custom results directory
+./test-go-versions.sh --verbose --output ./my-results 1.24 1.25
+
+# Show all options
+./test-go-versions.sh --help
+```
+
+The script creates Docker containers for each Go version and runs the full test
+suite. Results are saved to a `test-results/` directory with individual logs and
+a comprehensive summary report.
+
+The script only exits with a non-zero status code if either of the two most
+recent Go versions fail.
+
+#### GitHub Actions testing (maintainers)
+
+1. Go to the **Actions** tab in the GitHub repository
+2. Select **"Go Versions Compatibility Test"** from the workflow list
+3. Click **"Run workflow"**
+4. Optionally customize:
+ - **Go versions**: Space-separated list (e.g., `1.21 1.22 1.23`)
+ - **Execution mode**: Parallel (faster) or sequential (more stable)
+
### Check coverage
We use `go tool cover` to compute test coverage. Most code editors have a way to
@@ -111,7 +153,7 @@ code lowers the coverage.
Go-toml aims to stay efficient. We rely on a set of scenarios executed with Go's
builtin benchmark systems. Because of their noisy nature, containers provided by
-Github Actions cannot be reliably used for benchmarking. As a result, you are
+GitHub Actions cannot be reliably used for benchmarking. As a result, you are
responsible for checking that your changes do not incur a performance penalty.
You can run their following to execute benchmarks:
@@ -168,13 +210,13 @@ Checklist:
1. Decide on the next version number. Use semver. Review commits since last
version to assess.
2. Tag release. For example:
-```
-git checkout v2
-git pull
-git tag v2.2.0
-git push --tags
-```
-3. CI automatically builds a draft Github release. Review it and edit as
+ ```
+ git checkout v2
+ git pull
+ git tag v2.2.0
+ git push --tags
+ ```
+3. CI automatically builds a draft GitHub release. Review it and edit as
necessary. Look for "Other changes". That would indicate a pull request not
labeled properly. Tweak labels and pull request titles until changelog looks
good for users.
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/README.md b/hack/tools/vendor/github.com/pelletier/go-toml/v2/README.md
index 0755e55642d..14e65644963 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/README.md
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/README.md
@@ -21,8 +21,6 @@ documentation.
import "github.com/pelletier/go-toml/v2"
```
-See [Modules](#Modules).
-
## Features
### Stdlib behavior
@@ -107,7 +105,11 @@ type MyConfig struct {
### Unmarshaling
[`Unmarshal`][unmarshal] reads a TOML document and fills a Go structure with its
-content. For example:
+content.
+
+Note that the struct variable names are _capitalized_, while the variables in the toml document are _lowercase_.
+
+For example:
```go
doc := `
@@ -133,6 +135,62 @@ fmt.Println("tags:", cfg.Tags)
[unmarshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Unmarshal
+
+Here is an example using tables with some simple nesting:
+
+```go
+doc := `
+age = 45
+fruits = ["apple", "pear"]
+
+# these are very important!
+[my-variables]
+first = 1
+second = 0.2
+third = "abc"
+
+# this is not so important.
+[my-variables.b]
+bfirst = 123
+`
+
+var Document struct {
+ Age int
+ Fruits []string
+
+ Myvariables struct {
+ First int
+ Second float64
+ Third string
+
+ B struct {
+ Bfirst int
+ }
+ } `toml:"my-variables"`
+}
+
+err := toml.Unmarshal([]byte(doc), &Document)
+if err != nil {
+ panic(err)
+}
+
+fmt.Println("age:", Document.Age)
+fmt.Println("fruits:", Document.Fruits)
+fmt.Println("my-variables.first:", Document.Myvariables.First)
+fmt.Println("my-variables.second:", Document.Myvariables.Second)
+fmt.Println("my-variables.third:", Document.Myvariables.Third)
+fmt.Println("my-variables.B.Bfirst:", Document.Myvariables.B.Bfirst)
+
+// Output:
+// age: 45
+// fruits: [apple pear]
+// my-variables.first: 1
+// my-variables.second: 0.2
+// my-variables.third: abc
+// my-variables.B.Bfirst: 123
+```
+
+
### Marshaling
[`Marshal`][marshal] is the opposite of Unmarshal: it represents a Go structure
@@ -175,17 +233,17 @@ the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
Execution time speedup compared to other Go TOML libraries:
-
- | Benchmark | go-toml v1 | BurntSushi/toml |
-
-
- | Marshal/HugoFrontMatter-2 | 1.9x | 2.2x |
- | Marshal/ReferenceFile/map-2 | 1.7x | 2.1x |
- | Marshal/ReferenceFile/struct-2 | 2.2x | 3.0x |
- | Unmarshal/HugoFrontMatter-2 | 2.9x | 2.7x |
- | Unmarshal/ReferenceFile/map-2 | 2.6x | 2.7x |
- | Unmarshal/ReferenceFile/struct-2 | 4.6x | 5.1x |
-
+
+ | Benchmark | go-toml v1 | BurntSushi/toml |
+
+
+ | Marshal/HugoFrontMatter-2 | 2.1x | 2.0x |
+ | Marshal/ReferenceFile/map-2 | 2.0x | 2.0x |
+ | Marshal/ReferenceFile/struct-2 | 2.3x | 2.5x |
+ | Unmarshal/HugoFrontMatter-2 | 3.3x | 2.8x |
+ | Unmarshal/ReferenceFile/map-2 | 2.9x | 3.0x |
+ | Unmarshal/ReferenceFile/struct-2 | 4.8x | 5.0x |
+
See more
The table above has the results of the most common use-cases. The table below
@@ -193,40 +251,26 @@ contains the results of all benchmarks, including unrealistic ones. It is
provided for completeness.
-
- | Benchmark | go-toml v1 | BurntSushi/toml |
-
-
- | Marshal/SimpleDocument/map-2 | 1.8x | 2.7x |
- | Marshal/SimpleDocument/struct-2 | 2.7x | 3.8x |
- | Unmarshal/SimpleDocument/map-2 | 3.8x | 3.0x |
- | Unmarshal/SimpleDocument/struct-2 | 5.6x | 4.1x |
- | UnmarshalDataset/example-2 | 3.0x | 3.2x |
- | UnmarshalDataset/code-2 | 2.3x | 2.9x |
- | UnmarshalDataset/twitter-2 | 2.6x | 2.7x |
- | UnmarshalDataset/citm_catalog-2 | 2.2x | 2.3x |
- | UnmarshalDataset/canada-2 | 1.8x | 1.5x |
- | UnmarshalDataset/config-2 | 4.1x | 2.9x |
- | geomean | 2.7x | 2.8x |
-
+
+ | Benchmark | go-toml v1 | BurntSushi/toml |
+
+
+ | Marshal/SimpleDocument/map-2 | 2.0x | 2.9x |
+ | Marshal/SimpleDocument/struct-2 | 2.5x | 3.6x |
+ | Unmarshal/SimpleDocument/map-2 | 4.2x | 3.4x |
+ | Unmarshal/SimpleDocument/struct-2 | 5.9x | 4.4x |
+ | UnmarshalDataset/example-2 | 3.2x | 2.9x |
+ | UnmarshalDataset/code-2 | 2.4x | 2.8x |
+ | UnmarshalDataset/twitter-2 | 2.7x | 2.5x |
+ | UnmarshalDataset/citm_catalog-2 | 2.3x | 2.3x |
+ | UnmarshalDataset/canada-2 | 1.9x | 1.5x |
+ | UnmarshalDataset/config-2 | 5.4x | 3.0x |
+ | geomean | 2.9x | 2.8x |
+
This table can be generated with ./ci.sh benchmark -a -html.
-## Modules
-
-go-toml uses Go's standard modules system.
-
-Installation instructions:
-
-- Go ≥ 1.16: Nothing to do. Use the import in your code. The `go` command deals
- with it automatically.
-- Go ≥ 1.13: `GO111MODULE=on go get github.com/pelletier/go-toml/v2`.
-
-In case of trouble: [Go Modules FAQ][mod-faq].
-
-[mod-faq]: https://github.com/golang/go/wiki/Modules#why-does-installing-a-tool-via-go-get-fail-with-error-cannot-find-main-module
-
## Tools
Go-toml provides three handy command line tools:
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/ci.sh b/hack/tools/vendor/github.com/pelletier/go-toml/v2/ci.sh
index 86217a9b097..30c23d1a176 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/ci.sh
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/ci.sh
@@ -147,7 +147,7 @@ bench() {
pushd "$dir"
if [ "${replace}" != "" ]; then
- find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2|${replace}|g" {} \;
+ find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2\"|${replace}\"|g" {} \;
go get "${replace}"
fi
@@ -195,6 +195,11 @@ for line in reversed(lines[2:]):
"%.1fx" % (float(line[3])/v2), # v1
"%.1fx" % (float(line[7])/v2), # bs
])
+
+if not results:
+ print("No benchmark results to display.", file=sys.stderr)
+ sys.exit(1)
+
# move geomean to the end
results.append(results[0])
del results[0]
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/decode.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/decode.go
index f0ec3b17054..f3f14eff188 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/decode.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/decode.go
@@ -230,8 +230,8 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
return t, nil, err
}
- if t.Second > 60 {
- return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60")
+ if t.Second > 59 {
+ return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater than 59")
}
b = b[8:]
@@ -279,7 +279,6 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
return t, b, nil
}
-//nolint:cyclop
func parseFloat(b []byte) (float64, error) {
if len(b) == 4 && (b[0] == '+' || b[0] == '-') && b[1] == 'n' && b[2] == 'a' && b[3] == 'n' {
return math.NaN(), nil
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/errors.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/errors.go
index 309733f1f9f..d68835dfa60 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/errors.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/errors.go
@@ -2,10 +2,10 @@ package toml
import (
"fmt"
+ "reflect"
"strconv"
"strings"
- "github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/unstable"
)
@@ -54,6 +54,18 @@ func (s *StrictMissingError) String() string {
return buf.String()
}
+// Unwrap returns wrapped decode errors
+//
+// Implements errors.Join() interface.
+func (s *StrictMissingError) Unwrap() []error {
+ errs := make([]error, len(s.Errors))
+ for i := range s.Errors {
+ errs[i] = &s.Errors[i]
+ }
+ return errs
+}
+
+// Key represents a TOML key as a sequence of key parts.
type Key []string
// Error returns the error message contained in the DecodeError.
@@ -78,7 +90,7 @@ func (e *DecodeError) Key() Key {
return e.key
}
-// decodeErrorFromHighlight creates a DecodeError referencing a highlighted
+// wrapDecodeError creates a DecodeError referencing a highlighted
// range of bytes from document.
//
// highlight needs to be a sub-slice of document, or this function panics.
@@ -88,7 +100,7 @@ func (e *DecodeError) Key() Key {
//
//nolint:funlen
func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
- offset := danger.SubsliceOffset(document, de.Highlight)
+ offset := subsliceOffset(document, de.Highlight)
errMessage := de.Error()
errLine, errColumn := positionAtEnd(document[:offset])
@@ -248,5 +260,24 @@ func positionAtEnd(b []byte) (row int, column int) {
}
}
- return
+ return row, column
+}
+
+// subsliceOffset returns the byte offset of subslice within data.
+// subslice must share the same backing array as data.
+func subsliceOffset(data []byte, subslice []byte) int {
+ if len(subslice) == 0 {
+ return 0
+ }
+
+ // Use reflect to get the data pointers of both slices.
+ // This is safe because we're only reading the pointer values for comparison.
+ dataPtr := reflect.ValueOf(data).Pointer()
+ subPtr := reflect.ValueOf(subslice).Pointer()
+
+ offset := int(subPtr - dataPtr)
+ if offset < 0 || offset > len(data) {
+ panic("subslice is not within data")
+ }
+ return offset
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
index 80f698db4b0..50a6d170298 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
@@ -1,6 +1,6 @@
package characters
-var invalidAsciiTable = [256]bool{
+var invalidASCIITable = [256]bool{
0x00: true,
0x01: true,
0x02: true,
@@ -37,6 +37,6 @@ var invalidAsciiTable = [256]bool{
0x7F: true,
}
-func InvalidAscii(b byte) bool {
- return invalidAsciiTable[b]
+func InvalidASCII(b byte) bool {
+ return invalidASCIITable[b]
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
index db4f45acbf0..7c5cb55e429 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
@@ -1,20 +1,12 @@
+// Package characters provides functions for working with string encodings.
package characters
import (
"unicode/utf8"
)
-type utf8Err struct {
- Index int
- Size int
-}
-
-func (u utf8Err) Zero() bool {
- return u.Size == 0
-}
-
-// Verified that a given string is only made of valid UTF-8 characters allowed
-// by the TOML spec:
+// Utf8TomlValidAlreadyEscaped verifies that a given string is only made of
+// valid UTF-8 characters allowed by the TOML spec:
//
// Any Unicode character may be used except those that must be escaped:
// quotation mark, backslash, and the control characters other than tab (U+0000
@@ -23,8 +15,8 @@ func (u utf8Err) Zero() bool {
// It is a copy of the Go 1.17 utf8.Valid implementation, tweaked to exit early
// when a character is not allowed.
//
-// The returned utf8Err is Zero() if the string is valid, or contains the byte
-// index and size of the invalid character.
+// The returned slice is empty if the string is valid, or contains the bytes
+// of the invalid character.
//
// quotation mark => already checked
// backslash => already checked
@@ -32,9 +24,8 @@ func (u utf8Err) Zero() bool {
// 0x9 => tab, ok
// 0xA - 0x1F => invalid
// 0x7F => invalid
-func Utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
+func Utf8TomlValidAlreadyEscaped(p []byte) []byte {
// Fast path. Check for and skip 8 bytes of ASCII characters per iteration.
- offset := 0
for len(p) >= 8 {
// Combining two 32 bit loads allows the same code to be used
// for 32 and 64 bit platforms.
@@ -48,24 +39,19 @@ func Utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
}
for i, b := range p[:8] {
- if InvalidAscii(b) {
- err.Index = offset + i
- err.Size = 1
- return
+ if InvalidASCII(b) {
+ return p[i : i+1]
}
}
p = p[8:]
- offset += 8
}
n := len(p)
for i := 0; i < n; {
pi := p[i]
if pi < utf8.RuneSelf {
- if InvalidAscii(pi) {
- err.Index = offset + i
- err.Size = 1
- return
+ if InvalidASCII(pi) {
+ return p[i : i+1]
}
i++
continue
@@ -73,44 +59,34 @@ func Utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
x := first[pi]
if x == xx {
// Illegal starter byte.
- err.Index = offset + i
- err.Size = 1
- return
+ return p[i : i+1]
}
size := int(x & 7)
if i+size > n {
// Short or invalid.
- err.Index = offset + i
- err.Size = n - i
- return
+ return p[i:n]
}
accept := acceptRanges[x>>4]
if c := p[i+1]; c < accept.lo || accept.hi < c {
- err.Index = offset + i
- err.Size = 2
- return
- } else if size == 2 {
+ return p[i : i+2]
+ } else if size == 2 { //revive:disable:empty-block
} else if c := p[i+2]; c < locb || hicb < c {
- err.Index = offset + i
- err.Size = 3
- return
- } else if size == 3 {
+ return p[i : i+3]
+ } else if size == 3 { //revive:disable:empty-block
} else if c := p[i+3]; c < locb || hicb < c {
- err.Index = offset + i
- err.Size = 4
- return
+ return p[i : i+4]
}
i += size
}
- return
+ return nil
}
-// Return the size of the next rune if valid, 0 otherwise.
+// Utf8ValidNext returns the size of the next rune if valid, 0 otherwise.
func Utf8ValidNext(p []byte) int {
c := p[0]
if c < utf8.RuneSelf {
- if InvalidAscii(c) {
+ if InvalidASCII(c) {
return 0
}
return 1
@@ -129,10 +105,10 @@ func Utf8ValidNext(p []byte) int {
accept := acceptRanges[x>>4]
if c := p[1]; c < accept.lo || accept.hi < c {
return 0
- } else if size == 2 {
+ } else if size == 2 { //nolint:revive
} else if c := p[2]; c < locb || hicb < c {
return 0
- } else if size == 3 {
+ } else if size == 3 { //nolint:revive
} else if c := p[3]; c < locb || hicb < c {
return 0
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
deleted file mode 100644
index e38e1131b88..00000000000
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package danger
-
-import (
- "fmt"
- "reflect"
- "unsafe"
-)
-
-const maxInt = uintptr(int(^uint(0) >> 1))
-
-func SubsliceOffset(data []byte, subslice []byte) int {
- datap := (*reflect.SliceHeader)(unsafe.Pointer(&data))
- hlp := (*reflect.SliceHeader)(unsafe.Pointer(&subslice))
-
- if hlp.Data < datap.Data {
- panic(fmt.Errorf("subslice address (%d) is before data address (%d)", hlp.Data, datap.Data))
- }
- offset := hlp.Data - datap.Data
-
- if offset > maxInt {
- panic(fmt.Errorf("slice offset larger than int (%d)", offset))
- }
-
- intoffset := int(offset)
-
- if intoffset > datap.Len {
- panic(fmt.Errorf("slice offset (%d) is farther than data length (%d)", intoffset, datap.Len))
- }
-
- if intoffset+hlp.Len > datap.Len {
- panic(fmt.Errorf("slice ends (%d+%d) is farther than data length (%d)", intoffset, hlp.Len, datap.Len))
- }
-
- return intoffset
-}
-
-func BytesRange(start []byte, end []byte) []byte {
- if start == nil || end == nil {
- panic("cannot call BytesRange with nil")
- }
- startp := (*reflect.SliceHeader)(unsafe.Pointer(&start))
- endp := (*reflect.SliceHeader)(unsafe.Pointer(&end))
-
- if startp.Data > endp.Data {
- panic(fmt.Errorf("start pointer address (%d) is after end pointer address (%d)", startp.Data, endp.Data))
- }
-
- l := startp.Len
- endLen := int(endp.Data-startp.Data) + endp.Len
- if endLen > l {
- l = endLen
- }
-
- if l > startp.Cap {
- panic(fmt.Errorf("range length is larger than capacity"))
- }
-
- return start[:l]
-}
-
-func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer {
- // TODO: replace with unsafe.Add when Go 1.17 is released
- // https://github.com/golang/go/issues/40481
- return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset))
-}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
deleted file mode 100644
index 9d41c28a2f2..00000000000
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package danger
-
-import (
- "reflect"
- "unsafe"
-)
-
-// typeID is used as key in encoder and decoder caches to enable using
-// the optimize runtime.mapaccess2_fast64 function instead of the more
-// expensive lookup if we were to use reflect.Type as map key.
-//
-// typeID holds the pointer to the reflect.Type value, which is unique
-// in the program.
-//
-// https://github.com/segmentio/encoding/blob/master/json/codec.go#L59-L61
-type TypeID unsafe.Pointer
-
-func MakeTypeID(t reflect.Type) TypeID {
- // reflect.Type has the fields:
- // typ unsafe.Pointer
- // ptr unsafe.Pointer
- return TypeID((*[2]unsafe.Pointer)(unsafe.Pointer(&t))[1])
-}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
index 149b17f538b..6344fd047de 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
@@ -36,7 +36,7 @@ func (t *KeyTracker) Pop(node *unstable.Node) {
}
}
-// Key returns the current key
+// Key returns the current key.
func (t *KeyTracker) Key() []string {
k := make([]string, len(t.k))
copy(k, t.k)
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
index 76df2d5b6a9..20623580012 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
@@ -288,11 +288,12 @@ func (s *SeenTracker) checkKeyValue(node *unstable.Node) (bool, error) {
idx = s.create(parentIdx, k, tableKind, false, true)
} else {
entry := s.entries[idx]
- if it.IsLast() {
+ switch {
+ case it.IsLast():
return false, fmt.Errorf("toml: key %s is already defined", string(k))
- } else if entry.kind != tableKind {
+ case entry.kind != tableKind:
return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
- } else if entry.explicit {
+ case entry.explicit:
return false, fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k))
}
}
@@ -309,16 +310,16 @@ func (s *SeenTracker) checkKeyValue(node *unstable.Node) (bool, error) {
return s.checkInlineTable(value)
case unstable.Array:
return s.checkArray(value)
+ default:
+ return false, nil
}
-
- return false, nil
}
func (s *SeenTracker) checkArray(node *unstable.Node) (first bool, err error) {
it := node.Children()
for it.Next() {
n := it.Node()
- switch n.Kind {
+ switch n.Kind { //nolint:exhaustive
case unstable.InlineTable:
first, err = s.checkInlineTable(n)
if err != nil {
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
index bf0317392f4..ed510382c06 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
@@ -1 +1,2 @@
+// Package tracker provides functions for keeping track of AST nodes.
package tracker
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/localtime.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/localtime.go
index a856bfdb0d1..502ef2f2f11 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/localtime.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/localtime.go
@@ -45,7 +45,7 @@ func (d *LocalDate) UnmarshalText(b []byte) error {
type LocalTime struct {
Hour int // Hour of the day: [0; 24[
Minute int // Minute of the hour: [0; 60[
- Second int // Second of the minute: [0; 60[
+ Second int // Second of the minute: [0; 59]
Nanosecond int // Nanoseconds within the second: [0, 1000000000[
Precision int // Number of digits to display for Nanosecond.
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/marshaler.go
index 161acd93439..ca462d40e03 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/marshaler.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/marshaler.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding"
"encoding/json"
+ "errors"
"fmt"
"io"
"math"
@@ -42,7 +43,7 @@ type Encoder struct {
arraysMultiline bool
indentSymbol string
indentTables bool
- marshalJsonNumbers bool
+ marshalJSONNumbers bool
}
// NewEncoder returns a new Encoder that writes to w.
@@ -89,14 +90,14 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
return enc
}
-// SetMarshalJsonNumbers forces the encoder to serialize `json.Number` as a
+// SetMarshalJSONNumbers forces the encoder to serialize `json.Number` as a
// float or integer instead of relying on TextMarshaler to emit a string.
//
// *Unstable:* This method does not follow the compatibility guarantees of
// semver. It can be changed or removed without a new major version being
// issued.
-func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
- enc.marshalJsonNumbers = indent
+func (enc *Encoder) SetMarshalJSONNumbers(indent bool) *Encoder {
+ enc.marshalJSONNumbers = indent
return enc
}
@@ -161,6 +162,8 @@ func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
//
// The "omitempty" option prevents empty values or groups from being emitted.
//
+// The "omitzero" option prevents zero values or groups from being emitted.
+//
// The "commented" option prefixes the value and all its children with a comment
// symbol.
//
@@ -177,7 +180,7 @@ func (enc *Encoder) Encode(v interface{}) error {
ctx.inline = enc.tablesInline
if v == nil {
- return fmt.Errorf("toml: cannot encode a nil interface")
+ return errors.New("toml: cannot encode a nil interface")
}
b, err := enc.encode(b, ctx, reflect.ValueOf(v))
@@ -196,6 +199,7 @@ func (enc *Encoder) Encode(v interface{}) error {
type valueOptions struct {
multiline bool
omitempty bool
+ omitzero bool
commented bool
comment string
}
@@ -266,16 +270,15 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
case LocalDateTime:
return append(b, x.String()...), nil
case json.Number:
- if enc.marshalJsonNumbers {
+ if enc.marshalJSONNumbers {
if x == "" { /// Useful zero value.
return append(b, "0"...), nil
} else if v, err := x.Int64(); err == nil {
return enc.encode(b, ctx, reflect.ValueOf(v))
} else if f, err := x.Float64(); err == nil {
return enc.encode(b, ctx, reflect.ValueOf(f))
- } else {
- return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x)
}
+ return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x)
}
}
@@ -309,7 +312,7 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
return enc.encodeSlice(b, ctx, v)
case reflect.Interface:
if v.IsNil() {
- return nil, fmt.Errorf("toml: encoding a nil interface is not supported")
+ return nil, errors.New("toml: encoding a nil interface is not supported")
}
return enc.encode(b, ctx, v.Elem())
@@ -326,28 +329,30 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
case reflect.Float32:
f := v.Float()
- if math.IsNaN(f) {
+ switch {
+ case math.IsNaN(f):
b = append(b, "nan"...)
- } else if f > math.MaxFloat32 {
+ case f > math.MaxFloat32:
b = append(b, "inf"...)
- } else if f < -math.MaxFloat32 {
+ case f < -math.MaxFloat32:
b = append(b, "-inf"...)
- } else if math.Trunc(f) == f {
+ case math.Trunc(f) == f:
b = strconv.AppendFloat(b, f, 'f', 1, 32)
- } else {
+ default:
b = strconv.AppendFloat(b, f, 'f', -1, 32)
}
case reflect.Float64:
f := v.Float()
- if math.IsNaN(f) {
+ switch {
+ case math.IsNaN(f):
b = append(b, "nan"...)
- } else if f > math.MaxFloat64 {
+ case f > math.MaxFloat64:
b = append(b, "inf"...)
- } else if f < -math.MaxFloat64 {
+ case f < -math.MaxFloat64:
b = append(b, "-inf"...)
- } else if math.Trunc(f) == f {
+ case math.Trunc(f) == f:
b = strconv.AppendFloat(b, f, 'f', 1, 64)
- } else {
+ default:
b = strconv.AppendFloat(b, f, 'f', -1, 64)
}
case reflect.Bool:
@@ -384,6 +389,31 @@ func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
return options.omitempty && isEmptyValue(v)
}
+func shouldOmitZero(options valueOptions, v reflect.Value) bool {
+ if !options.omitzero {
+ return false
+ }
+
+ // Check if the type implements isZeroer interface (has a custom IsZero method).
+ if v.Type().Implements(isZeroerType) {
+ return v.Interface().(isZeroer).IsZero()
+ }
+
+ // Check if pointer type implements isZeroer.
+ if reflect.PointerTo(v.Type()).Implements(isZeroerType) {
+ if v.CanAddr() {
+ return v.Addr().Interface().(isZeroer).IsZero()
+ }
+ // Create a temporary addressable copy to call the pointer receiver method.
+ pv := reflect.New(v.Type())
+ pv.Elem().Set(v)
+ return pv.Interface().(isZeroer).IsZero()
+ }
+
+ // Fall back to reflect's IsZero for types without custom IsZero method.
+ return v.IsZero()
+}
+
func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {
var err error
@@ -434,8 +464,9 @@ func isEmptyValue(v reflect.Value) bool {
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
+ default:
+ return false
}
- return false
}
func isEmptyStruct(v reflect.Value) bool {
@@ -479,7 +510,7 @@ func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byt
func needsQuoting(v string) bool {
// TODO: vectorize
for _, b := range []byte(v) {
- if b == '\'' || b == '\r' || b == '\n' || characters.InvalidAscii(b) {
+ if b == '\'' || b == '\r' || b == '\n' || characters.InvalidASCII(b) {
return true
}
}
@@ -517,12 +548,26 @@ func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byt
del = 0x7f
)
- for _, r := range []byte(v) {
+ bv := []byte(v)
+ for i := 0; i < len(bv); i++ {
+ r := bv[i]
switch r {
case '\\':
b = append(b, `\\`...)
case '"':
- b = append(b, `\"`...)
+ if multiline {
+ // Quotation marks do not need to be quoted in multiline strings unless
+ // it contains 3 consecutive. If 3+ quotes appear, quote all of them
+ // because it's visually better
+ if i+2 > len(bv) || bv[i+1] != '"' || bv[i+2] != '"' {
+ b = append(b, r)
+ } else {
+ b = append(b, `\"\"\"`...)
+ i += 2
+ }
+ } else {
+ b = append(b, `\"`...)
+ }
case '\b':
b = append(b, `\b`...)
case '\f':
@@ -559,9 +604,9 @@ func (enc *Encoder) encodeUnquotedKey(b []byte, v string) []byte {
return append(b, v...)
}
-func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error) {
+func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) []byte {
if len(ctx.parentKey) == 0 {
- return b, nil
+ return b
}
b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
@@ -581,10 +626,9 @@ func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error)
b = append(b, "]\n"...)
- return b, nil
+ return b
}
-//nolint:cyclop
func (enc *Encoder) encodeKey(b []byte, k string) []byte {
needsQuotation := false
cannotUseLiteral := false
@@ -621,30 +665,33 @@ func (enc *Encoder) encodeKey(b []byte, k string) []byte {
func (enc *Encoder) keyToString(k reflect.Value) (string, error) {
keyType := k.Type()
- switch {
- case keyType.Kind() == reflect.String:
- return k.String(), nil
-
- case keyType.Implements(textMarshalerType):
+ if keyType.Implements(textMarshalerType) {
keyB, err := k.Interface().(encoding.TextMarshaler).MarshalText()
if err != nil {
return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err)
}
return string(keyB), nil
+ }
+
+ switch keyType.Kind() {
+ case reflect.String:
+ return k.String(), nil
- case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(k.Int(), 10), nil
- case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(k.Uint(), 10), nil
- case keyType.Kind() == reflect.Float32:
+ case reflect.Float32:
return strconv.FormatFloat(k.Float(), 'f', -1, 32), nil
- case keyType.Kind() == reflect.Float64:
+ case reflect.Float64:
return strconv.FormatFloat(k.Float(), 'f', -1, 64), nil
+
+ default:
+ return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind())
}
- return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind())
}
func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
@@ -657,8 +704,18 @@ func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte
for iter.Next() {
v := iter.Value()
- if isNil(v) {
- continue
+ // Handle nil values: convert nil pointers to zero value,
+ // skip nil interfaces and nil maps.
+ switch v.Kind() {
+ case reflect.Ptr:
+ if v.IsNil() {
+ v = reflect.Zero(v.Type().Elem())
+ }
+ case reflect.Interface, reflect.Map:
+ if v.IsNil() {
+ continue
+ }
+ default:
}
k, err := enc.keyToString(iter.Key())
@@ -748,9 +805,8 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
walkStruct(ctx, t, f.Elem())
}
continue
- } else {
- k = fieldType.Name
}
+ k = fieldType.Name
}
if isNil(f) {
@@ -760,6 +816,7 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
options := valueOptions{
multiline: opts.multiline,
omitempty: opts.omitempty,
+ omitzero: opts.omitzero,
commented: opts.commented,
comment: fieldType.Tag.Get("comment"),
}
@@ -820,6 +877,7 @@ type tagOptions struct {
multiline bool
inline bool
omitempty bool
+ omitzero bool
commented bool
}
@@ -832,7 +890,7 @@ func parseTag(tag string) (string, tagOptions) {
}
raw := tag[idx+1:]
- tag = string(tag[:idx])
+ tag = tag[:idx]
for raw != "" {
var o string
i := strings.Index(raw, ",")
@@ -848,6 +906,8 @@ func parseTag(tag string) (string, tagOptions) {
opts.inline = true
case "omitempty":
opts.omitempty = true
+ case "omitzero":
+ opts.omitzero = true
case "commented":
opts.commented = true
}
@@ -866,10 +926,7 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
}
if !ctx.skipTableHeader {
- b, err = enc.encodeTableHeader(ctx, b)
- if err != nil {
- return nil, err
- }
+ b = enc.encodeTableHeader(ctx, b)
if enc.indentTables && len(ctx.parentKey) > 0 {
ctx.indent++
@@ -882,6 +939,9 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
if shouldOmitEmpty(kv.Options, kv.Value) {
continue
}
+ if kv.Options.omitzero && shouldOmitZero(kv.Options, kv.Value) {
+ continue
+ }
hasNonEmptyKV = true
ctx.setKey(kv.Key)
@@ -901,6 +961,9 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
if shouldOmitEmpty(table.Options, table.Value) {
continue
}
+ if table.Options.omitzero && shouldOmitZero(table.Options, table.Value) {
+ continue
+ }
if first {
first = false
if hasNonEmptyKV {
@@ -935,6 +998,9 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
if shouldOmitEmpty(kv.Options, kv.Value) {
continue
}
+ if kv.Options.omitzero && shouldOmitZero(kv.Options, kv.Value) {
+ continue
+ }
if first {
first = false
@@ -963,11 +1029,14 @@ func willConvertToTable(ctx encoderCtx, v reflect.Value) bool {
if !v.IsValid() {
return false
}
- if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) {
+ t := v.Type()
+ if t == timeType || t.Implements(textMarshalerType) {
+ return false
+ }
+ if v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(t).Implements(textMarshalerType) {
return false
}
- t := v.Type()
switch t.Kind() {
case reflect.Map, reflect.Struct:
return !ctx.inline
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/strict.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/strict.go
index 802e7e4d150..e9a4be2c32c 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/strict.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/strict.go
@@ -1,7 +1,6 @@
package toml
import (
- "github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/internal/tracker"
"github.com/pelletier/go-toml/v2/unstable"
)
@@ -13,6 +12,9 @@ type strict struct {
key tracker.KeyTracker
missing []unstable.ParserError
+
+ // Reference to the document for computing key ranges.
+ doc []byte
}
func (s *strict) EnterTable(node *unstable.Node) {
@@ -53,7 +55,7 @@ func (s *strict) MissingTable(node *unstable.Node) {
}
s.missing = append(s.missing, unstable.ParserError{
- Highlight: keyLocation(node),
+ Highlight: s.keyLocation(node),
Message: "missing table",
Key: s.key.Key(),
})
@@ -65,8 +67,8 @@ func (s *strict) MissingField(node *unstable.Node) {
}
s.missing = append(s.missing, unstable.ParserError{
- Highlight: keyLocation(node),
- Message: "missing field",
+ Highlight: s.keyLocation(node),
+ Message: "unknown field",
Key: s.key.Key(),
})
}
@@ -88,7 +90,7 @@ func (s *strict) Error(doc []byte) error {
return err
}
-func keyLocation(node *unstable.Node) []byte {
+func (s *strict) keyLocation(node *unstable.Node) []byte {
k := node.Key()
hasOne := k.Next()
@@ -96,12 +98,17 @@ func keyLocation(node *unstable.Node) []byte {
panic("should not be called with empty key")
}
- start := k.Node().Data
- end := k.Node().Data
+ // Get the range from the first key to the last key.
+ firstRaw := k.Node().Raw
+ lastRaw := firstRaw
for k.Next() {
- end = k.Node().Data
+ lastRaw = k.Node().Raw
}
- return danger.BytesRange(start, end)
+ // Compute the slice from the document using the ranges.
+ start := firstRaw.Offset
+ end := lastRaw.Offset + lastRaw.Length
+
+ return s.doc[start:end]
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/test-go-versions.sh b/hack/tools/vendor/github.com/pelletier/go-toml/v2/test-go-versions.sh
new file mode 100644
index 00000000000..5fe5c777227
--- /dev/null
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/test-go-versions.sh
@@ -0,0 +1,597 @@
+#!/usr/bin/env bash
+
+set -uo pipefail
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Go versions to test (1.11 through 1.26)
+GO_VERSIONS=(
+ "1.11"
+ "1.12"
+ "1.13"
+ "1.14"
+ "1.15"
+ "1.16"
+ "1.17"
+ "1.18"
+ "1.19"
+ "1.20"
+ "1.21"
+ "1.22"
+ "1.23"
+ "1.24"
+ "1.25"
+ "1.26"
+)
+
+# Default values
+PARALLEL=true
+VERBOSE=false
+OUTPUT_DIR="test-results"
+DOCKER_TIMEOUT="10m"
+
+usage() {
+ cat << EOF
+Usage: $0 [OPTIONS] [GO_VERSIONS...]
+
+Test go-toml across multiple Go versions using Docker containers.
+
+The script reports the lowest continuous supported Go version (where all subsequent
+versions pass) and only exits with non-zero status if either of the two most recent
+Go versions fail, indicating immediate attention is needed.
+
+Note: For Go versions < 1.21, the script automatically updates go.mod to match the
+target version, but older versions may still fail due to missing standard library
+features (e.g., the 'slices' package introduced in Go 1.21).
+
+OPTIONS:
+ -h, --help Show this help message
+ -s, --sequential Run tests sequentially instead of in parallel
+ -v, --verbose Enable verbose output
+ -o, --output DIR Output directory for test results (default: test-results)
+ -t, --timeout TIME Docker timeout for each test (default: 10m)
+ --list List available Go versions and exit
+
+ARGUMENTS:
+ GO_VERSIONS Specific Go versions to test (default: all supported versions)
+ Examples: 1.21 1.22 1.23
+
+EXAMPLES:
+ $0 # Test all Go versions in parallel
+ $0 --sequential # Test all Go versions sequentially
+ $0 1.21 1.22 1.23 # Test specific versions
+ $0 --verbose --output ./results 1.25 1.26 # Verbose output to custom directory
+
+EXIT CODES:
+ 0 Recent Go versions pass (good compatibility)
+ 1 Recent Go versions fail (needs attention) or script error
+
+EOF
+}
+
+log() {
+ echo -e "${BLUE}[$(date +'%H:%M:%S')]${NC} $*" >&2
+}
+
+log_success() {
+ echo -e "${GREEN}[$(date +'%H:%M:%S')] ✓${NC} $*" >&2
+}
+
+log_error() {
+ echo -e "${RED}[$(date +'%H:%M:%S')] ✗${NC} $*" >&2
+}
+
+log_warning() {
+ echo -e "${YELLOW}[$(date +'%H:%M:%S')] ⚠${NC} $*" >&2
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -s|--sequential)
+ PARALLEL=false
+ shift
+ ;;
+ -v|--verbose)
+ VERBOSE=true
+ shift
+ ;;
+ -o|--output)
+ OUTPUT_DIR="$2"
+ shift 2
+ ;;
+ -t|--timeout)
+ DOCKER_TIMEOUT="$2"
+ shift 2
+ ;;
+ --list)
+ echo "Available Go versions:"
+ printf '%s\n' "${GO_VERSIONS[@]}"
+ exit 0
+ ;;
+ -*)
+ echo "Unknown option: $1" >&2
+ usage
+ exit 1
+ ;;
+ *)
+ # Remaining arguments are Go versions
+ break
+ ;;
+ esac
+done
+
+# If specific versions provided, use those instead of defaults
+if [[ $# -gt 0 ]]; then
+ GO_VERSIONS=("$@")
+fi
+
+# Validate Go versions
+for version in "${GO_VERSIONS[@]}"; do
+ if ! [[ "$version" =~ ^1\.(1[1-9]|2[0-6])$ ]]; then
+ log_error "Invalid Go version: $version. Supported versions: 1.11-1.26"
+ exit 1
+ fi
+done
+
+# Check if Docker is available
+if ! command -v docker &> /dev/null; then
+ log_error "Docker is required but not installed or not in PATH"
+ exit 1
+fi
+
+# Check if Docker daemon is running
+if ! docker info &> /dev/null; then
+ log_error "Docker daemon is not running"
+ exit 1
+fi
+
+# Create output directory
+mkdir -p "$OUTPUT_DIR"
+
+# Function to test a single Go version
+test_go_version() {
+ local go_version="$1"
+ local container_name="go-toml-test-${go_version}"
+ local result_file="${OUTPUT_DIR}/go-${go_version}.txt"
+ local dockerfile_content
+
+ log "Testing Go $go_version..."
+
+ # Create a temporary Dockerfile for this version
+ # For Go versions < 1.21, we need to update go.mod to match the Go version
+ local needs_go_mod_update=false
+ if [[ $(echo "$go_version 1.21" | tr ' ' '\n' | sort -V | head -n1) == "$go_version" && "$go_version" != "1.21" ]]; then
+ needs_go_mod_update=true
+ fi
+
+ dockerfile_content="FROM golang:${go_version}-alpine
+
+# Install git (required for go mod)
+RUN apk add --no-cache git
+
+# Set working directory
+WORKDIR /app
+
+# Copy source code
+COPY . ."
+
+ # Add go.mod update step for older Go versions
+ if [[ "$needs_go_mod_update" == true ]]; then
+ dockerfile_content="$dockerfile_content
+
+# Update go.mod to match Go version (required for Go < 1.21)
+RUN if [ -f go.mod ]; then sed -i 's/^go [0-9]\\+\\.[0-9]\\+\\(\\.[0-9]\\+\\)\\?/go $go_version/' go.mod; fi
+
+# Note: Go versions < 1.21 may fail due to missing standard library packages (e.g., slices)
+# This is expected for projects that use Go 1.21+ features"
+ fi
+
+ dockerfile_content="$dockerfile_content
+
+# Run tests
+CMD [\"sh\", \"-c\", \"go version && echo '--- Running go test ./... ---' && go test ./...\"]"
+
+ # Create temporary directory for this test
+ local temp_dir
+ temp_dir=$(mktemp -d)
+
+ # Copy source to temp directory (excluding test results and git)
+ rsync -a --exclude="$OUTPUT_DIR" --exclude=".git" --exclude="*.test" . "$temp_dir/"
+
+ # Create Dockerfile in temp directory
+ echo "$dockerfile_content" > "$temp_dir/Dockerfile"
+
+ # Build and run container
+ local exit_code=0
+ local output
+
+ if $VERBOSE; then
+ log "Building Docker image for Go $go_version..."
+ fi
+
+ # Capture both stdout and stderr, and the exit code
+ if output=$(cd "$temp_dir" && timeout "$DOCKER_TIMEOUT" docker build -t "$container_name" . 2>&1 && \
+ timeout "$DOCKER_TIMEOUT" docker run --rm "$container_name" 2>&1); then
+ log_success "Go $go_version: PASSED"
+ echo "PASSED" > "${result_file}.status"
+ else
+ exit_code=$?
+ log_error "Go $go_version: FAILED (exit code: $exit_code)"
+ echo "FAILED" > "${result_file}.status"
+ fi
+
+ # Save full output
+ echo "$output" > "$result_file"
+
+ # Clean up
+ docker rmi "$container_name" &> /dev/null || true
+ rm -rf "$temp_dir"
+
+ if $VERBOSE; then
+ echo "--- Go $go_version output ---"
+ echo "$output"
+ echo "--- End Go $go_version output ---"
+ fi
+
+ return $exit_code
+}
+
+# Function to run tests in parallel
+run_parallel() {
+ local pids=()
+ local failed_versions=()
+
+ log "Starting parallel tests for ${#GO_VERSIONS[@]} Go versions..."
+
+ # Start all tests in background
+ for version in "${GO_VERSIONS[@]}"; do
+ test_go_version "$version" &
+ pids+=($!)
+ done
+
+ # Wait for all tests to complete
+ for i in "${!pids[@]}"; do
+ local pid=${pids[$i]}
+ local version=${GO_VERSIONS[$i]}
+
+ if ! wait $pid; then
+ failed_versions+=("$version")
+ fi
+ done
+
+ return ${#failed_versions[@]}
+}
+
+# Function to run tests sequentially
+run_sequential() {
+ local failed_versions=()
+
+ log "Starting sequential tests for ${#GO_VERSIONS[@]} Go versions..."
+
+ for version in "${GO_VERSIONS[@]}"; do
+ if ! test_go_version "$version"; then
+ failed_versions+=("$version")
+ fi
+ done
+
+ return ${#failed_versions[@]}
+}
+
+# Main execution
+main() {
+ local start_time
+ start_time=$(date +%s)
+
+ log "Starting Go version compatibility tests..."
+ log "Testing versions: ${GO_VERSIONS[*]}"
+ log "Output directory: $OUTPUT_DIR"
+ log "Parallel execution: $PARALLEL"
+
+ local failed_count
+ if $PARALLEL; then
+ run_parallel
+ failed_count=$?
+ else
+ run_sequential
+ failed_count=$?
+ fi
+
+ local end_time
+ end_time=$(date +%s)
+ local duration=$((end_time - start_time))
+
+ # Collect results for display
+ local passed_versions=()
+ local failed_versions=()
+ local unknown_versions=()
+ local passed_count=0
+
+ for version in "${GO_VERSIONS[@]}"; do
+ local status_file="${OUTPUT_DIR}/go-${version}.txt.status"
+ if [[ -f "$status_file" ]]; then
+ local status
+ status=$(cat "$status_file")
+ if [[ "$status" == "PASSED" ]]; then
+ passed_versions+=("$version")
+ ((passed_count++))
+ else
+ failed_versions+=("$version")
+ fi
+ else
+ unknown_versions+=("$version")
+ fi
+ done
+
+ # Generate summary report
+ local summary_file="${OUTPUT_DIR}/summary.txt"
+ {
+ echo "Go Version Compatibility Test Summary"
+ echo "====================================="
+ echo "Date: $(date)"
+ echo "Duration: ${duration}s"
+ echo "Parallel: $PARALLEL"
+ echo ""
+ echo "Results:"
+
+ for version in "${GO_VERSIONS[@]}"; do
+ local status_file="${OUTPUT_DIR}/go-${version}.txt.status"
+ if [[ -f "$status_file" ]]; then
+ local status
+ status=$(cat "$status_file")
+ if [[ "$status" == "PASSED" ]]; then
+ echo " Go $version: ✓ PASSED"
+ else
+ echo " Go $version: ✗ FAILED"
+ fi
+ else
+ echo " Go $version: ? UNKNOWN (no status file)"
+ fi
+ done
+
+ echo ""
+ echo "Summary: $passed_count/${#GO_VERSIONS[@]} versions passed"
+
+ if [[ $failed_count -gt 0 ]]; then
+ echo ""
+ echo "Failed versions details:"
+ for version in "${failed_versions[@]}"; do
+ echo ""
+ echo "--- Go $version (FAILED) ---"
+ local result_file="${OUTPUT_DIR}/go-${version}.txt"
+ if [[ -f "$result_file" ]]; then
+ tail -n 30 "$result_file"
+ fi
+ done
+ fi
+ } > "$summary_file"
+
+ # Find lowest continuous supported version and check recent versions
+ local lowest_continuous_version=""
+ local recent_versions_failed=false
+
+ # Sort versions to ensure proper order
+ local sorted_versions=()
+ for version in "${GO_VERSIONS[@]}"; do
+ sorted_versions+=("$version")
+ done
+ # Sort versions numerically (1.11, 1.12, ..., 1.25)
+ IFS=$'\n' sorted_versions=($(sort -V <<< "${sorted_versions[*]}"))
+
+ # Find lowest continuous supported version (all versions from this point onwards pass)
+ for version in "${sorted_versions[@]}"; do
+ local status_file="${OUTPUT_DIR}/go-${version}.txt.status"
+ local all_subsequent_pass=true
+
+ # Check if this version and all subsequent versions pass
+ local found_current=false
+ for check_version in "${sorted_versions[@]}"; do
+ if [[ "$check_version" == "$version" ]]; then
+ found_current=true
+ fi
+
+ if [[ "$found_current" == true ]]; then
+ local check_status_file="${OUTPUT_DIR}/go-${check_version}.txt.status"
+ if [[ -f "$check_status_file" ]]; then
+ local status
+ status=$(cat "$check_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ all_subsequent_pass=false
+ break
+ fi
+ else
+ all_subsequent_pass=false
+ break
+ fi
+ fi
+ done
+
+ if [[ "$all_subsequent_pass" == true ]]; then
+ lowest_continuous_version="$version"
+ break
+ fi
+ done
+
+ # Check if the two most recent versions failed
+ local num_versions=${#sorted_versions[@]}
+ if [[ $num_versions -ge 2 ]]; then
+ local second_recent="${sorted_versions[$((num_versions-2))]}"
+ local most_recent="${sorted_versions[$((num_versions-1))]}"
+
+ local second_recent_status_file="${OUTPUT_DIR}/go-${second_recent}.txt.status"
+ local most_recent_status_file="${OUTPUT_DIR}/go-${most_recent}.txt.status"
+
+ local second_recent_failed=false
+ local most_recent_failed=false
+
+ if [[ -f "$second_recent_status_file" ]]; then
+ local status
+ status=$(cat "$second_recent_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ second_recent_failed=true
+ fi
+ else
+ second_recent_failed=true
+ fi
+
+ if [[ -f "$most_recent_status_file" ]]; then
+ local status
+ status=$(cat "$most_recent_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ most_recent_failed=true
+ fi
+ else
+ most_recent_failed=true
+ fi
+
+ if [[ "$second_recent_failed" == true || "$most_recent_failed" == true ]]; then
+ recent_versions_failed=true
+ fi
+ elif [[ $num_versions -eq 1 ]]; then
+ # Only one version tested, check if it's the most recent and failed
+ local only_version="${sorted_versions[0]}"
+ local only_status_file="${OUTPUT_DIR}/go-${only_version}.txt.status"
+
+ if [[ -f "$only_status_file" ]]; then
+ local status
+ status=$(cat "$only_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ recent_versions_failed=true
+ fi
+ else
+ recent_versions_failed=true
+ fi
+ fi
+
+ # Display summary
+ echo ""
+ log "Test completed in ${duration}s"
+ log "Summary report: $summary_file"
+
+ echo ""
+ echo "========================================"
+ echo " FINAL RESULTS"
+ echo "========================================"
+ echo ""
+
+ # Display passed versions
+ if [[ ${#passed_versions[@]} -gt 0 ]]; then
+ log_success "PASSED (${#passed_versions[@]}/${#GO_VERSIONS[@]}):"
+ # Sort passed versions for display
+ local sorted_passed=()
+ for version in "${sorted_versions[@]}"; do
+ for passed_version in "${passed_versions[@]}"; do
+ if [[ "$version" == "$passed_version" ]]; then
+ sorted_passed+=("$version")
+ break
+ fi
+ done
+ done
+ for version in "${sorted_passed[@]}"; do
+ echo -e " ${GREEN}✓${NC} Go $version"
+ done
+ echo ""
+ fi
+
+ # Display failed versions
+ if [[ ${#failed_versions[@]} -gt 0 ]]; then
+ log_error "FAILED (${#failed_versions[@]}/${#GO_VERSIONS[@]}):"
+ # Sort failed versions for display
+ local sorted_failed=()
+ for version in "${sorted_versions[@]}"; do
+ for failed_version in "${failed_versions[@]}"; do
+ if [[ "$version" == "$failed_version" ]]; then
+ sorted_failed+=("$version")
+ break
+ fi
+ done
+ done
+ for version in "${sorted_failed[@]}"; do
+ echo -e " ${RED}✗${NC} Go $version"
+ done
+ echo ""
+
+ # Show failure details
+ echo "========================================"
+ echo " FAILURE DETAILS"
+ echo "========================================"
+ echo ""
+
+ for version in "${sorted_failed[@]}"; do
+ echo -e "${RED}--- Go $version FAILURE LOGS (last 30 lines) ---${NC}"
+ local result_file="${OUTPUT_DIR}/go-${version}.txt"
+ if [[ -f "$result_file" ]]; then
+ tail -n 30 "$result_file" | sed 's/^/ /'
+ else
+ echo " No log file found: $result_file"
+ fi
+ echo ""
+ done
+ fi
+
+ # Display unknown versions
+ if [[ ${#unknown_versions[@]} -gt 0 ]]; then
+ log_warning "UNKNOWN (${#unknown_versions[@]}/${#GO_VERSIONS[@]}):"
+ for version in "${unknown_versions[@]}"; do
+ echo -e " ${YELLOW}?${NC} Go $version (no status file)"
+ done
+ echo ""
+ fi
+
+ echo "========================================"
+ echo " COMPATIBILITY SUMMARY"
+ echo "========================================"
+ echo ""
+
+ if [[ -n "$lowest_continuous_version" ]]; then
+ log_success "Lowest continuous supported version: Go $lowest_continuous_version"
+ echo " (All versions from Go $lowest_continuous_version onwards pass)"
+ else
+ log_error "No continuous version support found"
+ echo " (No version has all subsequent versions passing)"
+ fi
+
+ echo ""
+ echo "========================================"
+ echo "Full detailed logs available in: $OUTPUT_DIR"
+ echo "========================================"
+
+ # Determine exit code based on recent versions
+ if [[ "$recent_versions_failed" == true ]]; then
+ log_error "OVERALL RESULT: Recent Go versions failed - this needs attention!"
+ if [[ -n "$lowest_continuous_version" ]]; then
+ echo "Note: Continuous support starts from Go $lowest_continuous_version"
+ fi
+ exit 1
+ else
+ log_success "OVERALL RESULT: Recent Go versions pass - compatibility looks good!"
+ if [[ -n "$lowest_continuous_version" ]]; then
+ echo "Continuous support starts from Go $lowest_continuous_version"
+ fi
+ exit 0
+ fi
+}
+
+# Trap to clean up on exit
+cleanup() {
+ # Kill any remaining background processes
+ jobs -p | xargs -r kill 2>/dev/null || true
+
+ # Clean up any remaining Docker containers
+ docker ps -q --filter "name=go-toml-test-" | xargs -r docker stop 2>/dev/null || true
+ docker images -q --filter "reference=go-toml-test-*" | xargs -r docker rmi 2>/dev/null || true
+}
+
+trap cleanup EXIT
+
+# Run main function
+main
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/types.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/types.go
index 3c6b8fe5702..6d12fe5802c 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/types.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/types.go
@@ -6,9 +6,18 @@ import (
"time"
)
-var timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
-var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
-var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
-var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil))
-var sliceInterfaceType = reflect.TypeOf([]interface{}(nil))
-var stringType = reflect.TypeOf("")
+// isZeroer is used to check if a type has a custom IsZero method.
+// This allows custom types to define their own zero-value semantics.
+type isZeroer interface {
+ IsZero() bool
+}
+
+var (
+ timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
+ textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+ textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+ isZeroerType = reflect.TypeOf((*isZeroer)(nil)).Elem()
+ mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil))
+ sliceInterfaceType = reflect.TypeOf([]interface{}(nil))
+ stringType = reflect.TypeOf("")
+)
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
index 189be525e1f..e7db8128ceb 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
@@ -12,7 +12,6 @@ import (
"sync/atomic"
"time"
- "github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/internal/tracker"
"github.com/pelletier/go-toml/v2/unstable"
)
@@ -57,13 +56,18 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
// EnableUnmarshalerInterface allows to enable unmarshaler interface.
//
-// With this feature enabled, types implementing the unstable/Unmarshaler
+// With this feature enabled, types implementing the unstable.Unmarshaler
// interface can be decoded from any structure of the document. It allows types
// that don't have a straightforward TOML representation to provide their own
// decoding logic.
//
-// Currently, types can only decode from a single value. Tables and array tables
-// are not supported.
+// The UnmarshalTOML method receives raw TOML bytes:
+// - For single values: the raw value bytes (e.g., `"hello"` for a string)
+// - For tables: all key-value lines belonging to that table
+// - For inline tables/arrays: the raw bytes of the inline structure
+//
+// The unstable.RawMessage type can be used to capture raw TOML bytes for
+// later processing, similar to json.RawMessage.
//
// *Unstable:* This method does not follow the compatibility guarantees of
// semver. It can be changed or removed without a new major version being
@@ -123,6 +127,7 @@ func (d *Decoder) Decode(v interface{}) error {
dec := decoder{
strict: strict{
Enabled: d.strict,
+ doc: b,
},
unmarshalerInterface: d.unmarshalerInterface,
}
@@ -226,7 +231,7 @@ func (d *decoder) FromParser(v interface{}) error {
}
if r.IsNil() {
- return fmt.Errorf("toml: decoding pointer target cannot be nil")
+ return errors.New("toml: decoding pointer target cannot be nil")
}
r = r.Elem()
@@ -273,7 +278,7 @@ func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) err
var err error
var first bool // used for to clear array tables on first use
- if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
+ if !d.skipUntilTable || expr.Kind != unstable.KeyValue {
first, err = d.seen.CheckExpression(expr)
if err != nil {
return err
@@ -378,7 +383,7 @@ func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflec
case reflect.Array:
idx := d.arrayIndex(true, v)
if idx >= v.Len() {
- return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
+ return v, fmt.Errorf("%w at position %d", d.typeMismatchError("array table", v.Type()), idx)
}
elem := v.Index(idx)
_, err := d.handleArrayTable(key, elem)
@@ -416,27 +421,51 @@ func (d *decoder) handleArrayTableCollection(key unstable.Iterator, v reflect.Va
return v, nil
case reflect.Slice:
- elem := v.Index(v.Len() - 1)
+ // Create a new element when the slice is empty; otherwise operate on
+ // the last element.
+ var (
+ elem reflect.Value
+ created bool
+ )
+ if v.Len() == 0 {
+ created = true
+ elemType := v.Type().Elem()
+ if elemType.Kind() == reflect.Interface {
+ elem = makeMapStringInterface()
+ } else {
+ elem = reflect.New(elemType).Elem()
+ }
+ } else {
+ elem = v.Index(v.Len() - 1)
+ }
+
x, err := d.handleArrayTable(key, elem)
if err != nil || d.skipUntilTable {
return reflect.Value{}, err
}
if x.IsValid() {
- elem.Set(x)
+ if created {
+ elem = x
+ } else {
+ elem.Set(x)
+ }
}
+ if created {
+ return reflect.Append(v, elem), nil
+ }
return v, err
case reflect.Array:
idx := d.arrayIndex(false, v)
if idx >= v.Len() {
- return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
+ return v, fmt.Errorf("%w at position %d", d.typeMismatchError("array table", v.Type()), idx)
}
elem := v.Index(idx)
_, err := d.handleArrayTable(key, elem)
return v, err
+ default:
+ return d.handleArrayTable(key, v)
}
-
- return d.handleArrayTable(key, v)
}
func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
@@ -470,7 +499,8 @@ func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn h
mv := v.MapIndex(mk)
set := false
- if !mv.IsValid() {
+ switch {
+ case !mv.IsValid():
// If there is no value in the map, create a new one according to
// the map type. If the element type is interface, create either a
// map[string]interface{} or a []interface{} depending on whether
@@ -483,13 +513,13 @@ func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn h
mv = reflect.New(t).Elem()
}
set = true
- } else if mv.Kind() == reflect.Interface {
+ case mv.Kind() == reflect.Interface:
mv = mv.Elem()
if !mv.IsValid() {
mv = makeFn()
}
set = true
- } else if !mv.CanAddr() {
+ case !mv.CanAddr():
vt := v.Type()
t := vt.Elem()
oldmv := mv
@@ -574,18 +604,28 @@ func (d *decoder) handleArrayTablePart(key unstable.Iterator, v reflect.Value) (
// cannot handle it.
func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
if v.Kind() == reflect.Slice {
- if v.Len() == 0 {
- return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice")
- }
- elem := v.Index(v.Len() - 1)
- x, err := d.handleTable(key, elem)
- if err != nil {
- return reflect.Value{}, err
+ // For non-empty slices, work with the last element
+ if v.Len() > 0 {
+ elem := v.Index(v.Len() - 1)
+ x, err := d.handleTable(key, elem)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if x.IsValid() {
+ elem.Set(x)
+ }
+ return reflect.Value{}, nil
}
- if x.IsValid() {
- elem.Set(x)
+ // Empty slice - check if it implements Unmarshaler (e.g., RawMessage)
+ // and we're at the end of the key path
+ if d.unmarshalerInterface && !key.Next() {
+ if v.CanAddr() && v.Addr().CanInterface() {
+ if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
+ return d.handleKeyValuesUnmarshaler(outi)
+ }
+ }
}
- return reflect.Value{}, nil
+ return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice")
}
if key.Next() {
// Still scoping the key
@@ -599,6 +639,24 @@ func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.V
// Handle root expressions until the end of the document or the next
// non-key-value.
func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
+ // Check if target implements Unmarshaler before processing key-values.
+ // This allows types to handle entire tables themselves.
+ if d.unmarshalerInterface {
+ vv := v
+ for vv.Kind() == reflect.Ptr {
+ if vv.IsNil() {
+ vv.Set(reflect.New(vv.Type().Elem()))
+ }
+ vv = vv.Elem()
+ }
+ if vv.CanAddr() && vv.Addr().CanInterface() {
+ if outi, ok := vv.Addr().Interface().(unstable.Unmarshaler); ok {
+ // Collect all key-value expressions for this table
+ return d.handleKeyValuesUnmarshaler(outi)
+ }
+ }
+ }
+
var rv reflect.Value
for d.nextExpr() {
expr := d.expr()
@@ -628,6 +686,41 @@ func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
return rv, nil
}
+// handleKeyValuesUnmarshaler collects all key-value expressions for a table
+// and passes them to the Unmarshaler as raw TOML bytes.
+func (d *decoder) handleKeyValuesUnmarshaler(u unstable.Unmarshaler) (reflect.Value, error) {
+ // Collect raw bytes from all key-value expressions for this table.
+ // We use the Raw field on each KeyValue expression to preserve the
+ // original formatting (whitespace, quoting style, etc.) from the document.
+ var buf []byte
+
+ for d.nextExpr() {
+ expr := d.expr()
+ if expr.Kind != unstable.KeyValue {
+ d.stashExpr()
+ break
+ }
+
+ _, err := d.seen.CheckExpression(expr)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+
+ // Use the raw bytes from the original document to preserve formatting
+ if expr.Raw.Length > 0 {
+ raw := d.p.Raw(expr.Raw)
+ buf = append(buf, raw...)
+ }
+ buf = append(buf, '\n')
+ }
+
+ if err := u.UnmarshalTOML(buf); err != nil {
+ return reflect.Value{}, err
+ }
+
+ return reflect.Value{}, nil
+}
+
type (
handlerFn func(key unstable.Iterator, v reflect.Value) (reflect.Value, error)
valueMakerFn func() reflect.Value
@@ -672,14 +765,21 @@ func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {
if d.unmarshalerInterface {
if v.CanAddr() && v.Addr().CanInterface() {
if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
- return outi.UnmarshalTOML(value)
+ // Pass raw bytes from the original document
+ return outi.UnmarshalTOML(d.p.Raw(value.Raw))
}
}
}
- ok, err := d.tryTextUnmarshaler(value, v)
- if ok || err != nil {
- return err
+ // Only try TextUnmarshaler for scalar types. For Array and InlineTable,
+ // fall through to struct/map unmarshaling to allow flexible unmarshaling
+ // where a type can implement UnmarshalText for string values but still
+ // be populated field-by-field from a table. See issue #974.
+ if value.Kind != unstable.Array && value.Kind != unstable.InlineTable {
+ ok, err := d.tryTextUnmarshaler(value, v)
+ if ok || err != nil {
+ return err
+ }
}
switch value.Kind {
@@ -821,6 +921,9 @@ func (d *decoder) unmarshalDateTime(value *unstable.Node, v reflect.Value) error
return err
}
+ if v.Kind() != reflect.Interface && v.Type() != timeType {
+ return unstable.NewParserError(d.p.Raw(value.Raw), "%s", d.typeMismatchString("datetime", v.Type()))
+ }
v.Set(reflect.ValueOf(dt))
return nil
}
@@ -831,14 +934,14 @@ func (d *decoder) unmarshalLocalDate(value *unstable.Node, v reflect.Value) erro
return err
}
+ if v.Kind() != reflect.Interface && v.Type() != timeType {
+ return unstable.NewParserError(d.p.Raw(value.Raw), "%s", d.typeMismatchString("local date", v.Type()))
+ }
if v.Type() == timeType {
- cast := ld.AsTime(time.Local)
- v.Set(reflect.ValueOf(cast))
+ v.Set(reflect.ValueOf(ld.AsTime(time.Local)))
return nil
}
-
v.Set(reflect.ValueOf(ld))
-
return nil
}
@@ -852,6 +955,9 @@ func (d *decoder) unmarshalLocalTime(value *unstable.Node, v reflect.Value) erro
return unstable.NewParserError(rest, "extra characters at the end of a local time")
}
+ if v.Kind() != reflect.Interface {
+ return unstable.NewParserError(d.p.Raw(value.Raw), "%s", d.typeMismatchString("local time", v.Type()))
+ }
v.Set(reflect.ValueOf(lt))
return nil
}
@@ -866,15 +972,14 @@ func (d *decoder) unmarshalLocalDateTime(value *unstable.Node, v reflect.Value)
return unstable.NewParserError(rest, "extra characters at the end of a local date time")
}
+ if v.Kind() != reflect.Interface && v.Type() != timeType {
+ return unstable.NewParserError(d.p.Raw(value.Raw), "%s", d.typeMismatchString("local datetime", v.Type()))
+ }
if v.Type() == timeType {
- cast := ldt.AsTime(time.Local)
-
- v.Set(reflect.ValueOf(cast))
+ v.Set(reflect.ValueOf(ldt.AsTime(time.Local)))
return nil
}
-
v.Set(reflect.ValueOf(ldt))
-
return nil
}
@@ -929,8 +1034,9 @@ const (
// compile time, so it is computed during initialization.
var maxUint int64 = math.MaxInt64
-func init() {
+func init() { //nolint:gochecknoinits
m := uint64(^uint(0))
+ // #nosec G115
if m < uint64(maxUint) {
maxUint = int64(m)
}
@@ -1010,7 +1116,7 @@ func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error
case reflect.Interface:
r = reflect.ValueOf(i)
default:
- return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("integer", v.Type()))
+ return unstable.NewParserError(d.p.Raw(value.Raw), "%s", d.typeMismatchString("integer", v.Type()))
}
if !r.Type().AssignableTo(v.Type()) {
@@ -1029,7 +1135,7 @@ func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {
case reflect.Interface:
v.Set(reflect.ValueOf(string(value.Data)))
default:
- return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("string", v.Type()))
+ return unstable.NewParserError(d.p.Raw(value.Raw), "%s", d.typeMismatchString("string", v.Type()))
}
return nil
@@ -1080,35 +1186,39 @@ func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value,
return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
}
return mk.Elem(), nil
+ }
- case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:
+ switch keyType.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
key, err := strconv.ParseInt(string(data), 10, 64)
if err != nil {
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err)
}
return reflect.ValueOf(key).Convert(keyType), nil
- case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
key, err := strconv.ParseUint(string(data), 10, 64)
if err != nil {
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err)
}
return reflect.ValueOf(key).Convert(keyType), nil
- case keyType.Kind() == reflect.Float32:
+ case reflect.Float32:
key, err := strconv.ParseFloat(string(data), 32)
if err != nil {
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)
}
return reflect.ValueOf(float32(key)), nil
- case keyType.Kind() == reflect.Float64:
+ case reflect.Float64:
key, err := strconv.ParseFloat(string(data), 64)
if err != nil {
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)
}
return reflect.ValueOf(float64(key)), nil
+
+ default:
+ return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)
}
- return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)
}
func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
@@ -1154,6 +1264,18 @@ func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node
case reflect.Struct:
path, found := structFieldPath(v, string(key.Node().Data))
if !found {
+ // If no matching struct field is found but the target implements the
+ // unstable.Unmarshaler interface (and it is enabled), delegate the
+ // decoding of this value to the custom unmarshaler.
+ if d.unmarshalerInterface {
+ if v.CanAddr() && v.Addr().CanInterface() {
+ if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
+ // Pass raw bytes from the original document
+ return reflect.Value{}, outi.UnmarshalTOML(d.p.Raw(value.Raw))
+ }
+ }
+ }
+ // Otherwise, keep previous behavior and skip until the next table.
d.skipUntilTable = true
break
}
@@ -1259,13 +1381,13 @@ func fieldByIndex(v reflect.Value, path []int) reflect.Value {
type fieldPathsMap = map[string][]int
-var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
+var globalFieldPathsCache atomic.Value // map[reflect.Type]fieldPathsMap
func structFieldPath(v reflect.Value, name string) ([]int, bool) {
t := v.Type()
- cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap)
- fieldPaths, ok := cache[danger.MakeTypeID(t)]
+ cache, _ := globalFieldPathsCache.Load().(map[reflect.Type]fieldPathsMap)
+ fieldPaths, ok := cache[t]
if !ok {
fieldPaths = map[string][]int{}
@@ -1276,8 +1398,8 @@ func structFieldPath(v reflect.Value, name string) ([]int, bool) {
fieldPaths[strings.ToLower(name)] = path
})
- newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1)
- newCache[danger.MakeTypeID(t)] = fieldPaths
+ newCache := make(map[reflect.Type]fieldPathsMap, len(cache)+1)
+ newCache[t] = fieldPaths
for k, v := range cache {
newCache[k] = v
}
@@ -1301,7 +1423,9 @@ func forEachField(t reflect.Type, path []int, do func(name string, path []int))
continue
}
- fieldPath := append(path, i)
+ fieldPath := make([]int, 0, len(path)+1)
+ fieldPath = append(fieldPath, path...)
+ fieldPath = append(fieldPath, i)
fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]
name := f.Tag.Get("toml")
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
index f526bf2c090..6b21592d6e6 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
@@ -1,10 +1,8 @@
package unstable
import (
+ "errors"
"fmt"
- "unsafe"
-
- "github.com/pelletier/go-toml/v2/internal/danger"
)
// Iterator over a sequence of nodes.
@@ -19,30 +17,43 @@ import (
// // do something with n
// }
type Iterator struct {
+ nodes *[]Node
+ idx int32
started bool
- node *Node
}
// Next moves the iterator forward and returns true if points to a
// node, false otherwise.
func (c *Iterator) Next() bool {
+ if c.nodes == nil {
+ return false
+ }
+ nodes := *c.nodes
if !c.started {
c.started = true
- } else if c.node.Valid() {
- c.node = c.node.Next()
+ } else {
+ idx := c.idx
+ if idx >= 0 && int(idx) < len(nodes) {
+ c.idx = nodes[idx].next
+ }
}
- return c.node.Valid()
+ return c.idx >= 0 && int(c.idx) < len(nodes)
}
// IsLast returns true if the current node of the iterator is the last
// one. Subsequent calls to Next() will return false.
func (c *Iterator) IsLast() bool {
- return c.node.next == 0
+ return c.nodes == nil || c.idx < 0 || (*c.nodes)[c.idx].next < 0
}
// Node returns a pointer to the node pointed at by the iterator.
func (c *Iterator) Node() *Node {
- return c.node
+ if c.nodes == nil || c.idx < 0 {
+ return nil
+ }
+ n := &(*c.nodes)[c.idx]
+ n.nodes = c.nodes
+ return n
}
// Node in a TOML expression AST.
@@ -65,11 +76,12 @@ type Node struct {
Raw Range // Raw bytes from the input.
Data []byte // Node value (either allocated or referencing the input).
- // References to other nodes, as offsets in the backing array
- // from this node. References can go backward, so those can be
- // negative.
- next int // 0 if last element
- child int // 0 if no child
+ // Absolute indices into the backing nodes slice. -1 means none.
+ next int32
+ child int32
+
+ // Reference to the backing nodes slice for navigation.
+ nodes *[]Node
}
// Range of bytes in the document.
@@ -80,24 +92,24 @@ type Range struct {
// Next returns a pointer to the next node, or nil if there is no next node.
func (n *Node) Next() *Node {
- if n.next == 0 {
+ if n.next < 0 {
return nil
}
- ptr := unsafe.Pointer(n)
- size := unsafe.Sizeof(Node{})
- return (*Node)(danger.Stride(ptr, size, n.next))
+ next := &(*n.nodes)[n.next]
+ next.nodes = n.nodes
+ return next
}
// Child returns a pointer to the first child node of this node. Other children
-// can be accessed calling Next on the first child. Returns an nil if this Node
+// can be accessed calling Next on the first child. Returns nil if this Node
// has no child.
func (n *Node) Child() *Node {
- if n.child == 0 {
+ if n.child < 0 {
return nil
}
- ptr := unsafe.Pointer(n)
- size := unsafe.Sizeof(Node{})
- return (*Node)(danger.Stride(ptr, size, n.child))
+ child := &(*n.nodes)[n.child]
+ child.nodes = n.nodes
+ return child
}
// Valid returns true if the node's kind is set (not to Invalid).
@@ -111,13 +123,14 @@ func (n *Node) Valid() bool {
func (n *Node) Key() Iterator {
switch n.Kind {
case KeyValue:
- value := n.Child()
- if !value.Valid() {
- panic(fmt.Errorf("KeyValue should have at least two children"))
+ child := n.child
+ if child < 0 {
+ panic(errors.New("KeyValue should have at least two children"))
}
- return Iterator{node: value.Next()}
+ valueNode := &(*n.nodes)[child]
+ return Iterator{nodes: n.nodes, idx: valueNode.next}
case Table, ArrayTable:
- return Iterator{node: n.Child()}
+ return Iterator{nodes: n.nodes, idx: n.child}
default:
panic(fmt.Errorf("Key() is not supported on a %s", n.Kind))
}
@@ -132,5 +145,5 @@ func (n *Node) Value() *Node {
// Children returns an iterator over a node's children.
func (n *Node) Children() Iterator {
- return Iterator{node: n.Child()}
+ return Iterator{nodes: n.nodes, idx: n.child}
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
index 9538e30df93..e4354985be2 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
@@ -7,15 +7,6 @@ type root struct {
nodes []Node
}
-// Iterator over the top level nodes.
-func (r *root) Iterator() Iterator {
- it := Iterator{}
- if len(r.nodes) > 0 {
- it.node = &r.nodes[0]
- }
- return it
-}
-
func (r *root) at(idx reference) *Node {
return &r.nodes[idx]
}
@@ -33,12 +24,10 @@ type builder struct {
lastIdx int
}
-func (b *builder) Tree() *root {
- return &b.tree
-}
-
func (b *builder) NodeAt(ref reference) *Node {
- return b.tree.at(ref)
+ n := b.tree.at(ref)
+ n.nodes = &b.tree.nodes
+ return n
}
func (b *builder) Reset() {
@@ -48,24 +37,28 @@ func (b *builder) Reset() {
func (b *builder) Push(n Node) reference {
b.lastIdx = len(b.tree.nodes)
+ n.next = -1
+ n.child = -1
b.tree.nodes = append(b.tree.nodes, n)
return reference(b.lastIdx)
}
func (b *builder) PushAndChain(n Node) reference {
newIdx := len(b.tree.nodes)
+ n.next = -1
+ n.child = -1
b.tree.nodes = append(b.tree.nodes, n)
if b.lastIdx >= 0 {
- b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx
+ b.tree.nodes[b.lastIdx].next = int32(newIdx) //nolint:gosec // TOML ASTs are small
}
b.lastIdx = newIdx
return reference(b.lastIdx)
}
func (b *builder) AttachChild(parent reference, child reference) {
- b.tree.nodes[parent].child = int(child) - int(parent)
+ b.tree.nodes[parent].child = int32(child) //nolint:gosec // TOML ASTs are small
}
func (b *builder) Chain(from reference, to reference) {
- b.tree.nodes[from].next = int(to) - int(from)
+ b.tree.nodes[from].next = int32(to) //nolint:gosec // TOML ASTs are small
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
index ff9df1bef84..f87a95a78d6 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
@@ -6,28 +6,40 @@ import "fmt"
type Kind int
const (
- // Meta
+ // Invalid represents an invalid meta node.
Invalid Kind = iota
+ // Comment represents a comment meta node.
Comment
+ // Key represents a key meta node.
Key
- // Top level structures
+ // Table represents a top-level table.
Table
+ // ArrayTable represents a top-level array table.
ArrayTable
+ // KeyValue represents a top-level key value.
KeyValue
- // Containers values
+ // Array represents an array container value.
Array
+ // InlineTable represents an inline table container value.
InlineTable
- // Values
+ // String represents a string value.
String
+ // Bool represents a boolean value.
Bool
+ // Float represents a floating point value.
Float
+ // Integer represents an integer value.
Integer
+ // LocalDate represents a a local date value.
LocalDate
+ // LocalTime represents a local time value.
LocalTime
+ // LocalDateTime represents a local date/time value.
LocalDateTime
+ // DateTime represents a data/time value.
DateTime
)
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
index 50358a44ffd..15383012364 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
@@ -3,10 +3,10 @@ package unstable
import (
"bytes"
"fmt"
+ "reflect"
"unicode"
"github.com/pelletier/go-toml/v2/internal/characters"
- "github.com/pelletier/go-toml/v2/internal/danger"
)
// ParserError describes an error relative to the content of the document.
@@ -70,11 +70,34 @@ func (p *Parser) Data() []byte {
// panics.
func (p *Parser) Range(b []byte) Range {
return Range{
- Offset: uint32(danger.SubsliceOffset(p.data, b)),
- Length: uint32(len(b)),
+ Offset: uint32(p.subsliceOffset(b)), //nolint:gosec // TOML documents are small
+ Length: uint32(len(b)), //nolint:gosec // TOML documents are small
}
}
+// rangeOfToken computes the Range of a token given the remaining bytes after the token.
+// This is used when the token was extracted from the beginning of some position,
+// and 'rest' is what remains after the token.
+func (p *Parser) rangeOfToken(token, rest []byte) Range {
+ offset := len(p.data) - len(token) - len(rest)
+ return Range{Offset: uint32(offset), Length: uint32(len(token))} //nolint:gosec // TOML documents are small
+}
+
+// subsliceOffset returns the byte offset of subslice b within p.data.
+// b must share the same backing array as p.data.
+func (p *Parser) subsliceOffset(b []byte) int {
+ if len(b) == 0 {
+ return len(p.data)
+ }
+ dataPtr := reflect.ValueOf(p.data).Pointer()
+ subPtr := reflect.ValueOf(b).Pointer()
+ offset := int(subPtr - dataPtr)
+ if offset < 0 || offset > len(p.data) {
+ panic("subslice is not within data")
+ }
+ return offset
+}
+
// Raw returns the slice corresponding to the bytes in the given range.
func (p *Parser) Raw(raw Range) []byte {
return p.data[raw.Offset : raw.Offset+raw.Length]
@@ -158,9 +181,17 @@ type Shape struct {
End Position
}
-func (p *Parser) position(b []byte) Position {
- offset := danger.SubsliceOffset(p.data, b)
+// Shape returns the shape of the given range in the input. Will
+// panic if the range is not a subslice of the input.
+func (p *Parser) Shape(r Range) Shape {
+ return Shape{
+ Start: p.positionAt(int(r.Offset)),
+ End: p.positionAt(int(r.Offset + r.Length)),
+ }
+}
+// positionAt returns the position at the given byte offset in the document.
+func (p *Parser) positionAt(offset int) Position {
lead := p.data[:offset]
return Position{
@@ -170,16 +201,6 @@ func (p *Parser) position(b []byte) Position {
}
}
-// Shape returns the shape of the given range in the input. Will
-// panic if the range is not a subslice of the input.
-func (p *Parser) Shape(r Range) Shape {
- raw := p.Raw(r)
- return Shape{
- Start: p.position(raw),
- End: p.position(raw[r.Length:]),
- }
-}
-
func (p *Parser) parseNewline(b []byte) ([]byte, error) {
if b[0] == '\n' {
return b[1:], nil
@@ -199,7 +220,7 @@ func (p *Parser) parseComment(b []byte) (reference, []byte, error) {
if p.KeepComments && err == nil {
ref = p.builder.Push(Node{
Kind: Comment,
- Raw: p.Range(data),
+ Raw: p.rangeOfToken(data, rest),
Data: data,
})
}
@@ -316,6 +337,9 @@ func (p *Parser) parseStdTable(b []byte) (reference, []byte, error) {
func (p *Parser) parseKeyval(b []byte) (reference, []byte, error) {
// keyval = key keyval-sep val
+ // Track the start position for Raw range
+ startB := b
+
ref := p.builder.Push(Node{
Kind: KeyValue,
})
@@ -330,7 +354,7 @@ func (p *Parser) parseKeyval(b []byte) (reference, []byte, error) {
b = p.parseWhitespace(b)
if len(b) == 0 {
- return invalidReference, nil, NewParserError(b, "expected = after a key, but the document ends there")
+ return invalidReference, nil, NewParserError(startB[:len(startB)-len(b)], "expected = after a key, but the document ends there")
}
b, err = expect('=', b)
@@ -348,6 +372,11 @@ func (p *Parser) parseKeyval(b []byte) (reference, []byte, error) {
p.builder.Chain(valRef, key)
p.builder.AttachChild(ref, valRef)
+ // Set Raw to span the entire key-value expression.
+ // Access the node directly in the slice to avoid the write barrier
+ // that NodeAt's nodes-pointer setup would trigger.
+ p.builder.tree.nodes[ref].Raw = p.rangeOfToken(startB[:len(startB)-len(b)], b)
+
return ref, b, err
}
@@ -376,7 +405,7 @@ func (p *Parser) parseVal(b []byte) (reference, []byte, error) {
if err == nil {
ref = p.builder.Push(Node{
Kind: String,
- Raw: p.Range(raw),
+ Raw: p.rangeOfToken(raw, b),
Data: v,
})
}
@@ -394,7 +423,7 @@ func (p *Parser) parseVal(b []byte) (reference, []byte, error) {
if err == nil {
ref = p.builder.Push(Node{
Kind: String,
- Raw: p.Range(raw),
+ Raw: p.rangeOfToken(raw, b),
Data: v,
})
}
@@ -456,7 +485,7 @@ func (p *Parser) parseInlineTable(b []byte) (reference, []byte, error) {
// inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ]
parent := p.builder.Push(Node{
Kind: InlineTable,
- Raw: p.Range(b[:1]),
+ Raw: p.rangeOfToken(b[:1], b[1:]),
})
first := true
@@ -542,7 +571,7 @@ func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
var err error
for len(b) > 0 {
- cref := invalidReference
+ var cref reference
cref, b, err = p.parseOptionalWhitespaceCommentNewline(b)
if err != nil {
return parent, nil, err
@@ -611,12 +640,13 @@ func (p *Parser) parseOptionalWhitespaceCommentNewline(b []byte) (reference, []b
latestCommentRef := invalidReference
addComment := func(ref reference) {
- if rootCommentRef == invalidReference {
+ switch {
+ case rootCommentRef == invalidReference:
rootCommentRef = ref
- } else if latestCommentRef == invalidReference {
+ case latestCommentRef == invalidReference:
p.builder.AttachChild(rootCommentRef, ref)
latestCommentRef = ref
- } else {
+ default:
p.builder.Chain(latestCommentRef, ref)
latestCommentRef = ref
}
@@ -704,11 +734,11 @@ func (p *Parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, er
if !escaped {
str := token[startIdx:endIdx]
- verr := characters.Utf8TomlValidAlreadyEscaped(str)
- if verr.Zero() {
+ highlight := characters.Utf8TomlValidAlreadyEscaped(str)
+ if len(highlight) == 0 {
return token, str, rest, nil
}
- return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
+ return nil, nil, nil, NewParserError(highlight, "invalid UTF-8")
}
var builder bytes.Buffer
@@ -744,7 +774,7 @@ func (p *Parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, er
i += j
for ; i < len(token)-3; i++ {
c := token[i]
- if !(c == '\n' || c == '\r' || c == ' ' || c == '\t') {
+ if c != '\n' && c != '\r' && c != ' ' && c != '\t' {
i--
break
}
@@ -820,7 +850,7 @@ func (p *Parser) parseKey(b []byte) (reference, []byte, error) {
ref := p.builder.Push(Node{
Kind: Key,
- Raw: p.Range(raw),
+ Raw: p.rangeOfToken(raw, b),
Data: key,
})
@@ -836,7 +866,7 @@ func (p *Parser) parseKey(b []byte) (reference, []byte, error) {
p.builder.PushAndChain(Node{
Kind: Key,
- Raw: p.Range(raw),
+ Raw: p.rangeOfToken(raw, b),
Data: key,
})
} else {
@@ -897,11 +927,11 @@ func (p *Parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
// validate the string and return a direct reference to the buffer.
if !escaped {
str := token[startIdx:endIdx]
- verr := characters.Utf8TomlValidAlreadyEscaped(str)
- if verr.Zero() {
+ highlight := characters.Utf8TomlValidAlreadyEscaped(str)
+ if len(highlight) == 0 {
return token, str, rest, nil
}
- return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
+ return nil, nil, nil, NewParserError(highlight, "invalid UTF-8")
}
i := startIdx
@@ -972,7 +1002,7 @@ func hexToRune(b []byte, length int) (rune, error) {
var r uint32
for i, c := range b {
- d := uint32(0)
+ var d uint32
switch {
case '0' <= c && c <= '9':
d = uint32(c - '0')
@@ -1013,7 +1043,7 @@ func (p *Parser) parseIntOrFloatOrDateTime(b []byte) (reference, []byte, error)
return p.builder.Push(Node{
Kind: Float,
Data: b[:3],
- Raw: p.Range(b[:3]),
+ Raw: p.rangeOfToken(b[:3], b[3:]),
}), b[3:], nil
case 'n':
if !scanFollowsNan(b) {
@@ -1023,7 +1053,7 @@ func (p *Parser) parseIntOrFloatOrDateTime(b []byte) (reference, []byte, error)
return p.builder.Push(Node{
Kind: Float,
Data: b[:3],
- Raw: p.Range(b[:3]),
+ Raw: p.rangeOfToken(b[:3], b[3:]),
}), b[3:], nil
case '+', '-':
return p.scanIntOrFloat(b)
@@ -1076,7 +1106,7 @@ byteLoop:
}
case c == 'T' || c == 't' || c == ':' || c == '.':
hasTime = true
- case c == '+' || c == '-' || c == 'Z' || c == 'z':
+ case c == '+' || c == 'Z' || c == 'z':
hasTz = true
case c == ' ':
if !seenSpace && i+1 < len(b) && isDigit(b[i+1]) {
@@ -1148,7 +1178,7 @@ func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) {
return p.builder.Push(Node{
Kind: Integer,
Data: b[:i],
- Raw: p.Range(b[:i]),
+ Raw: p.rangeOfToken(b[:i], b[i:]),
}), b[i:], nil
}
@@ -1172,7 +1202,7 @@ func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) {
return p.builder.Push(Node{
Kind: Float,
Data: b[:i+3],
- Raw: p.Range(b[:i+3]),
+ Raw: p.rangeOfToken(b[:i+3], b[i+3:]),
}), b[i+3:], nil
}
@@ -1184,7 +1214,7 @@ func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) {
return p.builder.Push(Node{
Kind: Float,
Data: b[:i+3],
- Raw: p.Range(b[:i+3]),
+ Raw: p.rangeOfToken(b[:i+3], b[i+3:]),
}), b[i+3:], nil
}
@@ -1207,7 +1237,7 @@ func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) {
return p.builder.Push(Node{
Kind: kind,
Data: b[:i],
- Raw: p.Range(b[:i]),
+ Raw: p.rangeOfToken(b[:i], b[i:]),
}), b[i:], nil
}
diff --git a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
index 00cfd6de458..5a79da88e86 100644
--- a/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
+++ b/hack/tools/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
@@ -1,7 +1,32 @@
package unstable
-// The Unmarshaler interface may be implemented by types to customize their
-// behavior when being unmarshaled from a TOML document.
+// Unmarshaler is implemented by types that can unmarshal a TOML
+// description of themselves. The input is a valid TOML document
+// containing the relevant portion of the parsed document.
+//
+// For tables (including split tables defined in multiple places),
+// the data contains the raw key-value bytes from the original document
+// with adjusted table headers to be relative to the unmarshaling target.
type Unmarshaler interface {
- UnmarshalTOML(value *Node) error
+ UnmarshalTOML(data []byte) error
+}
+
+// RawMessage is a raw encoded TOML value. It implements Unmarshaler
+// and can be used to delay TOML decoding or capture raw content.
+//
+// Example usage:
+//
+// type Config struct {
+// Plugin RawMessage `toml:"plugin"`
+// }
+//
+// var cfg Config
+// toml.NewDecoder(r).EnableUnmarshalerInterface().Decode(&cfg)
+// // cfg.Plugin now contains the raw TOML bytes for [plugin]
+type RawMessage []byte
+
+// UnmarshalTOML implements Unmarshaler.
+func (m *RawMessage) UnmarshalTOML(data []byte) error {
+ *m = append((*m)[0:0], data...)
+ return nil
}
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.dockerignore b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.dockerignore
new file mode 100644
index 00000000000..77738287f0e
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.dockerignore
@@ -0,0 +1 @@
+dist/
\ No newline at end of file
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.gitignore b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.gitignore
new file mode 100644
index 00000000000..4ebc79c5d97
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.gitignore
@@ -0,0 +1,25 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+/gomodguard
+
+*.xml
+
+dist/
+
+coverage.*
+
+.idea/
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.golangci.yml b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.golangci.yml
new file mode 100644
index 00000000000..2e3266adbb0
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/.golangci.yml
@@ -0,0 +1,35 @@
+version: "2"
+
+linters:
+ default: all
+ disable:
+ - lll
+ - gomodguard
+ - gomoddirectives
+ - gochecknoglobals
+ - paralleltest
+ - varnamelen
+ - exhaustruct
+ - depguard
+ - forbidigo
+ - funlen
+ - nlreturn
+ - nonamedreturns
+ - cyclop
+ - err113
+ - perfsprint
+ - tagliatelle
+ - wrapcheck
+ - mnd
+ - wsl
+ - noinlineerr
+ settings:
+ revive:
+ rules:
+ - name: package-comments
+ disabled: true
+ exclusions:
+ rules:
+ - path: _test\.go$
+ linters:
+ - goconst
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/LICENSE b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/LICENSE
new file mode 100644
index 00000000000..acd8a81e167
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Ryan Currah
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/Makefile b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/Makefile
new file mode 100644
index 00000000000..d30a2255bf5
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/Makefile
@@ -0,0 +1,87 @@
+current_dir = $(shell pwd)
+
+.PHONY: goimports
+goimports:
+ find . -name '*.go' -exec goimports -w -local github.com/ryancurrah/gomodguard {} +
+
+.PHONY: lint
+lint:
+ golangci-lint run ./...
+ cd cmd/gomodguard && golangci-lint run ./...
+
+.PHONY: tidy
+tidy:
+ go mod tidy
+ cd cmd/gomodguard && go mod tidy
+
+.PHONY: build
+build:
+ cd cmd/gomodguard && go build -o "$$(go env GOPATH)/bin/gomodguard" main.go
+
+.PHONY: run
+run: build
+ ./gomodguard
+
+.PHONY: test
+test:
+ go test -v -coverprofile coverage.out
+ cd cmd/gomodguard && go test -v -coverprofile coverage.out ./...
+ cat cmd/gomodguard/coverage.out | tail -n +2 >> coverage.out
+
+.PHONY: cover
+cover:
+ gocover-cobertura < coverage.out > coverage.xml
+
+.PHONY: dockerrun
+dockerrun: dockerbuild
+ docker run -v "${current_dir}/.gomodguard.yaml:/.gomodguard.yaml" ryancurrah/gomodguard:latest
+
+.PHONY: snapshot
+snapshot:
+ cd cmd/gomodguard && goreleaser --clean --snapshot
+
+.PHONY: release
+release:
+ cd cmd/gomodguard && goreleaser --clean
+
+.PHONY: clean
+clean:
+ rm -rf dist/
+ rm -f gomodguard coverage.xml coverage.out
+ rm -f cmd/gomodguard/coverage.out
+
+.PHONY: tag
+tag:
+ @if [ -n "$$(git status --porcelain)" ]; then \
+ echo "error: working tree not clean"; exit 1; \
+ fi; \
+ current=$$(git tag --sort=-v:refname --list 'v*' | head -n1 || echo "none"); \
+ read -p "Current version: $$current. Enter new version: " version; \
+ if [ -z "$$version" ]; then echo "error: version required"; exit 1; fi; \
+ bump_branch="bump-library-to-$$version"; \
+ git tag "$$version" && \
+ git push origin "$$version" && \
+ git checkout -b "$$bump_branch" && \
+ (cd cmd/gomodguard && GOWORK=off go get "github.com/ryancurrah/gomodguard/v2@$$version" && GOWORK=off go mod tidy) && \
+ git add cmd/gomodguard/go.mod cmd/gomodguard/go.sum && \
+ git commit -m "chore: bump library to $$version" && \
+ git tag "cmd/gomodguard/$$version" && \
+ git push -u origin "$$bump_branch" "cmd/gomodguard/$$version" && \
+ gh pr create --title "chore: bump library to $$version" --body "Required by cmd/gomodguard/$$version release." && \
+ echo "waiting for PR to merge..." && \
+ while :; do \
+ state=$$(gh pr view --json state -q .state); \
+ if [ "$$state" = "MERGED" ]; then break; fi; \
+ if [ "$$state" = "CLOSED" ]; then echo "error: PR closed without merge"; exit 1; fi; \
+ sleep 30; \
+ done && \
+ git checkout main && git pull --ff-only origin main && \
+ git branch -D "$$bump_branch"
+
+.PHONY: install-mac-tools
+install-tools-mac:
+ brew install goreleaser/tap/goreleaser
+
+.PHONY: install-go-tools
+install-go-tools:
+ go install -v github.com/t-yuki/gocover-cobertura@latest
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/README.md b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/README.md
new file mode 100644
index 00000000000..a0bea99f0fe
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/README.md
@@ -0,0 +1,219 @@
+# gomodguard
+[](/LICENSE)
+[](https://codecov.io/gh/ryancurrah/gomodguard)
+[](https://github.com/ryancurrah/gomodguard/actions?query=workflow%3AGo)
+[](https://github.com/ryancurrah/gomodguard/releases/latest)
+[](https://hub.docker.com/r/ryancurrah/gomodguard)
+[](https://somsubhra.com/github-release-stats/?username=ryancurrah&repository=gomodguard)
+
+
+
+Allow and block list linter for direct Go module dependencies. This is useful for organizations where they want to standardize on the modules used and be able to recommend alternative modules.
+
+## Description
+
+Allowed and blocked modules are defined in a `./.gomodguard.yaml` or `~/.gomodguard.yaml` file.
+
+Modules can be allowed by module or prefix name. When allowed modules are specified any modules not in the allowed configuration are blocked.
+
+If no allowed modules or module prefixes are specified then all modules are allowed except for blocked ones.
+
+The linter looks for blocked modules in `go.mod` and searches for imported packages where the imported packages module is blocked. Indirect modules are not considered.
+
+Alternative modules can be optionally recommended in the blocked modules list.
+
+If the linted module imports a blocked module but the linted module is in the recommended modules list the blocked module is ignored. Usually, this means the linted module wraps that blocked module for use by other modules, therefore the import of the blocked module should not be blocked.
+
+Version constraints can be specified for modules as well which lets you block new or old versions of modules or specific versions.
+
+Results are printed to `stdout`.
+
+Logging statements are printed to `stderr`.
+
+Results can be exported to different report formats. Which can be imported into CI tools. See the help section for more information.
+
+# Configuration
+
+```yaml
+# allowed defines the modules that are permitted as direct dependencies.
+# When this section is non-empty, any module not matched by an entry is blocked.
+# When omitted entirely, all modules are allowed except those in the blocked list.
+allowed:
+ # Exact match (default when match-type is omitted).
+ - module: go.yaml.in/yaml/v4
+ - module: github.com/go-xmlfmt/xmlfmt
+
+ # version constrains which versions of the module are allowed.
+ # Uses semver constraint syntax (e.g. ">= 1.0.0", "~1.2", "== 2.5.0").
+ - module: github.com/confluentinc/confluent-kafka-go/v2
+ version: "== 2.5.0"
+
+ # match-type controls how the module is matched against module paths.
+ # Options: exact (default), prefix, regex
+ - module: github.com/kubernetes
+ match-type: prefix
+ - module: github.com/apache/arrow-go
+ match-type: prefix
+ - module: "github.com/somecompany/.*"
+ match-type: regex
+
+# blocked defines modules that are not permitted as direct dependencies.
+blocked:
+ - module: github.com/uudashr/go-module
+ # match-type controls how the module is matched against module paths.
+ # Options: exact (default), prefix, regex
+ match-type: exact
+
+ # recommendations lists alternative modules to suggest in the lint error.
+ recommendations:
+ - golang.org/x/mod
+
+ # reason is a human-readable explanation appended to the lint error.
+ reason: "`mod` is the official go.mod parser library."
+
+ - module: github.com/mitchellh/go-homedir
+ # version constrains which versions of the module are blocked.
+ # Uses semver constraint syntax. When omitted, all versions are blocked.
+ version: "<= 1.1.0"
+ reason: "old versions have a known bug."
+
+ - module: "github.com/badcompany/.*"
+ match-type: regex
+ reason: "No badcompany packages are permitted."
+
+# Blocks 'replace' directives using local filesystem paths to prevent
+# accidental commits of dev overrides. Sibling modules in multi-module
+# repos are automatically detected and permitted.
+local_replace_directives: true
+```
+
+### Field reference
+
+#### Top-level fields
+
+| Field | Type | Default | Description |
+|---|---|---|---|
+| `allowed` | list | *(none)* | Modules that are permitted. When non-empty, anything not matched is blocked. |
+| `blocked` | list | *(none)* | Modules that are explicitly blocked. |
+| `local_replace_directives` | bool | `false` | Block any module whose `replace` directive points to a local filesystem path. Multi-module repo aware: sibling modules whose replacement path contains a matching `go.mod` are not blocked. |
+
+#### `allowed` / `blocked` entry fields
+
+| Field | Type | Description |
+|---|---|---|
+| `module` | string | The module path to match against. |
+| `match-type` | `exact` \| `prefix` \| `regex` | How `module` is matched against dependency paths. Defaults to `exact`. |
+| `version` | semver constraint string | Restricts the rule to specific versions (e.g. `<= 1.2.0`, `>= 2.0.0`). When omitted, all versions match. |
+| `recommendations` | list of module paths | *(blocked only)* Alternative modules to suggest in the lint error. If the module being linted is itself in this list, the block is skipped. |
+| `reason` | string | *(blocked only)* Human-readable explanation appended to the lint error. |
+
+#### Match type precedence
+
+When multiple rules can match the same module the following precedence applies:
+
+1. **Exact match** — highest priority; wins over prefix and regex.
+2. **Prefix match** — next priority; longest matching prefix wins.
+3. **Regex match** — lowest priority; evaluated in alphabetical key order; first match wins.
+
+## Example .gomodguard.yaml Files
+
+The following example configuration files are available:
+
+- [examples/alloptions/.gomodguard.yaml](examples/alloptions/.gomodguard.yaml)
+- [examples/allowedversion/.gomodguard.yaml](examples/allowedversion/.gomodguard.yaml)
+- [examples/emptyallowlist/.gomodguard.yaml](examples/emptyallowlist/.gomodguard.yaml)
+- [examples/indirectdep/.gomodguard.yaml](examples/indirectdep/.gomodguard.yaml)
+- [examples/majorversion/.gomodguard.yaml](examples/majorversion/.gomodguard.yaml)
+- [examples/regexversion/.gomodguard.yaml](examples/regexversion/.gomodguard.yaml)
+- [examples/regextest/.gomodguard.yaml](examples/regextest/.gomodguard.yaml)
+
+### Migrating from v1
+
+If you have a v1 `.gomodguard.yaml` file, you can automatically migrate it to the new v2 schema by running:
+
+```
+gomodguard migrate > .gomodguard-v2.yaml
+mv .gomodguard-v2.yaml .gomodguard.yaml
+```
+
+## Usage
+
+```
+╰─ gomodguard -help
+Usage: gomodguard [files...]
+Also supports package syntax but will use it in relative path, i.e. ./pkg/...
+
+Commands:
+ (default) Lint Go module dependencies using the configuration file
+ migrate Convert a v1 .gomodguard.yaml config file to v2 format and print to stdout
+
+Flags:
+ -f string
+ Report results to the specified file. A report type must also be specified
+ -file string
+
+ -h Show this help text
+ -help
+
+ -i int
+ Exit code when issues were found (default 2)
+ -issues-exit-code int
+ (default 2)
+ -n Don't lint test files
+ -no-test
+
+ -r string
+ Report results to one of the following formats: checkstyle. A report file destination must also be specified
+ -report string
+
+ -version
+ Print the version
+```
+
+## Example
+
+```
+╰─ cd examples/alloptions
+╰─ gomodguard -r checkstyle -f gomodguard-checkstyle.xml ./...
+
+info: allowed modules, [github.com/Masterminds/semver/v3 github.com/go-xmlfmt/xmlfmt golang.org gopkg.in/yaml.v3]
+info: blocked modules, [github.com/gofrs/uuid github.com/mitchellh/go-homedir github.com/uudashr/go-module]
+blocked_example.go:6:1 import of package `github.com/gofrs/uuid` is blocked because the module is in the blocked modules list. `github.com/ryancurrah/gomodguard` is a recommended module. testing if module is not blocked when it is recommended.
+blocked_example.go:7:1 import of package `github.com/mitchellh/go-homedir` is blocked because the module is in the blocked modules list. version `v1.1.0` is blocked because it does not meet the version constraint `<=1.1.0`. testing if blocked version constraint works.
+blocked_example.go:8:1 import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library.
+```
+
+Resulting checkstyle file
+
+```
+╰─ cat gomodguard-checkstyle.xml
+
+
+
+
+
+
+
+
+
+```
+
+## Install
+
+```
+go install github.com/ryancurrah/gomodguard/cmd/gomodguard/v2@latest
+```
+
+## Develop
+
+```
+git clone https://github.com/ryancurrah/gomodguard.git && cd gomodguard/cmd/gomodguard
+
+go build -o gomodguard main.go
+```
+
+The repository is a multi-module workspace: the library lives at the root and the CLI lives under `cmd/gomodguard`. A `go.work` file at the repo root wires them together so local CLI builds pick up local library changes without needing a `replace` directive in `cmd/gomodguard/go.mod`.
+
+## License
+
+**MIT**
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/allowed.go b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/allowed.go
new file mode 100644
index 00000000000..536a74cbefd
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/allowed.go
@@ -0,0 +1,42 @@
+package gomodguard
+
+import (
+ "fmt"
+
+ "github.com/Masterminds/semver/v3"
+)
+
+// Allowed is a list of modules that are allowed to be used.
+type Allowed []AllowedModule
+
+// AllowedModule is a single entry in the allowed list.
+type AllowedModule struct {
+ Module string `yaml:"module"`
+ MatchType MatchType `yaml:"match-type"`
+ Version *semver.Constraints `yaml:"version"`
+ Matcher Matcher `yaml:"-"`
+}
+
+// CheckVersion returns true if the module version matches the allowed constraint,
+// or if no version constraint is specified.
+func (r *AllowedModule) CheckVersion(moduleVersion string) (bool, error) {
+ if r.Version == nil {
+ return true, nil
+ }
+
+ version, err := semver.NewVersion(moduleVersion)
+ if err != nil {
+ return false, err
+ }
+
+ return r.Version.Check(version), nil
+}
+
+// NotAllowedReason returns the reason why the module version is not allowed.
+func (r *AllowedModule) NotAllowedReason(moduleVersion string) string {
+ if r == nil || r.Version == nil {
+ return "the module is not in the allowed modules list."
+ }
+
+ return fmt.Sprintf("version `%s` does not meet the allowed version constraint `%s`.", moduleVersion, r.Version)
+}
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/blocked.go b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/blocked.go
new file mode 100644
index 00000000000..5ba7ee1f362
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/blocked.go
@@ -0,0 +1,99 @@
+package gomodguard
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/Masterminds/semver/v3"
+)
+
+// Blocked is a list of modules that are blocked and not to be used.
+type Blocked []BlockedModule
+
+// BlockedModule is a single entry in the blocked list.
+type BlockedModule struct {
+ Module string `yaml:"module"`
+ MatchType MatchType `yaml:"match-type"`
+ Recommendations []string `yaml:"recommendations"`
+ Reason string `yaml:"reason"`
+ Version *semver.Constraints `yaml:"version"`
+ Matcher Matcher `yaml:"-"`
+}
+
+// CheckVersion returns true if the module version matches the blocked constraint.
+// If no version constraint is specified, all versions are considered blocked.
+func (r *BlockedModule) CheckVersion(moduleVersion string) (bool, error) {
+ if r.Version == nil {
+ return true, nil
+ }
+
+ version, err := semver.NewVersion(moduleVersion)
+ if err != nil {
+ return true, err
+ }
+
+ return r.Version.Check(version), nil
+}
+
+// BlockReason returns the reason why the module or version is blocked.
+func (r *BlockedModule) BlockReason(currentModuleVersion string) string {
+ var sb strings.Builder
+
+ if r.Version != nil {
+ _, _ = fmt.Fprintf(&sb, "version `%s` is blocked because it does not meet the version constraint `%s`.",
+ currentModuleVersion, r.Version)
+ }
+
+ if len(r.Recommendations) > 0 {
+ if sb.Len() > 0 {
+ sb.WriteString(" ")
+ }
+
+ for i := range r.Recommendations {
+ switch {
+ case len(r.Recommendations) == 1:
+ _, _ = fmt.Fprintf(&sb, "`%s` is a recommended module.", r.Recommendations[i])
+ case (i+1) != len(r.Recommendations) && (i+1) == (len(r.Recommendations)-1):
+ _, _ = fmt.Fprintf(&sb, "`%s` ", r.Recommendations[i])
+ case (i + 1) != len(r.Recommendations):
+ _, _ = fmt.Fprintf(&sb, "`%s`, ", r.Recommendations[i])
+ default:
+ _, _ = fmt.Fprintf(&sb, "and `%s` are recommended modules.", r.Recommendations[i])
+ }
+ }
+ }
+
+ if r.Reason != "" {
+ if sb.Len() > 0 {
+ _, _ = fmt.Fprintf(&sb, " %s.", strings.TrimRight(r.Reason, "."))
+ } else {
+ _, _ = fmt.Fprintf(&sb, "%s.", strings.TrimRight(r.Reason, "."))
+ }
+ }
+
+ return sb.String()
+}
+
+// IsCurrentModuleARecommendation returns true if the current module is in the Recommendations list.
+func (r *BlockedModule) IsCurrentModuleARecommendation(currentModuleName string) bool {
+ if r == nil {
+ return false
+ }
+
+ for n := range r.Recommendations {
+ if strings.TrimSpace(currentModuleName) == strings.TrimSpace(r.Recommendations[n]) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// HasRecommendations returns true if the blocked package has recommended modules.
+func (r *BlockedModule) HasRecommendations() bool {
+ if r == nil {
+ return false
+ }
+
+ return len(r.Recommendations) > 0
+}
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/codecov.yml b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/codecov.yml
new file mode 100644
index 00000000000..4c475c7ca73
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/codecov.yml
@@ -0,0 +1,9 @@
+coverage:
+ status:
+ project:
+ default:
+ target: auto
+ threshold: 5%
+ patch:
+ default:
+ target: auto
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/filesearch.go b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/filesearch.go
new file mode 100644
index 00000000000..4c4769d711d
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/filesearch.go
@@ -0,0 +1,66 @@
+package gomodguard
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// Find returns files based on search string arguments and filters.
+func Find(cwd string, skipTests bool, args []string) []string {
+ var (
+ foundFiles = []string{}
+ filteredFiles = []string{}
+ )
+
+ for _, f := range args {
+ if strings.HasSuffix(f, "/...") {
+ dir, _ := filepath.Split(f)
+
+ foundFiles = append(foundFiles, expandGoWildcard(dir)...)
+
+ continue
+ }
+
+ if _, err := os.Stat(f); err == nil {
+ foundFiles = append(foundFiles, f)
+ }
+ }
+
+ // Use relative path to print shorter names, sort out test foundFiles if chosen.
+ for _, f := range foundFiles {
+ if skipTests {
+ if strings.HasSuffix(f, "_test.go") {
+ continue
+ }
+ }
+
+ if relativePath, err := filepath.Rel(cwd, f); err == nil {
+ filteredFiles = append(filteredFiles, relativePath)
+
+ continue
+ }
+
+ filteredFiles = append(filteredFiles, f)
+ }
+
+ return filteredFiles
+}
+
+// expandGoWildcard path provided.
+func expandGoWildcard(root string) []string {
+ foundFiles := []string{}
+
+ _ = filepath.Walk(root, func(path string, info os.FileInfo, _ error) error {
+ // Only append go foundFiles.
+ if !strings.HasSuffix(info.Name(), ".go") {
+ return nil
+ }
+
+ foundFiles = append(foundFiles, path)
+
+ return nil
+ })
+
+ return foundFiles
+}
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/go.work b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/go.work
new file mode 100644
index 00000000000..63d63678e24
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/go.work
@@ -0,0 +1,6 @@
+go 1.25.0
+
+use (
+ .
+ ./cmd/gomodguard
+)
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/go.work.sum b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/go.work.sum
new file mode 100644
index 00000000000..fc90f0f3b68
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/go.work.sum
@@ -0,0 +1,8 @@
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw=
+golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/issue.go b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/issue.go
new file mode 100644
index 00000000000..d60fc3a868d
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/issue.go
@@ -0,0 +1,20 @@
+package gomodguard
+
+import (
+ "fmt"
+ "go/token"
+)
+
+// Issue represents the result of one error.
+type Issue struct {
+ FileName string
+ LineNumber int
+ Position token.Position
+ Reason string
+}
+
+// String returns the filename, line
+// number and reason of a Issue.
+func (r *Issue) String() string {
+ return fmt.Sprintf("%s:%d:1 %s", r.FileName, r.LineNumber, r.Reason)
+}
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/matchers.go b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/matchers.go
new file mode 100644
index 00000000000..ae74b978a3c
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/matchers.go
@@ -0,0 +1,77 @@
+package gomodguard
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+// MatchType represents the type of matching to be performed for a module name.
+type MatchType string
+
+const (
+ // ExactMatch matches a module name exactly.
+ ExactMatch MatchType = "exact"
+ // PrefixMatch matches a module name by prefix.
+ PrefixMatch MatchType = "prefix"
+ // RegexMatch matches a module name by regex.
+ RegexMatch MatchType = "regex"
+)
+
+// Matcher interface for matching module names.
+type Matcher interface {
+ Match(moduleName string) bool
+}
+
+// ExactMatcher matches a module name exactly.
+type ExactMatcher struct {
+ Target string
+}
+
+func (m ExactMatcher) Match(moduleName string) bool {
+ return strings.TrimSpace(moduleName) == m.Target
+}
+
+// PrefixMatcher matches a module name by prefix.
+type PrefixMatcher struct {
+ Prefix string
+}
+
+// Match returns true if the moduleName starts with the Prefix, ignoring leading/trailing whitespace and case.
+func (m PrefixMatcher) Match(moduleName string) bool {
+ return strings.HasPrefix(strings.TrimSpace(strings.ToLower(moduleName)), strings.ToLower(m.Prefix))
+}
+
+// RegexMatcher matches a module name by regex.
+type RegexMatcher struct {
+ Regex *regexp.Regexp
+}
+
+func (m RegexMatcher) Match(moduleName string) bool {
+ if m.Regex == nil {
+ return false
+ }
+
+ return m.Regex.MatchString(strings.TrimSpace(moduleName))
+}
+
+// compileMatcher creates a Matcher based on the match type and pattern.
+//
+//nolint:ireturn // This factory intentionally returns the Matcher interface.
+func compileMatcher(matchType MatchType, pattern string) (Matcher, error) {
+ switch matchType {
+ case PrefixMatch:
+ return PrefixMatcher{Prefix: strings.TrimSpace(pattern)}, nil
+ case RegexMatch:
+ re, err := regexp.Compile(strings.TrimSpace(pattern))
+ if err != nil {
+ return nil, err
+ }
+
+ return RegexMatcher{Regex: re}, nil
+ case ExactMatch, "":
+ return ExactMatcher{Target: strings.TrimSpace(pattern)}, nil
+ default:
+ return nil, fmt.Errorf("unknown match-type %q for pattern %q", matchType, pattern)
+ }
+}
diff --git a/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/processor.go b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/processor.go
new file mode 100644
index 00000000000..82fa4c2dfaf
--- /dev/null
+++ b/hack/tools/vendor/github.com/ryancurrah/gomodguard/v2/processor.go
@@ -0,0 +1,517 @@
+package gomodguard
+
+import (
+ "bytes"
+ "cmp"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "go/parser"
+ "go/token"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "slices"
+ "strings"
+
+ "golang.org/x/mod/modfile"
+)
+
+const (
+ goModFilename = "go.mod"
+ errReadingGoModFile = "unable to read module file %s: %w"
+ errParsingGoModFile = "unable to parse module file %s: %w"
+)
+
+var (
+ blockReasonInBlockedList = "import of package `%s` is blocked because the module is in the blocked modules list."
+ blockReasonHasLocalReplaceDirective = "import of package `%s` is blocked because the module has a local replace directive."
+
+ // startsWithVersion is used to test when a string begins with the version identifier of a module,
+ // after having stripped the prefix base module name. IE "github.com/foo/bar/v2/baz" => "v2/baz"
+ // probably indicates that the module is actually github.com/foo/bar/v2, not github.com/foo/bar.
+ startsWithVersion = regexp.MustCompile(`^v[0-9]+`)
+)
+
+// ruleIndex provides deterministic, specificity-based rule matching.
+// Rules are evaluated in three tiers:
+// 1. Exact match — O(1) map lookup.
+// 2. Prefix match — longest matching prefix wins.
+// 3. Regex match — evaluated in alphabetical key order; first match wins.
+type ruleIndex struct {
+ exactLookup map[string]string // trimmed module name -> original map key
+ prefixKeys []string // sorted by length desc, then alphabetically
+ regexKeys []string // sorted alphabetically
+ matchers map[string]Matcher // key -> compiled matcher
+}
+
+// newRuleIndex categorises rule keys into exact, prefix, and regex tiers
+// and pre-sorts the prefix and regex tiers for deterministic evaluation.
+func newRuleIndex(keys []string, matchTypes map[string]MatchType, matchers map[string]Matcher) *ruleIndex {
+ idx := &ruleIndex{
+ exactLookup: make(map[string]string, len(keys)),
+ matchers: matchers,
+ }
+
+ for _, k := range keys {
+ switch matchTypes[k] {
+ case ExactMatch:
+ idx.exactLookup[strings.TrimSpace(k)] = k
+ case PrefixMatch:
+ idx.prefixKeys = append(idx.prefixKeys, k)
+ case RegexMatch:
+ idx.regexKeys = append(idx.regexKeys, k)
+ default:
+ idx.exactLookup[strings.TrimSpace(k)] = k
+ }
+ }
+
+ // Longest prefix first for most-specific match.
+ slices.SortFunc(idx.prefixKeys, func(a, b string) int {
+ return cmp.Compare(len(b), len(a))
+ })
+
+ // Alphabetical order for deterministic regex evaluation.
+ slices.Sort(idx.regexKeys)
+
+ return idx
+}
+
+// bestMatch returns the key of the best-matching rule for moduleName,
+// following the tiered precedence: exact > longest prefix > first regex.
+func (idx *ruleIndex) bestMatch(moduleName string) (string, bool) {
+ trimmed := strings.TrimSpace(moduleName)
+
+ // Tier 1: exact match (O(1))
+ if key, ok := idx.exactLookup[trimmed]; ok {
+ return key, true
+ }
+
+ // Tier 2: longest prefix match
+ for _, key := range idx.prefixKeys {
+ if idx.matchers[key].Match(moduleName) {
+ return key, true
+ }
+ }
+
+ // Tier 3: first regex match (alphabetical order)
+ for _, key := range idx.regexKeys {
+ if idx.matchers[key].Match(moduleName) {
+ return key, true
+ }
+ }
+
+ return "", false
+}
+
+// Configuration of gomodguard allow and block lists.
+type Configuration struct {
+ Allowed Allowed `yaml:"allowed"`
+ Blocked Blocked `yaml:"blocked"`
+ LocalReplaceDirectives bool `yaml:"local_replace_directives"`
+}
+
+// InitMatchers initializes matchers for the configuration rules.
+func (c *Configuration) InitMatchers() error {
+ for i := range c.Allowed {
+ m, err := compileMatcher(c.Allowed[i].MatchType, c.Allowed[i].Module)
+ if err != nil {
+ return fmt.Errorf("failed compiling allowed matcher for '%s': %w", c.Allowed[i].Module, err)
+ }
+
+ c.Allowed[i].Matcher = m
+ }
+
+ for i := range c.Blocked {
+ m, err := compileMatcher(c.Blocked[i].MatchType, c.Blocked[i].Module)
+ if err != nil {
+ return fmt.Errorf("failed compiling blocked matcher for '%s': %w", c.Blocked[i].Module, err)
+ }
+
+ c.Blocked[i].Matcher = m
+ }
+
+ return nil
+}
+
+// Processor processes Go files.
+type Processor struct {
+ Config *Configuration
+ Modfile *modfile.File
+ blockedModulesFromModFile map[string][]string
+}
+
+// NewProcessor will create a Processor to lint blocked packages.
+func NewProcessor(config *Configuration) (*Processor, error) {
+ goModFileBytes, err := loadGoModFile()
+ if err != nil {
+ return nil, fmt.Errorf(errReadingGoModFile, goModFilename, err)
+ }
+
+ modFile, err := modfile.Parse(goModFilename, goModFileBytes, nil)
+ if err != nil {
+ return nil, fmt.Errorf(errParsingGoModFile, goModFilename, err)
+ }
+
+ if err := config.InitMatchers(); err != nil {
+ return nil, err
+ }
+
+ p := &Processor{
+ Config: config,
+ Modfile: modFile,
+ }
+
+ p.SetBlockedModules()
+
+ return p, nil
+}
+
+// ProcessFiles takes a string slice with file names (full paths)
+// and lints them.
+func (p *Processor) ProcessFiles(filenames []string) (issues []Issue) {
+ for _, filename := range filenames {
+ data, err := os.ReadFile(filepath.Clean(filename))
+ if err != nil {
+ issues = append(issues, Issue{
+ FileName: filename,
+ LineNumber: 0,
+ Reason: fmt.Sprintf("unable to read file, file cannot be linted (%s)", err.Error()),
+ })
+
+ continue
+ }
+
+ issues = append(issues, p.process(filename, data)...)
+ }
+
+ return issues
+}
+
+// SetBlockedModules determines and sets which modules are blocked by reading
+// the go.mod file of the current module.
+//
+// It works by iterating over the required modules specified in the require
+// directive, checking if the module prefix or full name is in the allowed list.
+//
+// Rules are evaluated using a layered strategy for deterministic results:
+// 1. Exact match — O(1) lookup; wins immediately.
+// 2. Prefix match — longest matching prefix wins.
+// 3. Regex match — evaluated in alphabetical key order; first match wins.
+func (p *Processor) SetBlockedModules() { //nolint:gocognit // Ack this is a long func.
+ blockedModules := make(map[string][]string, len(p.Modfile.Require))
+ currentModuleName := p.Modfile.Module.Mod.Path
+ requiredModules := p.Modfile.Require
+
+ // Build tiered rule indices for blocked and allowed rules.
+ blockedIdx, blockedLookup := buildRuleIndex(
+ p.Config.Blocked,
+ func(r BlockedModule) string { return r.Module },
+ func(r BlockedModule) MatchType { return r.MatchType },
+ func(r BlockedModule) Matcher { return r.Matcher },
+ )
+ allowedIdx, allowedLookup := buildRuleIndex(
+ p.Config.Allowed,
+ func(r AllowedModule) string { return r.Module },
+ func(r AllowedModule) MatchType { return r.MatchType },
+ func(r AllowedModule) Matcher { return r.Matcher },
+ )
+
+ for i := range requiredModules {
+ requiredModuleName := strings.TrimSpace(requiredModules[i].Mod.Path)
+ requiredModuleVersion := strings.TrimSpace(requiredModules[i].Mod.Version)
+
+ var matchedBlockRule *BlockedModule
+
+ // Check against blocked rules first (exact > longest prefix > first regex)
+ if key, ok := blockedIdx.bestMatch(requiredModuleName); ok {
+ rule := blockedLookup[key] // copy
+ matchedBlockRule = &rule
+ }
+
+ if matchedBlockRule != nil && matchedBlockRule.IsCurrentModuleARecommendation(currentModuleName) {
+ // The current module is a recommended alternative for this blocked module, allowing it.
+ matchedBlockRule = nil
+ }
+
+ if matchedBlockRule != nil {
+ isVersBlocked, err := matchedBlockRule.CheckVersion(requiredModuleVersion)
+ if err != nil {
+ // NOTE: Unreachable via real go.mod files; modfile.Parse rejects invalid versions
+ // earlier. Left untested by design as this branch cannot be triggered.
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("%s unable to parse version `%s`: %s",
+ blockReasonInBlockedList, requiredModuleVersion, err,
+ ),
+ )
+
+ continue
+ }
+
+ if !isVersBlocked {
+ // Doesn't match the blocked version constraint, so we let it pass the block check
+ matchedBlockRule = nil
+ }
+ }
+
+ // If it's blocked, record it and move to next
+ if matchedBlockRule != nil {
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("%s %s", blockReasonInBlockedList,
+ matchedBlockRule.BlockReason(requiredModuleVersion),
+ ),
+ )
+
+ continue
+ }
+
+ // If no allowed list is specified, default mapping is to allow all
+ if len(p.Config.Allowed) == 0 {
+ continue
+ }
+
+ isAllowed := false
+
+ var matchedButWrongVersion *AllowedModule
+
+ if key, ok := allowedIdx.bestMatch(requiredModuleName); ok {
+ rule := allowedLookup[key] // copy
+
+ ok, err := rule.CheckVersion(requiredModuleVersion)
+
+ switch {
+ case err != nil:
+ // NOTE: Unreachable via real go.mod files; modfile.Parse rejects invalid versions
+ // earlier. Left untested by design as this branch cannot be triggered.
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("import of package `%%s` is blocked because the module version `%s` could not be parsed: %s",
+ requiredModuleVersion, err,
+ ),
+ )
+
+ isAllowed = true // skip the generic "not allowed" message below
+ case ok:
+ isAllowed = true
+ default:
+ matchedButWrongVersion = &rule
+ }
+ }
+
+ if !isAllowed {
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("import of package `%%s` is blocked because %s", matchedButWrongVersion.NotAllowedReason(requiredModuleVersion)))
+ }
+ }
+
+ // Blocks local 'replace' directives to prevent committing dev overrides.
+ // Legitimate sibling modules in multi-module repos (sharing the same
+ // module name) are exempt.
+ if p.Config.LocalReplaceDirectives {
+ for _, r := range p.Modfile.Replace {
+ if isBlockedLocalReplace(r) {
+ blockedModules[r.Old.Path] = append(blockedModules[r.Old.Path],
+ blockReasonHasLocalReplaceDirective,
+ )
+ }
+ }
+ }
+
+ p.blockedModulesFromModFile = blockedModules
+}
+
+// buildRuleIndex constructs a ruleIndex and a key→rule lookup from any slice of rules.
+// The three accessor functions extract the module name, match type, and compiled matcher
+// from each rule, keeping this function independent of the concrete rule type.
+func buildRuleIndex[R any](
+ rules []R,
+ moduleFn func(R) string,
+ matchTypeFn func(R) MatchType,
+ matcherFn func(R) Matcher,
+) (*ruleIndex, map[string]R) {
+ keys := make([]string, 0, len(rules))
+ matchTypes := make(map[string]MatchType, len(rules))
+ matchers := make(map[string]Matcher, len(rules))
+ lookup := make(map[string]R, len(rules))
+
+ for _, r := range rules {
+ mod := moduleFn(r)
+ keys = append(keys, mod)
+ matchTypes[mod] = matchTypeFn(r)
+ matchers[mod] = matcherFn(r)
+ lookup[mod] = r
+ }
+
+ return newRuleIndex(keys, matchTypes, matchers), lookup
+}
+
+// process file imports and add lint error if blocked package is imported.
+func (p *Processor) process(filename string, data []byte) (issues []Issue) {
+ fileSet := token.NewFileSet()
+
+ file, err := parser.ParseFile(fileSet, filename, data, parser.ParseComments)
+ if err != nil {
+ issues = append(issues, Issue{
+ FileName: filename,
+ LineNumber: 0,
+ Reason: fmt.Sprintf("invalid syntax, file cannot be linted (%s)", err.Error()),
+ })
+
+ return
+ }
+
+ imports := file.Imports
+ for n := range imports {
+ importedPkg := strings.TrimSpace(strings.Trim(imports[n].Path.Value, "\""))
+
+ blockReasons := p.isBlockedPackageFromModFile(importedPkg)
+ if blockReasons == nil {
+ continue
+ }
+
+ for _, blockReason := range blockReasons {
+ issues = append(issues, p.addError(fileSet, imports[n].Pos(), blockReason))
+ }
+ }
+
+ return issues
+}
+
+// addError adds an error for the file and line number for the current token.Pos
+// with the given reason.
+func (p *Processor) addError(fileset *token.FileSet, pos token.Pos, reason string) Issue {
+ position := fileset.Position(pos)
+
+ return Issue{
+ FileName: position.Filename,
+ LineNumber: position.Line,
+ Position: position,
+ Reason: reason,
+ }
+}
+
+// isBlockedPackageFromModFile returns the block reason if the package is blocked.
+func (p *Processor) isBlockedPackageFromModFile(packageName string) []string {
+ for blockedModuleName, blockReasons := range p.blockedModulesFromModFile {
+ if isPackageInModule(packageName, blockedModuleName) {
+ formattedReasons := make([]string, 0, len(blockReasons))
+
+ for _, blockReason := range blockReasons {
+ formattedReasons = append(formattedReasons, fmt.Sprintf(blockReason, packageName))
+ }
+
+ return formattedReasons
+ }
+ }
+
+ return nil
+}
+
+// loadGoModFile loads the contents of the go.mod file in the current working directory.
+// It first checks the "GOMOD" environment variable to determine the path of the go.mod file.
+// If the environment variable is not set or the file does not exist, it falls back to reading the go.mod file in the current directory.
+// If the "GOMOD" environment variable is set to "/dev/null", it returns an error indicating that the current working directory must have a go.mod file.
+// The function returns the contents of the go.mod file as a byte slice and any error encountered during the process.
+func loadGoModFile() ([]byte, error) {
+ cmd := exec.Command("go", "env", "-json") //nolint:noctx // Ack at some point might use os/exec.CommandContext.
+ stdout, _ := cmd.StdoutPipe()
+ _ = cmd.Start()
+
+ if stdout == nil {
+ return os.ReadFile(filepath.Clean(goModFilename))
+ }
+
+ buf := new(bytes.Buffer)
+ _, _ = buf.ReadFrom(stdout)
+
+ goEnv := make(map[string]string)
+
+ err := json.Unmarshal(buf.Bytes(), &goEnv)
+ if err != nil {
+ return os.ReadFile(goModFilename)
+ }
+
+ if _, ok := goEnv["GOMOD"]; !ok {
+ return os.ReadFile(goModFilename)
+ }
+
+ if _, err = os.Stat(goEnv["GOMOD"]); os.IsNotExist(err) {
+ return os.ReadFile(goModFilename)
+ }
+
+ if goEnv["GOMOD"] == "/dev/null" || goEnv["GOMOD"] == "NUL" {
+ return nil, errors.New("current working directory must have a go.mod file")
+ }
+
+ return os.ReadFile(goEnv["GOMOD"])
+}
+
+// isBlockedLocalReplace returns true if the replace directive points to a local
+// filesystem path that is not a legitimate sibling module.
+func isBlockedLocalReplace(r *modfile.Replace) bool {
+ if r.New.Path == "" || r.New.Version != "" {
+ return false
+ }
+
+ replacePath := r.New.Path
+ if !filepath.IsAbs(replacePath) {
+ wd, err := os.Getwd()
+ if err != nil {
+ wd = "."
+ }
+
+ replacePath = filepath.Join(wd, replacePath)
+ }
+
+ return !isModuleAtPath(replacePath, r.Old.Path)
+}
+
+// isModuleAtPath returns true if the directory at path contains a go.mod file
+// that declares moduleName as its module, indicating a legitimate sibling module
+// in a multi-module repository rather than a local development override.
+func isModuleAtPath(path, moduleName string) bool {
+ data, err := os.ReadFile(filepath.Clean(filepath.Join(path, goModFilename)))
+ if err != nil {
+ return false
+ }
+
+ mf, err := modfile.Parse(goModFilename, data, nil)
+ if err != nil {
+ return false
+ }
+
+ return mf.Module.Mod.Path == moduleName
+}
+
+// isPackageInModule determines if a package is a part of the specified Go module.
+func isPackageInModule(pkg, mod string) bool {
+ // Split pkg and mod paths into parts
+ pkgPart := strings.Split(pkg, "/")
+ modPart := strings.Split(mod, "/")
+
+ pkgPartMatches := 0
+
+ // Count number of times pkg path matches the mod path
+ for i, m := range modPart {
+ if len(pkgPart) > i && pkgPart[i] == m {
+ pkgPartMatches++
+ }
+ }
+
+ // If pkgPartMatches are not the same length as modPart
+ // than the package is not in this module
+ if pkgPartMatches != len(modPart) {
+ return false
+ }
+
+ if len(pkgPart) > len(modPart) {
+ // If pkgPart path starts with a major version
+ // than the package is not in this module as
+ // major versions are completely different modules
+ if startsWithVersion.MatchString(pkgPart[len(modPart)]) {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/CLAUDE.md b/hack/tools/vendor/github.com/securego/gosec/v2/CLAUDE.md
new file mode 100644
index 00000000000..f3e0b72d206
--- /dev/null
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/CLAUDE.md
@@ -0,0 +1,51 @@
+# gosec - Go Security Checker
+
+gosec is a Go static analysis tool that inspects Go source code for security vulnerabilities by scanning the Go AST and SSA form.
+
+## Build & Test
+
+```bash
+# Build
+go build ./cmd/gosec/
+
+# Run all tests
+go test ./...
+
+# Run a specific test
+go test -run TestName ./path/to/package/
+
+# Lint
+golangci-lint run
+
+# Run gosec against a sample file
+go run ./cmd/gosec/ ./path/to/sample.go
+```
+
+## Code Style
+
+- Idiomatic Go; follow existing patterns in the codebase.
+- Prefer SSA-based analyzers over AST-based rules when feasible.
+- Optimize for performance — avoid unnecessary repeated AST or SSA traversals.
+
+## Project Structure
+
+- `rules/` — AST-based rule implementations
+- `analyzers/` — SSA-based analyzer implementations
+- `cmd/gosec/` — CLI entry point
+- `testutils/` — sample files used in tests (positive and negative cases)
+- `issue/` — issue and CWE type definitions
+- `report/` — output formatters
+
+## Adding Rules
+
+- Select an appropriate CWE aligned with current repository mappings.
+- Integrate the rule in all required registration points.
+- Add sample files in `testutils/` with at least 2 positive and 2 negative cases.
+- Update rule documentation in `README.md` in the same style as other rules.
+
+## Custom Commands
+
+- `/create-gosec-rule` — Design and implement a new gosec rule from an issue description
+- `/fix-gosec-bug` — Investigate and fix a bug from a GitHub issue URL
+- `/update-go-versions` — Bump supported Go versions across the repo
+- `/update-action-version` — Update the gosec GHCR image version in action.yml
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md b/hack/tools/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md
index f32526d5c6c..5a8a0e3cc47 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md
@@ -97,7 +97,7 @@ func runMyAnalyzer(pass *analysis.Pass) (interface{}, error) {
### Creating taint analysis rules
gosec taint analyzers track data flow from untrusted sources to dangerous sinks.
-Current taint rules include SQL injection, command injection, path traversal, SSRF, XSS, log injection, and SMTP injection.
+Current taint rules include SQL injection, command injection, path traversal, SSRF, XSS, log injection, SMTP injection, server-side template injection, unsafe deserialization, and open redirect.
#### Steps
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/Makefile b/hack/tools/vendor/github.com/securego/gosec/v2/Makefile
index 6dd8c4c3a9e..f91529ca65c 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/Makefile
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/Makefile
@@ -33,6 +33,9 @@ install-govulncheck:
test: build-race fmt vet sec govulncheck
go run github.com/onsi/ginkgo/v2/ginkgo -- --ginkgo.v --ginkgo.fail-fast
+test-nocache: build-race fmt vet sec govulncheck
+ go test -count=1 -v ./...
+
fmt:
@echo "FORMATTING"
@FORMATTED=`$(GO) fmt ./...`
@@ -99,4 +102,4 @@ tlsconfig:
perf-diff:
./perf-diff.sh
-.PHONY: test build clean release image image-push tlsconfig perf-diff
+.PHONY: test test-nocache build clean release image image-push tlsconfig perf-diff
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/README.md b/hack/tools/vendor/github.com/securego/gosec/v2/README.md
index 6f6d27d1205..283d8533ba2 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/README.md
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/README.md
@@ -1,7 +1,8 @@
# gosec - Go Security Checker
-Inspects source code for security problems by scanning the Go AST and SSA code representation.
+Inspects source code for security problems by scanning the Go AST
+and SSA code representation.
@@ -14,20 +15,23 @@ Inspects source code for security problems by scanning the Go AST and SSA code r
- [Selecting rules](#selecting-rules)
- [Output formats](#output-formats)
-> ⚠️ Container image migration notice: `gosec` images was migrated from Docker Hub to `ghcr.io/securego/gosec`.
-> Starting with release `v2.24.7` the image is no longer published in Docker Hub.
-
## Features
-- **Pattern-based rules** for detecting common security issues in Go code
-- **SSA-based analyzers** for type conversions, slice bounds, and crypto issues
-- **Taint analysis** for tracking data flow from user input to dangerous functions (SQL injection, command injection, path traversal, SSRF, XSS, log injection)
+- **Pattern-based rules** for detecting common security issues
+ in Go code
+- **SSA-based analyzers** for type conversions, slice bounds,
+ and crypto issues
+- **Taint analysis** for tracking data flow from user input to
+ dangerous functions (SQL injection, command injection, path
+ traversal, SSRF, XSS, log injection, SMTP injection, SSTI,
+ unsafe deserialization, open redirect)
## License
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 [here](http://www.apache.org/licenses/LICENSE-2.0).
+You may obtain a copy of the License
+[here](http://www.apache.org/licenses/LICENSE-2.0).
## Project status
@@ -48,7 +52,8 @@ You may obtain a copy of the License [here](http://www.apache.org/licenses/LICEN
You can run `gosec` as a GitHub action as follows:
-Use the versioned tag with `@master` which is pinned to the latest stable release. This will provide a stable behavior.
+Use the versioned tag with `@master` which is pinned to the
+latest stable release. This will provide a stable behavior.
```yaml
name: Run Gosec
@@ -75,10 +80,16 @@ jobs:
#### Scanning Projects with Private Modules
-If your project imports private Go modules, you need to configure authentication so that `gosec` can fetch the dependencies. Set the following environment variables in your workflow:
+If your project imports private Go modules, you need to
+configure authentication so that `gosec` can fetch the
+dependencies. Set the following environment variables in
+your workflow:
-- `GOPRIVATE`: A comma-separated list of module path prefixes that should be considered private (e.g., `github.com/your-org/*`).
-- `GITHUB_AUTHENTICATION_TOKEN`: A GitHub token with read access to your private repositories.
+- `GOPRIVATE`: A comma-separated list of module path prefixes
+ that should be considered private
+ (e.g., `github.com/your-org/*`).
+- `GITHUB_AUTHENTICATION_TOKEN`: A GitHub token with read
+ access to your private repositories.
```yaml
name: Run Gosec
@@ -107,9 +118,13 @@ jobs:
### Integrating with code scanning
-You can [integrate third-party code analysis tools](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/integrating-with-code-scanning) with GitHub code scanning by uploading data as SARIF files.
+You can [integrate third-party code analysis tools](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/integrating-with-code-scanning)
+with GitHub code scanning by uploading data as SARIF files.
-The workflow shows an example of running the `gosec` as a step in a GitHub action workflow which outputs the `results.sarif` file. The workflow then uploads the `results.sarif` file to GitHub using the `upload-sarif` action.
+The workflow shows an example of running the `gosec` as a step
+in a GitHub action workflow which outputs the `results.sarif`
+file. The workflow then uploads the `results.sarif` file to
+GitHub using the `upload-sarif` action.
```yaml
name: "Security Scan"
@@ -143,7 +158,12 @@ jobs:
### Go Analysis
-The `goanalysis` package provides a [`golang.org/x/tools/go/analysis.Analyzer`](https://pkg.go.dev/golang.org/x/tools/go/analysis) for integration with tools that support the standard Go analysis interface, such as Bazel's [nogo](https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst) framework:
+The `goanalysis` package provides a
+[`golang.org/x/tools/go/analysis.Analyzer`](https://pkg.go.dev/golang.org/x/tools/go/analysis)
+for integration with tools that support the standard Go
+analysis interface, such as Bazel's
+[nogo](https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst)
+framework:
```starlark
nogo(
@@ -185,34 +205,48 @@ gosec -fmt sarif -out results.sarif ./...
## Usage
-Gosec can be configured to only run a subset of rules, to exclude certain file
-paths, and produce reports in different formats. By default all rules will be
-run against the supplied input files. To recursively scan from the current
-directory you can supply `./...` as the input argument.
+Gosec can be configured to only run a subset of rules, to
+exclude certain file paths, and produce reports in different
+formats. By default all rules will be run against the supplied
+input files. To recursively scan from the current directory you
+can supply `./...` as the input argument.
### Available rules
gosec includes rules across these categories:
-- `G1xx`: general secure coding issues (for example hardcoded credentials, unsafe usage, HTTP hardening)
-- `G2xx`: injection risks in query/template/command construction
-- `G3xx`: file and path handling risks (permissions, traversal, temp files, archive extraction)
+- `G1xx`: general secure coding issues (for example hardcoded
+ credentials, unsafe usage, HTTP hardening, cookie security)
+- `G2xx`: injection risks in query/template/command
+ construction
+- `G3xx`: file and path handling risks (permissions, traversal,
+ temp files, archive extraction)
- `G4xx`: crypto and TLS weaknesses
- `G5xx`: blocklisted imports
-- `G6xx`: Go-specific correctness/security checks (for example range aliasing and slice bounds)
-- `G7xx`: taint analysis rules (SQL injection, command injection, path traversal, SSRF, XSS, log and SMTP injection)
+- `G6xx`: Go-specific correctness/security checks (for example
+ range aliasing and slice bounds)
+- `G7xx`: taint analysis rules (SQL injection, command
+ injection, path traversal, SSRF, XSS, log, SMTP injection,
+ SSTI, unsafe deserialization, and open redirect)
-For the full list, rule descriptions, and per-rule configuration, see [RULES.md](RULES.md).
+For the full list, rule descriptions, and per-rule
+configuration, see [RULES.md](RULES.md).
### Retired rules
-- G105: Audit the use of math/big.Int.Exp - [CVE is fixed](https://github.com/golang/go/issues/15184)
-- G307: Deferring a method which returns an error - causing more inconvenience than fixing a security issue, despite the details from this [blog post](https://www.joeshaw.org/dont-defer-close-on-writable-files/)
+- G105: Audit the use of math/big.Int.Exp -
+ [CVE is fixed](https://github.com/golang/go/issues/15184)
+- G307: Deferring a method which returns an error - causing
+ more inconvenience than fixing a security issue, despite the
+ details from this
+ [blog post](https://www.joeshaw.org/dont-defer-close-on-writable-files/)
### Selecting rules
-By default, gosec will run all rules against the supplied file paths. It is however possible to select a subset of rules to run via the `-include=` flag,
-or to specify a set of rules to explicitly exclude using the `-exclude=` flag.
+By default, gosec will run all rules against the supplied file
+paths. It is however possible to select a subset of rules to
+run via the `-include=` flag, or to specify a set of rules to
+explicitly exclude using the `-exclude=` flag.
```bash
# Run a specific set of rules
@@ -224,11 +258,16 @@ $ gosec -exclude=G303 ./...
### CWE Mapping
-Every issue detected by `gosec` is mapped to a [CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html) which describes in more generic terms the vulnerability. The exact mapping can be found [here](https://github.com/securego/gosec/blob/master/issue/issue.go#L50).
+Every issue detected by `gosec` is mapped to a
+[CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html)
+which describes in more generic terms the vulnerability. The
+exact mapping can be found
+[here](https://github.com/securego/gosec/blob/master/issue/issue.go#L50).
### Configuration
-A number of global settings can be provided in a configuration file as follows:
+A number of global settings can be provided in a configuration
+file as follows:
```JSON
{
@@ -239,8 +278,10 @@ A number of global settings can be provided in a configuration file as follows:
}
```
-- `nosec`: this setting will overwrite all `#nosec` directives defined throughout the code base
-- `audit`: runs in audit mode which enables addition checks that for normal code analysis might be too nosy
+- `nosec`: this setting will overwrite all `#nosec` directives
+ defined throughout the code base
+- `audit`: runs in audit mode which enables addition checks
+ that for normal code analysis might be too nosy
```bash
# Run with a global configuration file
@@ -249,9 +290,9 @@ $ gosec -conf config.json .
### Path-Based Rule Exclusions
-Large repositories with multiple components may need different security rules
-for different paths. Use `exclude-rules` to suppress specific rules for specific
-paths.
+Large repositories with multiple components may need different
+security rules for different paths. Use `exclude-rules` to
+suppress specific rules for specific paths.
**Configuration File:**
```json
@@ -283,22 +324,31 @@ gosec --exclude-rules="cmd/.*:G204,G304;test/.*:G101" ./...
| Field | Type | Description |
|-------|------|-------------|
-| `path` | string (regex) | Regular expression matched against file paths |
-| `rules` | []string | Rule IDs to exclude. Use `*` to exclude all rules |
+| `path` | string (regex) | Regex matched against file paths |
+| `rules` | []string | Rule IDs to exclude. `*` for all |
#### Rule Configuration
-Some rules accept configuration flags as well; these flags are documented in [RULES.md](https://github.com/securego/gosec/blob/master/RULES.md).
+Some rules accept configuration flags as well; these flags are
+documented in
+[RULES.md](https://github.com/securego/gosec/blob/master/RULES.md).
#### Go version
-Some rules require a specific Go version which is retrieved from the Go module file present in the project. If this version cannot be found, it will fallback to Go runtime version.
+Some rules require a specific Go version which is retrieved
+from the Go module file present in the project. If this version
+cannot be found, it will fallback to Go runtime version.
-The Go module version is parsed using the `go list` command which in some cases might lead to performance degradation. In this situation, the go module version can be easily provided by setting the environment variable `GOSECGOVERSION=go1.21.1`.
+The Go module version is parsed using the `go list` command
+which in some cases might lead to performance degradation. In
+this situation, the go module version can be easily provided by
+setting the environment variable
+`GOSECGOVERSION=go1.21.1`.
### Dependencies
-gosec loads packages using Go modules. In most projects, dependencies are resolved automatically during scanning.
+gosec loads packages using Go modules. In most projects,
+dependencies are resolved automatically during scanning.
If dependencies are missing, run:
@@ -309,9 +359,11 @@ go mod download
### Excluding test files and folders
-gosec will ignore test files across all packages and any dependencies in your vendor directory.
+gosec will ignore test files across all packages and any
+dependencies in your vendor directory.
-The scanning of test files can be enabled with the following flag:
+The scanning of test files can be enabled with the following
+flag:
```bash
gosec -tests ./...
@@ -325,7 +377,8 @@ Also additional folders can be excluded as follows:
### Excluding generated files
-gosec can ignore generated go files with default generated code comment.
+gosec can ignore generated go files with default generated
+code comment.
```
// Code generated by some generator DO NOT EDIT.
@@ -337,36 +390,56 @@ gosec -exclude-generated ./...
### Auto fixing vulnerabilities
-gosec can suggest fixes based on AI recommendation. It will call an AI API to receive a suggestion for a security finding.
-
-You can enable this feature by providing the following command line arguments:
-
-- `ai-api-provider`: the name of the AI API provider. Supported providers:
- - **Gemini**: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`, `gemini-2.0-flash`, `gemini-2.0-flash-lite` (default)
- - **Claude**: `claude-sonnet-4-0` (default), `claude-opus-4-0`, `claude-opus-4-1`, `claude-sonnet-3-7`
- - **OpenAI**: `gpt-4o` (default), `gpt-4o-mini`
- - **Custom OpenAI-compatible**: Any custom model name (requires `ai-base-url`)
-- `ai-api-key` or set the environment variable `GOSEC_AI_API_KEY`: the key to access the AI API
- - For Gemini, you can create an API key following [these instructions](https://ai.google.dev/gemini-api/docs/api-key)
- - For Claude, get your API key from [Anthropic Console](https://console.anthropic.com/)
- - For OpenAI, get your API key from [OpenAI Platform](https://platform.openai.com/api-keys)
-- `ai-base-url`: (optional) custom base URL for OpenAI-compatible APIs (e.g., Azure OpenAI, LocalAI, Ollama)
-- `ai-skip-ssl`: (optional) skip SSL certificate verification for AI API (useful for self-signed certificates)
+gosec can suggest fixes based on AI recommendation. It will
+call an AI API to receive a suggestion for a security finding.
+
+You can enable this feature by providing the following command
+line arguments:
+
+- `ai-api-provider`: the name of the AI API provider.
+ Supported providers:
+ - **Gemini**: `gemini-3-pro-preview` (default),
+ `gemini-2.5-pro`, `gemini-2.5-flash`,
+ `gemini-2.5-flash-lite`
+ - **Claude**: `claude-sonnet-4-6` (default),
+ `claude-opus-4-7`, `claude-opus-4-6`,
+ `claude-sonnet-4-5`, `claude-opus-4-5`,
+ `claude-haiku-4-5`
+ - **OpenAI**: `gpt-5.4` (default), `gpt-5.4-mini`,
+ `gpt-5.4-nano`
+ - **Custom OpenAI-compatible**: Any custom model name
+ (requires `ai-base-url`)
+- `ai-api-key` or set the environment variable
+ `GOSEC_AI_API_KEY`: the key to access the AI API
+ - For Gemini, you can create an API key following
+ [these instructions](https://ai.google.dev/gemini-api/docs/api-key)
+ - For Claude, get your API key from
+ [Anthropic Console](https://console.anthropic.com/)
+ - For OpenAI, get your API key from
+ [OpenAI Platform](https://platform.openai.com/api-keys)
+- `ai-base-url`: (optional) custom base URL for
+ OpenAI-compatible APIs (e.g., Azure OpenAI, LocalAI,
+ Ollama)
+- `ai-skip-ssl`: (optional) skip SSL certificate verification
+ for AI API (useful for self-signed certificates)
**Examples:**
```bash
# Using Gemini
-gosec -ai-api-provider="gemini-2.0-flash" -ai-api-key="your_key" ./...
+gosec -ai-api-provider="gemini-3-pro-preview" \
+ -ai-api-key="your_key" ./...
# Using Claude
-gosec -ai-api-provider="claude-sonnet-4-0" -ai-api-key="your_key" ./...
+gosec -ai-api-provider="claude-sonnet-4-6" \
+ -ai-api-key="your_key" ./...
# Using OpenAI
-gosec -ai-api-provider="gpt-4o" -ai-api-key="your_key" ./...
+gosec -ai-api-provider="gpt-5.4" \
+ -ai-api-key="your_key" ./...
# Using Azure OpenAI
-gosec -ai-api-provider="gpt-4o" \
+gosec -ai-api-provider="gpt-5.4" \
-ai-api-key="your_azure_key" \
-ai-base-url="https://your-resource.openai.azure.com/openai/deployments/your-deployment" \
./...
@@ -386,13 +459,16 @@ gosec -ai-api-provider="custom-model" \
### Annotating code
-As with all automated detection tools, there will be cases of false positives.
-In cases where gosec reports a failure that has been manually verified as being safe,
-it is possible to annotate the code with a comment that starts with `#nosec`.
+As with all automated detection tools, there will be cases of
+false positives. In cases where gosec reports a failure that
+has been manually verified as being safe, it is possible to
+annotate the code with a comment that starts with `#nosec`.
-The `#nosec` comment should have the format `#nosec [RuleList] [- Justification]`.
+The `#nosec` comment should have the format
+`#nosec [RuleList] [- Justification]`.
-The `#nosec` comment needs to be placed on the line where the warning is reported.
+The `#nosec` comment needs to be placed on the line where the
+warning is reported.
```go
func main() {
@@ -410,24 +486,29 @@ func main() {
}
```
-When a specific false positive has been identified and verified as safe, you may
-wish to suppress only that single rule (or a specific set of rules) within a section of code,
-while continuing to scan for other problems. To do this, you can list the rule(s) to be suppressed within
-the `#nosec` annotation, e.g: `/* #nosec G401 */` or `//#nosec G201 G202 G203`
+When a specific false positive has been identified and verified
+as safe, you may wish to suppress only that single rule (or a
+specific set of rules) within a section of code, while
+continuing to scan for other problems. To do this, you can list
+the rule(s) to be suppressed within the `#nosec` annotation,
+e.g: `/* #nosec G401 */` or `//#nosec G201 G202 G203`
-You could put the description or justification text for the annotation. The
-justification should be after the rule(s) to suppress and start with two or
-more dashes, e.g: `//#nosec G101 G102 -- This is a false positive`
+You could put the description or justification text for the
+annotation. The justification should be after the rule(s) to
+suppress and start with two or more dashes,
+e.g: `//#nosec G101 G102 -- This is a false positive`
-Alternatively, gosec also supports the `//gosec:disable` directive, which functions similar to `#nosec`:
+Alternatively, gosec also supports the `//gosec:disable`
+directive, which functions similar to `#nosec`:
```go
//gosec:disable G101 -- This is a false positive
```
-In some cases you may also want to revisit places where `#nosec` or `//gosec:disable` annotations
-have been used. To run the scanner and ignore any `#nosec` annotations you
-can do the following:
+In some cases you may also want to revisit places where
+`#nosec` or `//gosec:disable` annotations have been used. To
+run the scanner and ignore any `#nosec` annotations you can do
+the following:
```bash
gosec -nosec=true ./...
@@ -435,26 +516,31 @@ gosec -nosec=true ./...
### Tracking suppressions
-As described above, we could suppress violations externally (using `-include`/
-`-exclude`) or inline (using `#nosec` annotations). Suppression metadata can be emitted for auditing.
+As described above, we could suppress violations externally
+(using `-include`/`-exclude`) or inline (using `#nosec`
+annotations). Suppression metadata can be emitted for auditing.
Enable suppression tracking with `-track-suppressions`:
```bash
-gosec -track-suppressions -exclude=G101 -fmt=sarif -out=results.sarif ./...
+gosec -track-suppressions -exclude=G101 \
+ -fmt=sarif -out=results.sarif ./...
```
-- For external suppressions, gosec records suppression info where `kind` is
-`external` and `justification` is `Globally suppressed.`.
-- For inline suppressions, gosec records suppression info where `kind` is
-`inSource` and `justification` is the text after two or more dashes in the
-comment.
+- For external suppressions, gosec records suppression info
+ where `kind` is `external` and `justification` is
+ `Globally suppressed.`.
+- For inline suppressions, gosec records suppression info
+ where `kind` is `inSource` and `justification` is the text
+ after two or more dashes in the comment.
-**Note:** Only SARIF and JSON formats support tracking suppressions.
+**Note:** Only SARIF and JSON formats support tracking
+suppressions.
### Build tags
-gosec is able to pass your [Go build tags](https://pkg.go.dev/go/build/) to the analyzer.
+gosec is able to pass your
+[Go build tags](https://pkg.go.dev/go/build/) to the analyzer.
They can be provided as a comma separated list as follows:
```bash
@@ -463,9 +549,12 @@ gosec -tags debug,ignore ./...
### Output formats
-gosec supports `text`, `json`, `yaml`, `csv`, `junit-xml`, `html`, `sonarqube`, `golint`, and `sarif`. By default,
-results will be reported to stdout, but can also be written to an output
-file. The output format is controlled by the `-fmt` flag, and the output file is controlled by the `-out` flag as follows:
+gosec supports `text`, `json`, `yaml`, `csv`, `junit-xml`,
+`html`, `sonarqube`, `golint`, and `sarif`. By default,
+results will be reported to stdout, but can also be written to
+an output file. The output format is controlled by the `-fmt`
+flag, and the output file is controlled by the `-out` flag as
+follows:
```bash
# Write output in json format to results.json
@@ -473,16 +562,22 @@ $ gosec -fmt=json -out=results.json *.go
```
Use `-stdout` to print results while also writing `-out`.
-Use `-verbose` to override stdout format while preserving the file format.
+Use `-verbose` to override stdout format while preserving the
+file format.
```bash
# Write output in json format to results.json as well as stdout
$ gosec -fmt=json -out=results.json -stdout *.go
-# Overrides the output format to 'text' when stdout the results, while writing it to results.json
+# Overrides the output format to 'text' when stdout the results,
+# while writing it to results.json
$ gosec -fmt=json -out=results.json -stdout -verbose=text *.go
```
-**Note:** gosec generates the [generic issue import format](https://docs.sonarqube.org/latest/analysis/generic-issue/) for SonarQube, and a report has to be imported into SonarQube using `sonar.externalIssuesReportPaths=path/to/gosec-report.json`.
+**Note:** gosec generates the
+[generic issue import format](https://docs.sonarqube.org/latest/analysis/generic-issue/)
+for SonarQube, and a report has to be imported into SonarQube
+using
+`sonar.externalIssuesReportPaths=path/to/gosec-report.json`.
## Common usage patterns
@@ -505,7 +600,8 @@ gosec -tests ./...
## Development
-Development documentation was moved to [DEVELOPMENT.md](DEVELOPMENT.md).
+Development documentation was moved to
+[DEVELOPMENT.md](DEVELOPMENT.md).
## Who is using gosec?
@@ -513,6 +609,7 @@ This is a [list](USERS.md) with some of the gosec's users.
## Sponsors
-Support this project by becoming a sponsor. Your logo will show up here with a link to your website
+Support this project by becoming a sponsor. Your logo will
+show up here with a link to your website
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/RULES.md b/hack/tools/vendor/github.com/securego/gosec/v2/RULES.md
index 21994ce1081..badc3b189f7 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/RULES.md
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/RULES.md
@@ -16,6 +16,7 @@
- [G104](#g104)
- [G111](#g111)
- [G117](#g117)
+ - [G118](#g118)
- [G301, G302, G306, G307](#g301-g302-g306-g307)
## Rules List
@@ -38,12 +39,13 @@
- G115 — Type conversion which leads to integer overflow (**SSA**)
- G116 — Detect Trojan Source attacks using bidirectional Unicode characters (**AST**)
- [G117](#g117) — Potential exposure of secrets via JSON/YAML/XML/TOML marshaling (**AST**)
-- G118 — Context propagation failure leading to goroutine/resource leaks (**SSA**)
+- [G118](#g118) — Context propagation failure leading to goroutine/resource leaks (**SSA**)
- G119 — Unsafe redirect policy may propagate sensitive headers (**SSA**)
-- G120 — Unbounded form parsing in HTTP handlers can cause memory exhaustion (**SSA**)
+- G120 — Unbounded `ParseMultipartForm` in HTTP handlers can cause memory exhaustion (**Taint**)
- G121 — Unsafe CrossOriginProtection bypass patterns (**SSA**)
- G122 — Filesystem TOCTOU race risk in `filepath.Walk/WalkDir` callbacks (**SSA**)
- G123 — TLS resumption may bypass `VerifyPeerCertificate` when `VerifyConnection` is unset (**SSA**)
+- G124 — Insecure HTTP cookie configuration missing Secure, HttpOnly, or SameSite attributes (**SSA**)
### G2xx: Injection Patterns
@@ -97,6 +99,9 @@
- G705 — XSS via taint analysis (**Taint**)
- G706 — Log injection via taint analysis (**Taint**)
- G707 — SMTP command/header injection via taint analysis (**Taint**)
+- G708 — Server-side template injection via `text/template` (**Taint**)
+- G709 — Unsafe deserialization of untrusted data (**Taint**)
+- G710 — Open redirect via taint analysis (**Taint**)
_Note: Implementation types used in this document:_
- **AST**: rule implemented in `rules/` and evaluated on AST patterns
@@ -170,6 +175,106 @@ This replaces the default pattern.
}
```
+### G118
+
+`G118` detects three classes of context-propagation failure using SSA-level analysis:
+
+**1. Lost cancel function (CWE-400)**
+
+Reports when a `context.WithCancel`, `context.WithTimeout`, or `context.WithDeadline` call
+returns a cancel function that is never called, potentially leaking resources.
+
+```go
+// Flagged: cancel never called
+func work(ctx context.Context) {
+ child, _ := context.WithTimeout(ctx, time.Second)
+ _ = child
+}
+
+// Safe: cancel deferred
+func work(ctx context.Context) {
+ child, cancel := context.WithTimeout(ctx, time.Second)
+ defer cancel()
+ _ = child
+}
+```
+
+The following patterns are all recognised as *safe* (cancel is considered called):
+
+| Pattern | Description |
+|---|---|
+| `defer cancel()` | Direct deferred call |
+| `defer func() { cancel() }()` | Cancel in a deferred closure |
+| `cancelCopy := cancel; defer cancelCopy()` | Alias via variable |
+| `return ctx, cancel` | Cancel returned to caller (responsibility transferred) |
+| `s.cancelFn = cancel` + method `s.cancelFn()` | Stored in struct field, called via receiver method |
+| `s.cancel = cancel; defer s.cancel()` | Stored in struct field, deferred in same function |
+| `s.cancel = cancel; defer func() { s.cancel() }()` | Stored in struct field, called in closure |
+| Struct containing field is returned | Caller inherits cancel responsibility |
+| `var cancel CancelFunc` in `init()` + `cancel()` in another function | Package-level variable assigned in init, called in any function (e.g., signal handlers) |
+
+Example of package-level variable pattern:
+
+```go
+// Safe: cancel stored in package-level variable and called in signal handler
+var cancel context.CancelFunc
+
+func init() {
+ ctx, c := context.WithCancel(context.Background())
+ cancel = c
+}
+
+func handleShutdown() {
+ cancel() // Called from signal handler
+}
+```
+
+**2. Goroutine uses `context.Background`/`TODO` when request context is available (CWE-400)**
+
+Reports when a goroutine spawned inside an HTTP handler or a function accepting a
+`context.Context` / `*http.Request` uses `context.Background()` or `context.TODO()`
+instead of the request-scoped context.
+
+```go
+// Flagged
+func handler(w http.ResponseWriter, r *http.Request) {
+ go func() {
+ ctx := context.Background() // ignores request context
+ doWork(ctx)
+ }()
+}
+```
+
+**3. Long-running loop without `ctx.Done()` guard (CWE-400)**
+
+Reports an infinite loop that performs blocking I/O (e.g. `http.Get`, `db.Query`,
+`time.Sleep`, interface methods such as `Read`/`Write`) but never checks `ctx.Done()`,
+making the loop impossible to cancel.
+
+```go
+// Flagged
+func poll(ctx context.Context) {
+ for {
+ http.Get("https://example.com") // blocks, no cancellation path
+ time.Sleep(time.Second)
+ }
+}
+
+// Safe
+func poll(ctx context.Context) {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-time.After(time.Second):
+ http.Get("https://example.com")
+ }
+ }
+}
+```
+
+Loops with an external exit path (e.g. a `break` or bounded `for i < n`) are not flagged.
+
### G301, G302, G306, G307
File and directory permission rules can be configured with stricter maximum permissions:
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/action.yml b/hack/tools/vendor/github.com/securego/gosec/v2/action.yml
index dce5779453e..caedf343e5a 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/action.yml
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/action.yml
@@ -10,7 +10,7 @@ inputs:
runs:
using: "docker"
- image: "docker://ghcr.io/securego/gosec:2.24.7"
+ image: "docker://ghcr.io/securego/gosec:2.25.0"
args:
- ${{ inputs.args }}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzer.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzer.go
index ed03efc6959..c0eb3b1d781 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzer.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzer.go
@@ -711,6 +711,9 @@ func (gosec *Analyzer) buildSSA(pkg *packages.Package) (*buildssa.SSA, error) {
if pkg.TypesInfo == nil {
return nil, fmt.Errorf("%w: %s", ErrNoPackageTypeInfo, pkg.Name)
}
+ if pkg.IllTyped {
+ return nil, fmt.Errorf("package %s has type errors, skipping SSA analysis", pkg.Name)
+ }
pass := &analysis.Pass{
Fset: pkg.Fset,
Files: pkg.Syntax,
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go
index 658b30a1621..0a541e908f3 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go
@@ -81,6 +81,34 @@ var (
Severity: "HIGH",
CWE: "CWE-93",
}
+
+ SSTIRule = taint.RuleInfo{
+ ID: "G708",
+ Description: "Server-side template injection via text/template",
+ Severity: "CRITICAL",
+ CWE: "CWE-94",
+ }
+
+ UnsafeDeserializationRule = taint.RuleInfo{
+ ID: "G709",
+ Description: "Unsafe deserialization of untrusted data",
+ Severity: "HIGH",
+ CWE: "CWE-502",
+ }
+
+ OpenRedirectRule = taint.RuleInfo{
+ ID: "G710",
+ Description: "Open redirect: user-controlled URL flows into http.Redirect",
+ Severity: "MEDIUM",
+ CWE: "CWE-601",
+ }
+
+ FormParsingLimitRule = taint.RuleInfo{
+ ID: "G120",
+ Description: "Unbounded multipart form parsing can cause memory exhaustion",
+ Severity: "MEDIUM",
+ CWE: "CWE-400",
+ }
)
// AnalyzerList contains a mapping of analyzer ID's to analyzer definitions and a mapping
@@ -128,6 +156,7 @@ var defaultAnalyzers = []AnalyzerDefinition{
{"G121", "Unsafe CrossOriginProtection bypass patterns", newCORSBypassPatternAnalyzer},
{"G122", "Filesystem TOCTOU race risk in filepath.Walk/WalkDir callbacks", newWalkSymlinkRaceAnalyzer},
{"G123", "TLS resumption may bypass VerifyPeerCertificate when VerifyConnection is unset", newTLSResumptionVerifyPeerAnalyzer},
+ {"G124", "Insecure HTTP cookie configuration missing Secure, HttpOnly, or SameSite attributes", newInsecureCookieAnalyzer},
{"G602", "Possible slice bounds out of range", newSliceBoundsAnalyzer},
{"G407", "Use of hardcoded IV/nonce for encryption", newHardCodedNonce},
{"G408", "Stateful misuse of ssh.PublicKeyCallback leading to auth bypass", newSSHCallbackAnalyzer},
@@ -138,6 +167,9 @@ var defaultAnalyzers = []AnalyzerDefinition{
{"G705", "XSS via taint analysis", newXSSAnalyzer},
{"G706", "Log injection via taint analysis", newLogInjectionAnalyzer},
{"G707", "SMTP command/header injection via taint analysis", newSMTPInjectionAnalyzer},
+ {"G708", "Server-side template injection via taint analysis", newSSTIAnalyzer},
+ {"G709", "Unsafe deserialization of untrusted data via taint analysis", newUnsafeDeserializationAnalyzer},
+ {"G710", "Open redirect via taint analysis", newOpenRedirectAnalyzer},
}
// Generate the list of analyzers to use
@@ -172,6 +204,10 @@ func DefaultTaintAnalyzers() []*analysis.Analyzer {
xssConfig := XSS()
logConfig := LogInjection()
smtpConfig := SMTPInjection()
+ sstiConfig := SSTI()
+ deserConfig := UnsafeDeserialization()
+ formConfig := FormParsingLimits()
+ openRedirectConfig := OpenRedirect()
return []*analysis.Analyzer{
taint.NewGosecAnalyzer(&SQLInjectionRule, &sqlConfig),
@@ -181,5 +217,9 @@ func DefaultTaintAnalyzers() []*analysis.Analyzer {
taint.NewGosecAnalyzer(&XSSRule, &xssConfig),
taint.NewGosecAnalyzer(&LogInjectionRule, &logConfig),
taint.NewGosecAnalyzer(&SMTPInjectionRule, &smtpConfig),
+ taint.NewGosecAnalyzer(&SSTIRule, &sstiConfig),
+ taint.NewGosecAnalyzer(&UnsafeDeserializationRule, &deserConfig),
+ taint.NewGosecAnalyzer(&FormParsingLimitRule, &formConfig),
+ taint.NewGosecAnalyzer(&OpenRedirectRule, &openRedirectConfig),
}
}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go
index 0136d660d4c..178d41169cd 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go
@@ -710,6 +710,23 @@ func isCancelCalled(cancelValue ssa.Value, allFuncs []*ssa.Function) bool {
if isStructFieldReturnedFromFunc(fa) {
return true
}
+ // Check if any function (including closures capturing the
+ // struct) loads and calls the same field. This handles
+ // post-construction storage such as:
+ // s.cancel = cancel; defer s.cancel()
+ // s.cancel = cancel; defer func() { s.cancel() }()
+ if isFieldCalledInAnyFunc(fa, allFuncs) {
+ return true
+ }
+ }
+ // Check if storing to a package-level global variable.
+ // When cancel is stored to a global (e.g., in init()), we need
+ // to search all functions in the package for loads of that global
+ // followed by a call.
+ if global, ok := r.Addr.(*ssa.Global); ok {
+ if isGlobalCalledInAnyFunc(global, allFuncs) {
+ return true
+ }
}
queue = append(queue, r.Addr)
case *ssa.UnOp:
@@ -783,6 +800,163 @@ func isStructFieldReturnedFromFunc(fa *ssa.FieldAddr) bool {
return false
}
+// isFieldCalledInAnyFunc checks whether a cancel function stored into a struct
+// field is subsequently called in any function (including closures) that
+// accesses the same field by struct pointer type and field index. This covers
+// post-construction storage patterns not handled by isCancelCalledViaStructField:
+//
+// s.cancel = cancel; defer s.cancel()
+// s.cancel = cancel; defer func() { s.cancel() }()
+func isFieldCalledInAnyFunc(fa *ssa.FieldAddr, allFuncs []*ssa.Function) bool {
+ structPtrType := fa.X.Type()
+ fieldIdx := fa.Field
+
+ for _, fn := range allFuncs {
+ if fn == nil {
+ continue
+ }
+ for _, block := range fn.Blocks {
+ for _, instr := range block.Instrs {
+ otherFA, ok := instr.(*ssa.FieldAddr)
+ if !ok || otherFA.Field != fieldIdx {
+ continue
+ }
+ if !types.Identical(otherFA.X.Type(), structPtrType) {
+ continue
+ }
+ if isFieldValueCalled(otherFA) {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+// isGlobalCalledInAnyFunc checks whether a cancel function stored into a
+// package-level global variable is subsequently called in any function
+// (including init(), main(), signal handlers, etc.). This handles patterns
+// like:
+//
+// var cancel context.CancelFunc
+// func init() { _, cancel = context.WithCancel(ctx) }
+// func shutdown() { cancel() }
+func isGlobalCalledInAnyFunc(global *ssa.Global, allFuncs []*ssa.Function) bool {
+ if global == nil {
+ return false
+ }
+
+ // Iterate through all functions in the package to find loads from this global
+ for _, fn := range allFuncs {
+ if fn == nil || fn.Blocks == nil {
+ continue
+ }
+
+ for _, block := range fn.Blocks {
+ for _, instr := range block.Instrs {
+ // Look for UnOp (dereference/load) from the global
+ unop, ok := instr.(*ssa.UnOp)
+ if !ok || unop.Op != token.MUL {
+ continue
+ }
+
+ // Check if this load is from our global
+ if unop.X != global {
+ continue
+ }
+
+ // Check if the loaded value is eventually called
+ if isValueCalled(unop) {
+ return true
+ }
+ }
+ }
+ }
+
+ return false
+}
+
+// isValueCalled checks if a value (typically a loaded function pointer) is
+// eventually used as a callee. This performs a BFS through value referrers
+// to find calls, handling phi nodes, stores/loads, type conversions, and closures.
+func isValueCalled(value ssa.Value) bool {
+ if value == nil {
+ return false
+ }
+
+ refs := value.Referrers()
+ if refs == nil {
+ return false
+ }
+
+ queue := []ssa.Value{value}
+ visited := make(map[ssa.Value]bool)
+
+ for len(queue) > 0 {
+ cur := queue[0]
+ queue = queue[1:]
+
+ if cur == nil || visited[cur] {
+ continue
+ }
+ visited[cur] = true
+
+ curRefs := cur.Referrers()
+ if curRefs == nil {
+ continue
+ }
+
+ for _, ref := range *curRefs {
+ switch r := ref.(type) {
+ case ssa.CallInstruction:
+ // Check if cur is used as the callee or an argument
+ if isUsedInCall(r.Common(), cur) {
+ return true
+ }
+ case *ssa.Phi:
+ // Value flows through phi node - continue tracking
+ queue = append(queue, r)
+ case *ssa.Store:
+ // Stored then loaded elsewhere - follow the address
+ if r.Val == cur {
+ queue = append(queue, r.Addr)
+ }
+ case *ssa.UnOp:
+ // Dereference or other operation - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.ChangeType:
+ // Type conversion - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.Convert:
+ // Type conversion - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.MakeInterface:
+ // Wrapped in interface - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.MakeClosure:
+ // Captured in closure - follow into closure body
+ if fn, ok := r.Fn.(*ssa.Function); ok {
+ for i, binding := range r.Bindings {
+ if binding == cur && i < len(fn.FreeVars) {
+ queue = append(queue, fn.FreeVars[i])
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false
+}
+
// isCancelCalledViaStructField checks whether a cancel function stored into a
// struct field (e.g., job.cancelFn = cancel) is subsequently called in any other
// method of the same receiver type (e.g., job.Close() calls job.cancelFn()).
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go
index 23a350b477c..2c3c7d86986 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go
@@ -79,6 +79,13 @@ func runConversionOverflow(pass *analysis.Pass) (any, error) {
continue
}
+ // Skip conversions between platform-word-sized
+ // types (e.g. uintptr -> int) since they never
+ // truncate bits.
+ if isSameWidthPlatformConversion(instr.X.Type(), instr.Type()) {
+ continue
+ }
+
if hasOverflow(srcInfo, dstInfo) {
if state.isSafeConversion(instr, dstInfo) {
continue
@@ -140,6 +147,28 @@ func hasOverflow(srcInfo, dstInfo IntTypeInfo) bool {
return srcInfo.Min < dstInfo.Min || srcInfo.Max > dstInfo.Max
}
+// isSameWidthPlatformConversion returns true when both the source
+// and destination are platform-word-sized integer types (e.g.
+// uintptr -> int). These conversions never truncate bits because
+// Go guarantees both types have the same width on every platform.
+func isSameWidthPlatformConversion(src, dst types.Type) bool {
+ srcBasic, _ := src.Underlying().(*types.Basic)
+ dstBasic, _ := dst.Underlying().(*types.Basic)
+ if srcBasic == nil || dstBasic == nil {
+ return false
+ }
+ return isPlatformWordType(srcBasic.Kind()) &&
+ isPlatformWordType(dstBasic.Kind())
+}
+
+func isPlatformWordType(k types.BasicKind) bool {
+ switch k {
+ case types.Int, types.Uint, types.Uintptr:
+ return true
+ }
+ return false
+}
+
// hasRangeCheck determines if there is a valid range check for the given value that ensures safety.
func (s *overflowState) hasRangeCheck(v ssa.Value, dstInt IntTypeInfo, block *ssa.BasicBlock) bool {
// Clear visited map for new resolution
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/dependency_checker.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/dependency_checker.go
new file mode 100644
index 00000000000..2f800ab216d
--- /dev/null
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/dependency_checker.go
@@ -0,0 +1,116 @@
+// (c) Copyright gosec's authors
+//
+// 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 analyzers
+
+import "golang.org/x/tools/go/ssa"
+
+type dependencyKey struct {
+ value ssa.Value
+ target ssa.Value
+}
+
+type dependencyChecker struct {
+ memo map[dependencyKey]bool
+ visiting map[dependencyKey]struct{}
+}
+
+func newDependencyChecker() *dependencyChecker {
+ return &dependencyChecker{
+ memo: make(map[dependencyKey]bool),
+ visiting: make(map[dependencyKey]struct{}),
+ }
+}
+
+func (c *dependencyChecker) dependsOn(value ssa.Value, target ssa.Value) bool {
+ return c.dependsOnDepth(value, target, 0)
+}
+
+func (c *dependencyChecker) dependsOnDepth(value ssa.Value, target ssa.Value, depth int) bool {
+ if value == nil || target == nil || depth > MaxDepth {
+ return false
+ }
+ if value == target {
+ return true
+ }
+
+ key := dependencyKey{value: value, target: target}
+ if result, ok := c.memo[key]; ok {
+ return result
+ }
+ if _, ok := c.visiting[key]; ok {
+ return false
+ }
+
+ c.visiting[key] = struct{}{}
+ result := false
+
+ switch v := value.(type) {
+ case *ssa.ChangeType:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.MakeInterface:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.TypeAssert:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.UnOp:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.FieldAddr:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.Field:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.IndexAddr:
+ result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
+ case *ssa.Index:
+ result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
+ case *ssa.Slice:
+ if c.dependsOnDepth(v.X, target, depth+1) {
+ result = true
+ break
+ }
+ if v.Low != nil && c.dependsOnDepth(v.Low, target, depth+1) {
+ result = true
+ break
+ }
+ if v.High != nil && c.dependsOnDepth(v.High, target, depth+1) {
+ result = true
+ break
+ }
+ result = v.Max != nil && c.dependsOnDepth(v.Max, target, depth+1)
+ case *ssa.Extract:
+ result = c.dependsOnDepth(v.Tuple, target, depth+1)
+ case *ssa.Phi:
+ for _, edge := range v.Edges {
+ if c.dependsOnDepth(edge, target, depth+1) {
+ result = true
+ break
+ }
+ }
+ case *ssa.Call:
+ if v.Call.Value != nil && c.dependsOnDepth(v.Call.Value, target, depth+1) {
+ result = true
+ break
+ }
+ for _, arg := range v.Call.Args {
+ if c.dependsOnDepth(arg, target, depth+1) {
+ result = true
+ break
+ }
+ }
+ }
+
+ delete(c.visiting, key)
+ c.memo[key] = result
+
+ return result
+}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go
index 0c4723f0059..8b27d6d1e7e 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go
@@ -15,507 +15,38 @@
package analyzers
import (
- "go/token"
- "go/types"
-
"golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/passes/buildssa"
- "golang.org/x/tools/go/ssa"
- "github.com/securego/gosec/v2/internal/ssautil"
- "github.com/securego/gosec/v2/issue"
+ "github.com/securego/gosec/v2/taint"
)
-const msgUnboundedFormParsing = "Parsing form data without limiting request body size can allow memory exhaustion (use http.MaxBytesReader)"
-
-type dependencyKey struct {
- value ssa.Value
- target ssa.Value
-}
-
-type dependencyChecker struct {
- memo map[dependencyKey]bool
- visiting map[dependencyKey]struct{}
-}
-
-func newDependencyChecker() *dependencyChecker {
- return &dependencyChecker{
- memo: make(map[dependencyKey]bool),
- visiting: make(map[dependencyKey]struct{}),
- }
-}
-
-func (c *dependencyChecker) dependsOn(value ssa.Value, target ssa.Value) bool {
- return c.dependsOnDepth(value, target, 0)
-}
-
-func (c *dependencyChecker) dependsOnDepth(value ssa.Value, target ssa.Value, depth int) bool {
- if value == nil || target == nil || depth > MaxDepth {
- return false
- }
- if value == target {
- return true
- }
-
- key := dependencyKey{value: value, target: target}
- if result, ok := c.memo[key]; ok {
- return result
- }
- if _, ok := c.visiting[key]; ok {
- return false
- }
-
- c.visiting[key] = struct{}{}
- result := false
-
- switch v := value.(type) {
- case *ssa.ChangeType:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.MakeInterface:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.TypeAssert:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.UnOp:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.FieldAddr:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.Field:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.IndexAddr:
- result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
- case *ssa.Index:
- result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
- case *ssa.Slice:
- if c.dependsOnDepth(v.X, target, depth+1) {
- result = true
- break
- }
- if v.Low != nil && c.dependsOnDepth(v.Low, target, depth+1) {
- result = true
- break
- }
- if v.High != nil && c.dependsOnDepth(v.High, target, depth+1) {
- result = true
- break
- }
- result = v.Max != nil && c.dependsOnDepth(v.Max, target, depth+1)
- case *ssa.Extract:
- result = c.dependsOnDepth(v.Tuple, target, depth+1)
- case *ssa.Phi:
- for _, edge := range v.Edges {
- if c.dependsOnDepth(edge, target, depth+1) {
- result = true
- break
- }
- }
- case *ssa.Call:
- if v.Call.Value != nil && c.dependsOnDepth(v.Call.Value, target, depth+1) {
- result = true
- break
- }
- for _, arg := range v.Call.Args {
- if c.dependsOnDepth(arg, target, depth+1) {
- result = true
- break
- }
- }
+// FormParsingLimits returns a taint analysis configuration for detecting
+// unbounded multipart form parsing in HTTP handlers.
+//
+// Only ParseMultipartForm is flagged because ParseForm, FormValue, and
+// PostFormValue already enforce a built-in 10 MiB body limit in Go's
+// standard library (see net/http.Request.ParseForm documentation).
+func FormParsingLimits() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ {Package: "net/http", Name: "Request", Pointer: true},
+ },
+ Sinks: []taint.Sink{
+ // ParseMultipartForm reads the entire body into memory/disk with
+ // no automatic cap — the caller-supplied maxMemory only limits the
+ // in-memory portion while the total can be maxMemory + 10 MiB.
+ // Without http.MaxBytesReader the full body is consumed.
+ // CheckArgs: [0] checks only the receiver (*http.Request).
+ {Package: "net/http", Receiver: "Request", Method: "ParseMultipartForm", Pointer: true, CheckArgs: []int{0}},
+ },
+ Sanitizers: []taint.Sanitizer{},
}
-
- delete(c.visiting, key)
- c.memo[key] = result
-
- return result
}
func newFormParsingLimitAnalyzer(id string, description string) *analysis.Analyzer {
- return &analysis.Analyzer{
- Name: id,
- Doc: description,
- Run: runFormParsingLimitAnalysis,
- Requires: []*analysis.Analyzer{buildssa.Analyzer},
- }
-}
-
-func runFormParsingLimitAnalysis(pass *analysis.Pass) (any, error) {
- ssaResult, err := ssautil.GetSSAResult(pass)
- if err != nil {
- return nil, err
- }
-
- checker := newDependencyChecker()
- issuesByPos := make(map[token.Pos]*issue.Issue)
- handlerProtection := computeFormParsingHandlerProtection(ssaResult.SSA.SrcFuncs, checker)
-
- for _, fn := range collectAnalyzerFunctions(ssaResult.SSA.SrcFuncs) {
- requestParam, writerParam := findHandlerRequestAndWriterParams(fn)
- if requestParam == nil || writerParam == nil {
- continue
- }
-
- hasRequestBodyLimit := handlerProtection[fn]
- if hasRequestBodyLimit {
- continue
- }
-
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- callInstr, ok := instr.(ssa.CallInstruction)
- if !ok {
- continue
- }
- if !isRiskyFormParsingCall(callInstr, requestParam, checker) {
- continue
- }
- addRedirectIssue(issuesByPos, pass, instr.Pos(), msgUnboundedFormParsing, issue.Medium, issue.High)
- }
- }
- }
-
- if len(issuesByPos) == 0 {
- return nil, nil
- }
-
- issues := make([]*issue.Issue, 0, len(issuesByPos))
- for _, i := range issuesByPos {
- issues = append(issues, i)
- }
-
- return issues, nil
-}
-
-func computeFormParsingHandlerProtection(srcFuncs []*ssa.Function, checker *dependencyChecker) map[*ssa.Function]bool {
- protection := make(map[*ssa.Function]bool)
- allFuncs := collectAnalyzerFunctions(srcFuncs)
- for _, fn := range allFuncs {
- requestParam, writerParam := findHandlerRequestAndWriterParams(fn)
- if requestParam == nil || writerParam == nil {
- continue
- }
- if functionHasRequestBodyLimit(fn, requestParam, writerParam, checker) {
- protection[fn] = true
- continue
- }
- if isProtectedByWrapperCall(fn, allFuncs, checker) {
- protection[fn] = true
- }
- }
-
- return protection
-}
-
-func isProtectedByWrapperCall(handler *ssa.Function, allFuncs []*ssa.Function, checker *dependencyChecker) bool {
- for _, fn := range allFuncs {
- if fn == nil {
- continue
- }
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- callInstr, ok := instr.(ssa.CallInstruction)
- if !ok {
- continue
- }
- common := callInstr.Common()
- if common == nil {
- continue
- }
- wrapper := common.StaticCallee()
- if wrapper == nil {
- continue
- }
-
- for argIndex, arg := range common.Args {
- if !checker.dependsOn(arg, handler) {
- continue
- }
- if wrapperProtectsParamHandler(wrapper, argIndex, checker) {
- return true
- }
- }
- }
- }
- }
-
- return false
-}
-
-func wrapperProtectsParamHandler(wrapper *ssa.Function, paramIndex int, checker *dependencyChecker) bool {
- if wrapper == nil || paramIndex < 0 || paramIndex >= len(wrapper.Params) {
- return false
- }
- handlerParam := wrapper.Params[paramIndex]
-
- if wrapperDelegatesWithRequestLimit(wrapper, handlerParam, checker) {
- return true
- }
-
- for _, block := range wrapper.Blocks {
- for _, instr := range block.Instrs {
- makeClosure, ok := instr.(*ssa.MakeClosure)
- if !ok {
- continue
- }
- closureFn, ok := makeClosure.Fn.(*ssa.Function)
- if !ok || closureFn == nil {
- continue
- }
-
- requestParam, writerParam := findHandlerRequestAndWriterParams(closureFn)
- if requestParam == nil || writerParam == nil {
- continue
- }
- if !functionHasRequestBodyLimit(closureFn, requestParam, writerParam, checker) {
- continue
- }
-
- for bindingIndex, binding := range makeClosure.Bindings {
- if !bindingDependsOnValue(binding, handlerParam, checker) {
- continue
- }
- if closureDelegatesWithRequestLimit(closureFn, bindingIndex, requestParam, writerParam, checker) {
- return true
- }
- }
- }
- }
-
- return false
-}
-
-func bindingDependsOnValue(binding ssa.Value, target ssa.Value, checker *dependencyChecker) bool {
- if checker.dependsOn(binding, target) {
- return true
- }
-
- alloc, ok := binding.(*ssa.Alloc)
- if !ok {
- return false
- }
-
- for _, ref := range safeReferrers(alloc) {
- store, ok := ref.(*ssa.Store)
- if !ok {
- continue
- }
- if store.Addr != alloc {
- continue
- }
- if checker.dependsOn(store.Val, target) {
- return true
- }
- }
-
- return false
-}
-
-func wrapperDelegatesWithRequestLimit(wrapper *ssa.Function, handlerValue ssa.Value, checker *dependencyChecker) bool {
- requestParam, writerParam := findHandlerRequestAndWriterParams(wrapper)
- if requestParam == nil || writerParam == nil {
- return false
- }
- if !functionHasRequestBodyLimit(wrapper, requestParam, writerParam, checker) {
- return false
- }
- return hasServeHTTPDelegation(wrapper, handlerValue, writerParam, requestParam, checker)
-}
-
-func closureDelegatesWithRequestLimit(closure *ssa.Function, freeVarIndex int, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker) bool {
- if freeVarIndex < 0 || freeVarIndex >= len(closure.FreeVars) {
- return false
- }
- handlerValue := closure.FreeVars[freeVarIndex]
- return hasServeHTTPDelegation(closure, handlerValue, writerParam, requestParam, checker)
-}
-
-func hasServeHTTPDelegation(fn *ssa.Function, handlerValue ssa.Value, writerValue ssa.Value, requestValue ssa.Value, checker *dependencyChecker) bool {
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- call, ok := instr.(*ssa.Call)
- if !ok {
- continue
- }
- common := call.Common()
- if common == nil {
- continue
- }
-
- var (
- receiver ssa.Value
- writer ssa.Value
- request ssa.Value
- )
-
- if method := common.Method; method != nil && method.Name() == "ServeHTTP" {
- if len(common.Args) < 2 {
- continue
- }
- receiver = common.Value
- writer = common.Args[0]
- request = common.Args[1]
- } else {
- callee := common.StaticCallee()
- if callee == nil || callee.Name() != "ServeHTTP" || callee.Signature == nil || callee.Signature.Recv() == nil {
- continue
- }
- if len(common.Args) < 3 {
- continue
- }
- receiver = common.Args[0]
- writer = common.Args[1]
- request = common.Args[2]
- }
-
- if !checker.dependsOn(receiver, handlerValue) {
- continue
- }
- if !checker.dependsOn(writer, writerValue) {
- continue
- }
- if !checker.dependsOn(request, requestValue) {
- continue
- }
- return true
- }
- }
-
- return false
-}
-
-func findHandlerRequestAndWriterParams(fn *ssa.Function) (*ssa.Parameter, *ssa.Parameter) {
- if fn == nil {
- return nil, nil
- }
-
- var requestParam *ssa.Parameter
- var writerParam *ssa.Parameter
-
- for _, param := range fn.Params {
- if param == nil {
- continue
- }
- if requestParam == nil && isHTTPRequestPointerType(param.Type()) {
- requestParam = param
- continue
- }
- if writerParam == nil && isHTTPResponseWriterType(param.Type()) {
- writerParam = param
- }
- }
-
- return requestParam, writerParam
-}
-
-func isHTTPResponseWriterType(t types.Type) bool {
- named, ok := t.(*types.Named)
- if !ok {
- return false
- }
-
- obj := named.Obj()
- if obj == nil || obj.Name() != "ResponseWriter" {
- return false
- }
-
- pkg := obj.Pkg()
- return pkg != nil && pkg.Path() == "net/http"
-}
-
-func functionHasRequestBodyLimit(fn *ssa.Function, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker) bool {
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- store, ok := instr.(*ssa.Store)
- if !ok {
- continue
- }
- if isRequestBodyStoreFromMaxBytesReader(store, requestParam, writerParam, checker) {
- return true
- }
- }
- }
- return false
-}
-
-func isRequestBodyStoreFromMaxBytesReader(store *ssa.Store, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker) bool {
- fieldAddr, ok := store.Addr.(*ssa.FieldAddr)
- if !ok {
- return false
- }
-
- if !checker.dependsOn(fieldAddr.X, requestParam) {
- return false
- }
-
- if !isMaxBytesReaderValue(store.Val, requestParam, writerParam, checker, 0) {
- return false
- }
-
- return true
-}
-
-func isMaxBytesReaderValue(v ssa.Value, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker, depth int) bool {
- if v == nil || depth > MaxDepth {
- return false
- }
-
- switch value := v.(type) {
- case *ssa.Call:
- callee := value.Call.StaticCallee()
- if callee == nil || callee.Name() != "MaxBytesReader" {
- return false
- }
- if callee.Pkg == nil || callee.Pkg.Pkg == nil || callee.Pkg.Pkg.Path() != "net/http" {
- return false
- }
- if len(value.Call.Args) < 3 {
- return false
- }
- if !checker.dependsOn(value.Call.Args[0], writerParam) {
- return false
- }
- return checker.dependsOn(value.Call.Args[1], requestParam)
- case *ssa.ChangeType:
- return isMaxBytesReaderValue(value.X, requestParam, writerParam, checker, depth+1)
- case *ssa.MakeInterface:
- return isMaxBytesReaderValue(value.X, requestParam, writerParam, checker, depth+1)
- case *ssa.TypeAssert:
- return isMaxBytesReaderValue(value.X, requestParam, writerParam, checker, depth+1)
- case *ssa.Phi:
- for _, edge := range value.Edges {
- if isMaxBytesReaderValue(edge, requestParam, writerParam, checker, depth+1) {
- return true
- }
- }
- }
-
- return false
-}
-
-func isRiskyFormParsingCall(callInstr ssa.CallInstruction, requestParam *ssa.Parameter, checker *dependencyChecker) bool {
- common := callInstr.Common()
- if common == nil {
- return false
- }
-
- callee := common.StaticCallee()
- if callee == nil {
- return false
- }
-
- if callee.Signature == nil || callee.Signature.Recv() == nil {
- return false
- }
-
- if !isHTTPRequestPointerType(callee.Signature.Recv().Type()) {
- return false
- }
-
- name := callee.Name()
- if name != "ParseForm" && name != "ParseMultipartForm" && name != "FormValue" && name != "PostFormValue" {
- return false
- }
-
- if len(common.Args) == 0 {
- return false
- }
-
- return checker.dependsOn(common.Args[0], requestParam)
+ config := FormParsingLimits()
+ rule := FormParsingLimitRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/insecure_cookie.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/insecure_cookie.go
new file mode 100644
index 00000000000..5c22eeb69bb
--- /dev/null
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/insecure_cookie.go
@@ -0,0 +1,269 @@
+// (c) Copyright gosec's authors
+//
+// 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 analyzers
+
+import (
+ "go/constant"
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/buildssa"
+ "golang.org/x/tools/go/ssa"
+
+ "github.com/securego/gosec/v2/internal/ssautil"
+ "github.com/securego/gosec/v2/issue"
+)
+
+func newInsecureCookieAnalyzer(id string, description string) *analysis.Analyzer {
+ return &analysis.Analyzer{
+ Name: id,
+ Doc: description,
+ Run: runInsecureCookieAnalysis,
+ Requires: []*analysis.Analyzer{buildssa.Analyzer},
+ }
+}
+
+// cookieState tracks the security-relevant fields set on a single http.Cookie allocation.
+type cookieState struct {
+ allocPos token.Pos
+ secureSet bool
+ httpOnlySet bool
+ sameSiteSet bool
+ // Track the actual values when explicitly set
+ secureTrue bool
+ httpOnlyTrue bool
+ sameSiteSafe bool // SameSiteStrictMode (3) or SameSiteLaxMode (2)
+}
+
+type insecureCookieState struct {
+ *BaseAnalyzerState
+ cookies map[ssa.Value]*cookieState
+ issuesByPos map[token.Pos]*issue.Issue
+}
+
+func newInsecureCookieState(pass *analysis.Pass) *insecureCookieState {
+ return &insecureCookieState{
+ BaseAnalyzerState: NewBaseState(pass),
+ cookies: make(map[ssa.Value]*cookieState),
+ issuesByPos: make(map[token.Pos]*issue.Issue),
+ }
+}
+
+func runInsecureCookieAnalysis(pass *analysis.Pass) (any, error) {
+ ssaResult, err := ssautil.GetSSAResult(pass)
+ if err != nil {
+ return nil, err
+ }
+
+ state := newInsecureCookieState(pass)
+ defer state.Release()
+
+ funcs := collectAnalyzerFunctions(ssaResult.SSA.SrcFuncs)
+ if len(funcs) == 0 {
+ return nil, nil
+ }
+
+ // Phase 1: Collect field stores on http.Cookie allocations.
+ TraverseSSA(funcs, func(_ *ssa.BasicBlock, instr ssa.Instruction) {
+ store, ok := instr.(*ssa.Store)
+ if !ok {
+ return
+ }
+ state.trackCookieFieldStore(store)
+ })
+
+ // Phase 2: Report cookies missing secure attributes.
+ state.reportInsecureCookies()
+
+ if len(state.issuesByPos) == 0 {
+ return nil, nil
+ }
+
+ issues := make([]*issue.Issue, 0, len(state.issuesByPos))
+ for _, i := range state.issuesByPos {
+ issues = append(issues, i)
+ }
+ return issues, nil
+}
+
+func (s *insecureCookieState) trackCookieFieldStore(store *ssa.Store) {
+ fieldAddr, ok := store.Addr.(*ssa.FieldAddr)
+ if !ok {
+ return
+ }
+
+ if !isHTTPCookiePointerType(fieldAddr.X.Type()) {
+ return
+ }
+
+ fieldName, ok := httpCookieFieldName(fieldAddr)
+ if !ok {
+ return
+ }
+
+ root := cookieRoot(fieldAddr.X, 0)
+ if root == nil {
+ return
+ }
+
+ cs := s.getOrCreateCookieState(root)
+
+ switch fieldName {
+ case "Secure":
+ cs.secureSet = true
+ if b, ok := boolConstValue(store.Val); ok {
+ cs.secureTrue = b
+ }
+ case "HttpOnly":
+ cs.httpOnlySet = true
+ if b, ok := boolConstValue(store.Val); ok {
+ cs.httpOnlyTrue = b
+ }
+ case "SameSite":
+ cs.sameSiteSet = true
+ if c, ok := store.Val.(*ssa.Const); ok && c.Value != nil {
+ // http.SameSiteLaxMode = 2, http.SameSiteStrictMode = 3
+ val, isInt := intConstValue(c)
+ if isInt && (val == 2 || val == 3) {
+ cs.sameSiteSafe = true
+ }
+ }
+ }
+}
+
+func (s *insecureCookieState) getOrCreateCookieState(root ssa.Value) *cookieState {
+ if cs, ok := s.cookies[root]; ok {
+ return cs
+ }
+ cs := &cookieState{allocPos: root.Pos()}
+ s.cookies[root] = cs
+ return cs
+}
+
+func (s *insecureCookieState) reportInsecureCookies() {
+ for _, cs := range s.cookies {
+ if cs.allocPos == token.NoPos {
+ continue
+ }
+
+ // Check: Secure must be explicitly set to true
+ if !cs.secureSet || !cs.secureTrue {
+ s.addIssue(cs.allocPos, "http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute")
+ continue
+ }
+ // Check: HttpOnly must be explicitly set to true
+ if !cs.httpOnlySet || !cs.httpOnlyTrue {
+ s.addIssue(cs.allocPos, "http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute")
+ continue
+ }
+ // Check: SameSite must be Lax or Strict
+ if !cs.sameSiteSet || !cs.sameSiteSafe {
+ s.addIssue(cs.allocPos, "http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute")
+ continue
+ }
+ }
+}
+
+func (s *insecureCookieState) addIssue(pos token.Pos, msg string) {
+ if pos == token.NoPos {
+ return
+ }
+ if _, exists := s.issuesByPos[pos]; exists {
+ return
+ }
+ s.issuesByPos[pos] = newIssue(s.Pass.Analyzer.Name, msg, s.Pass.Fset, pos, issue.Medium, issue.High)
+}
+
+// isHTTPCookiePointerType returns true if t is *net/http.Cookie.
+func isHTTPCookiePointerType(t types.Type) bool {
+ ptr, ok := t.(*types.Pointer)
+ if !ok {
+ return false
+ }
+ named, ok := ptr.Elem().(*types.Named)
+ if !ok {
+ return false
+ }
+ obj := named.Obj()
+ if obj == nil || obj.Name() != "Cookie" {
+ return false
+ }
+ pkg := obj.Pkg()
+ return pkg != nil && pkg.Path() == "net/http"
+}
+
+// httpCookieFieldName returns the field name for a FieldAddr on *http.Cookie.
+func httpCookieFieldName(fieldAddr *ssa.FieldAddr) (string, bool) {
+ if fieldAddr == nil {
+ return "", false
+ }
+ t := fieldAddr.X.Type()
+ if ptr, ok := t.(*types.Pointer); ok {
+ t = ptr.Elem()
+ }
+ named, ok := t.(*types.Named)
+ if !ok {
+ return "", false
+ }
+ if named.Obj() == nil || named.Obj().Pkg() == nil ||
+ named.Obj().Pkg().Path() != "net/http" || named.Obj().Name() != "Cookie" {
+ return "", false
+ }
+ st, ok := named.Underlying().(*types.Struct)
+ if !ok || fieldAddr.Field >= st.NumFields() {
+ return "", false
+ }
+ return st.Field(fieldAddr.Field).Name(), true
+}
+
+// cookieRoot traces a value back to its http.Cookie allocation root.
+func cookieRoot(v ssa.Value, depth int) ssa.Value {
+ if v == nil || depth > MaxDepth {
+ return nil
+ }
+ if isHTTPCookiePointerType(v.Type()) {
+ return v
+ }
+ switch value := v.(type) {
+ case *ssa.ChangeType:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.MakeInterface:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.TypeAssert:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.UnOp:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.FieldAddr:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.Phi:
+ if len(value.Edges) > 0 {
+ return cookieRoot(value.Edges[0], depth+1)
+ }
+ }
+ return nil
+}
+
+// intConstValue extracts an int64 from an ssa.Const.
+func intConstValue(c *ssa.Const) (int64, bool) {
+ if c == nil || c.Value == nil {
+ return 0, false
+ }
+ if c.Value.Kind() != constant.Int {
+ return 0, false
+ }
+ val, ok := constant.Int64Val(c.Value)
+ return val, ok
+}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go
index 2cbd1135597..a6abe2f953f 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go
@@ -46,10 +46,19 @@ func LogInjection() taint.Config {
{Package: "log", Method: "Panic"},
{Package: "log", Method: "Panicf"},
{Package: "log", Method: "Panicln"},
- {Package: "log/slog", Method: "Info"},
- {Package: "log/slog", Method: "Warn"},
- {Package: "log/slog", Method: "Error"},
- {Package: "log/slog", Method: "Debug"},
+ // log/slog structured logging functions have the signature:
+ // func Warn(msg string, args ...any)
+ // The variadic `args` are key-value attribute pairs whose values are
+ // automatically escaped by both TextHandler (JSON-quoted) and JSONHandler
+ // (JSON-encoded), making them safe against log injection.
+ // Only the `msg` argument (args[0]) is a real injection vector because
+ // TextHandler writes it verbatim without quoting.
+ // CheckArgs: []int{0} scopes the taint check to the message only,
+ // preventing false positives on: slog.Warn("msg", "key", taintedVal)
+ {Package: "log/slog", Method: "Info", CheckArgs: []int{0}},
+ {Package: "log/slog", Method: "Warn", CheckArgs: []int{0}},
+ {Package: "log/slog", Method: "Error", CheckArgs: []int{0}},
+ {Package: "log/slog", Method: "Debug", CheckArgs: []int{0}},
},
Sanitizers: []taint.Sanitizer{
// strings.ReplaceAll can strip newlines/CRLF for log injection
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/openredirect.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/openredirect.go
new file mode 100644
index 00000000000..bcdddc9658b
--- /dev/null
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/openredirect.go
@@ -0,0 +1,67 @@
+// (c) Copyright gosec's authors
+//
+// 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 analyzers
+
+import (
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/securego/gosec/v2/taint"
+)
+
+// OpenRedirect returns a configuration for detecting open-redirect vulnerabilities
+// where user-controlled data flows into the URL argument of net/http.Redirect.
+// See CWE-601.
+func OpenRedirect() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ // Type sources: tainted when received as parameters from external callers.
+ // Any read from a *http.Request (FormValue, URL.Query().Get, Cookie, etc.)
+ // propagates taint through the existing receiver-based logic in isTainted.
+ {Package: "net/http", Name: "Request", Pointer: true},
+ {Package: "net/url", Name: "URL", Pointer: true},
+ {Package: "net/url", Name: "Values"},
+ },
+ Sinks: []taint.Sink{
+ // http.Redirect(w, r, url, code): only the URL string (arg index 2)
+ // is the redirect target. Skipping arg 1 (*http.Request) prevents the
+ // receiver itself from being treated as a tainted sink argument.
+ {Package: "net/http", Method: "Redirect", CheckArgs: []int{2}},
+ },
+ Sanitizers: []taint.Sanitizer{
+ // url.PathEscape / QueryEscape neutralize untrusted path or query
+ // fragments embedded into a hard-coded base URL.
+ {Package: "net/url", Method: "PathEscape"},
+ {Package: "net/url", Method: "QueryEscape"},
+
+ // Numeric conversions cannot produce a URL host or scheme.
+ {Package: "strconv", Method: "Atoi"},
+ {Package: "strconv", Method: "Itoa"},
+ {Package: "strconv", Method: "ParseInt"},
+ {Package: "strconv", Method: "ParseUint"},
+ {Package: "strconv", Method: "FormatInt"},
+ {Package: "strconv", Method: "FormatUint"},
+ },
+ }
+}
+
+// newOpenRedirectAnalyzer creates an analyzer for detecting open-redirect
+// vulnerabilities via taint analysis (G710).
+func newOpenRedirectAnalyzer(id string, description string) *analysis.Analyzer {
+ config := OpenRedirect()
+ rule := OpenRedirectRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
+}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go
index 34142982cfc..ba9b72e8113 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go
@@ -61,10 +61,15 @@ func PathTraversal() taint.Config {
{Package: "io/ioutil", Method: "ReadDir"},
{Package: "path/filepath", Method: "Walk"},
{Package: "path/filepath", Method: "WalkDir"},
+ // HTTP file-serving functions: user-controlled path = arbitrary file read
+ {Package: "net/http", Method: "ServeFile", CheckArgs: []int{2}},
+ {Package: "net/http", Method: "ServeFileFS", CheckArgs: []int{3}},
},
Sanitizers: []taint.Sanitizer{
// filepath.Clean normalizes and removes traversal components
{Package: "path/filepath", Method: "Clean"},
+ // filepath.Abs calls Clean internally (per Go docs)
+ {Package: "path/filepath", Method: "Abs"},
// filepath.Base extracts just the filename, removing directory traversal
{Package: "path/filepath", Method: "Base"},
// filepath.Rel computes a relative path safely
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go
index 42a4ad80c6f..93f77666b40 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go
@@ -494,6 +494,12 @@ func (ra *RangeAnalyzer) isNonNegativeRecursive(v ssa.Value) bool {
return true
}
+ // Elements loaded from a []rune slice created by converting a
+ // string are valid Unicode code points, guaranteed non-negative.
+ if isElementOfStringRuneSlice(v) {
+ return true
+ }
+
v, info := getRealValueFromOperation(v)
if info.op == "neg" || info.op == "-" {
return false
@@ -565,6 +571,44 @@ func (ra *RangeAnalyzer) isNonNegativeRecursive(v ssa.Value) bool {
return false
}
+// isElementOfStringRuneSlice checks whether v is a value loaded
+// from a []rune slice that was created by converting a string.
+// Go guarantees that string-to-[]rune conversions produce valid
+// Unicode code points (>= 0), so every element is non-negative.
+func isElementOfStringRuneSlice(v ssa.Value) bool {
+ unOp, ok := v.(*ssa.UnOp)
+ if !ok || unOp.Op != token.MUL {
+ return false
+ }
+ idx, ok := unOp.X.(*ssa.IndexAddr)
+ if !ok {
+ return false
+ }
+ return isStringToRuneConversion(idx.X)
+}
+
+// isStringToRuneConversion returns true when v is a Convert from
+// string to []int32 (i.e. []rune).
+func isStringToRuneConversion(v ssa.Value) bool {
+ conv, ok := v.(*ssa.Convert)
+ if !ok {
+ return false
+ }
+ srcBasic, ok := conv.X.Type().Underlying().(*types.Basic)
+ if !ok || srcBasic.Kind() != types.String {
+ return false
+ }
+ dstSlice, ok := conv.Type().Underlying().(*types.Slice)
+ if !ok {
+ return false
+ }
+ elemBasic, ok := dstSlice.Elem().Underlying().(*types.Basic)
+ if !ok {
+ return false
+ }
+ return elemBasic.Kind() == types.Int32
+}
+
func (ra *RangeAnalyzer) ComputeRange(v ssa.Value, block *ssa.BasicBlock) *rangeResult {
res := ra.acquireResult()
isSrcUnsigned := isUint(v)
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/ssti.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/ssti.go
new file mode 100644
index 00000000000..f40d74d576b
--- /dev/null
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/ssti.go
@@ -0,0 +1,104 @@
+// (c) Copyright gosec's authors
+//
+// 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 analyzers
+
+import (
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/securego/gosec/v2/taint"
+)
+
+// SSTI returns a configuration for detecting Server-Side Template Injection
+// vulnerabilities via text/template.
+//
+// The text/template package performs NO auto-escaping and allows calling any
+// exported method on the data object passed to Execute. When user-controlled
+// input flows into Template.Parse, an attacker can invoke arbitrary methods,
+// read files, or achieve remote code execution depending on available gadgets.
+//
+// Even when the template string is static, rendering user data through
+// text/template into an HTTP response produces unescaped HTML, enabling XSS.
+func SSTI() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ // Type sources: tainted when received as parameters
+ {Package: "net/http", Name: "Request", Pointer: true},
+ {Package: "net/url", Name: "Values"},
+
+ // Function sources
+ {Package: "os", Name: "Args", IsFunc: true},
+ {Package: "os", Name: "Getenv", IsFunc: true},
+
+ // I/O sources
+ {Package: "bufio", Name: "Reader", Pointer: true},
+ {Package: "bufio", Name: "Scanner", Pointer: true},
+ },
+ Sinks: []taint.Sink{
+ // CRITICAL: user input flows into the template string itself.
+ // Template.Parse takes a single string argument (the template text).
+ {Package: "text/template", Receiver: "Template", Method: "Parse", Pointer: true, CheckArgs: []int{1}},
+
+ // text/template.Must wraps Parse; arg[0] is the (*Template, error) pair
+ // but in practice the taint flows through the Parse call above.
+
+ // HIGH: text/template.Execute writes unescaped output to an HTTP response.
+ // Guard: only flag when the writer (arg 1) implements net/http.ResponseWriter.
+ {
+ Package: "text/template",
+ Receiver: "Template",
+ Method: "Execute",
+ Pointer: true,
+ CheckArgs: []int{2},
+ ArgTypeGuards: map[int]string{1: "net/http.ResponseWriter"},
+ },
+ {
+ Package: "text/template",
+ Receiver: "Template",
+ Method: "ExecuteTemplate",
+ Pointer: true,
+ CheckArgs: []int{3},
+ ArgTypeGuards: map[int]string{1: "net/http.ResponseWriter"},
+ },
+ },
+ Sanitizers: []taint.Sanitizer{
+ // HTML escaping neutralizes both SSTI template directives and XSS payloads
+ {Package: "html", Method: "EscapeString"},
+ {Package: "html/template", Method: "HTMLEscapeString"},
+ {Package: "html/template", Method: "JSEscapeString"},
+ {Package: "net/url", Method: "QueryEscape"},
+ {Package: "net/url", Method: "PathEscape"},
+
+ // Numeric conversions produce safe output
+ {Package: "strconv", Method: "Atoi"},
+ {Package: "strconv", Method: "Itoa"},
+ {Package: "strconv", Method: "ParseInt"},
+ {Package: "strconv", Method: "ParseUint"},
+ {Package: "strconv", Method: "ParseFloat"},
+ {Package: "strconv", Method: "FormatInt"},
+ {Package: "strconv", Method: "FormatUint"},
+ {Package: "strconv", Method: "FormatFloat"},
+ },
+ }
+}
+
+// newSSTIAnalyzer creates an analyzer for detecting Server-Side Template
+// Injection vulnerabilities via taint analysis (G708).
+func newSSTIAnalyzer(id string, description string) *analysis.Analyzer {
+ config := SSTI()
+ rule := SSTIRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
+}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/unsafe_deserialization.go b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/unsafe_deserialization.go
new file mode 100644
index 00000000000..bbdac51e531
--- /dev/null
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/analyzers/unsafe_deserialization.go
@@ -0,0 +1,87 @@
+// (c) Copyright gosec's authors
+//
+// 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 analyzers
+
+import (
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/securego/gosec/v2/taint"
+)
+
+// UnsafeDeserialization returns a configuration for detecting unsafe
+// deserialization of untrusted data.
+//
+// Go's encoding/gob package embeds full type information in its wire format
+// and will instantiate arbitrary registered types during decode. When an HTTP
+// handler passes r.Body directly to gob.NewDecoder().Decode(), an attacker
+// controls which types get instantiated, leading to denial-of-service or
+// potential RCE (CVE-2024-34156).
+//
+// gopkg.in/yaml.v2's Unmarshal into interface{} can instantiate arbitrary Go
+// types via YAML tags. encoding/xml is susceptible to deeply-nested structure
+// DoS and external entity expansion.
+func UnsafeDeserialization() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ // Type sources: tainted when received as parameters
+ {Package: "net/http", Name: "Request", Pointer: true},
+ {Package: "net/url", Name: "Values"},
+
+ // Function sources
+ {Package: "os", Name: "Args", IsFunc: true},
+ {Package: "os", Name: "Getenv", IsFunc: true},
+
+ // I/O sources
+ {Package: "bufio", Name: "Reader", Pointer: true},
+ {Package: "bufio", Name: "Scanner", Pointer: true},
+ },
+ Sinks: []taint.Sink{
+ // encoding/gob — highest risk: arbitrary type instantiation from wire format
+ // gob.NewDecoder takes an io.Reader (arg 0), so if the reader is tainted
+ // the decoder will process attacker-controlled data.
+ {Package: "encoding/gob", Method: "NewDecoder", CheckArgs: []int{0}},
+
+ // gopkg.in/yaml.v2 — Unmarshal([]byte, interface{}) can instantiate arbitrary types
+ {Package: "gopkg.in/yaml.v2", Method: "Unmarshal", CheckArgs: []int{0}},
+ // yaml.NewDecoder takes an io.Reader (arg 0)
+ {Package: "gopkg.in/yaml.v2", Method: "NewDecoder", CheckArgs: []int{0}},
+
+ // encoding/xml — deeply-nested structure DoS, entity expansion
+ {Package: "encoding/xml", Method: "NewDecoder", CheckArgs: []int{0}},
+ {Package: "encoding/xml", Method: "Unmarshal", CheckArgs: []int{0}},
+ },
+ Sanitizers: []taint.Sanitizer{
+ // io.LimitReader bounds the amount of data read, mitigating DoS amplification
+ {Package: "io", Method: "LimitReader"},
+
+ // Numeric conversions — result is safe
+ {Package: "strconv", Method: "Atoi"},
+ {Package: "strconv", Method: "Itoa"},
+ {Package: "strconv", Method: "ParseInt"},
+ {Package: "strconv", Method: "ParseUint"},
+ {Package: "strconv", Method: "ParseFloat"},
+ },
+ }
+}
+
+// newUnsafeDeserializationAnalyzer creates an analyzer for detecting unsafe
+// deserialization of untrusted data via taint analysis (G709).
+func newUnsafeDeserializationAnalyzer(id string, description string) *analysis.Analyzer {
+ config := UnsafeDeserialization()
+ rule := UnsafeDeserializationRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
+}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/cwe/data.go b/hack/tools/vendor/github.com/securego/gosec/v2/cwe/data.go
index c8bfc27dca9..16f7645c2b5 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/cwe/data.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/cwe/data.go
@@ -48,6 +48,11 @@ var idWeaknesses = map[string]*Weakness{
Description: "The software does not properly neutralize CRLF sequences before using externally-influenced input in protocol elements that rely on CRLF as delimiters, allowing attackers to inject additional commands or headers.",
Name: "Improper Neutralization of CRLF Sequences ('CRLF Injection')",
},
+ "94": {
+ ID: "94",
+ Description: "The software constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.",
+ Name: "Improper Control of Generation of Code ('Code Injection')",
+ },
"118": {
ID: "118",
Description: "The software does not restrict or incorrectly restricts operations within the boundaries of a resource that is accessed using an index or pointer, such as memory or files.",
@@ -163,6 +168,26 @@ var idWeaknesses = map[string]*Weakness{
Description: "The product uses a cryptographic primitive that uses an Initialization Vector (IV), but the product does not generate IVs that are sufficiently unpredictable or unique according to the expected cryptographic requirements for that primitive.",
Name: "Generation of Weak Initialization Vector (IV)",
},
+ "117": {
+ ID: "117",
+ Description: "The software does not neutralize or incorrectly neutralizes output that is written to logs.",
+ Name: "Improper Output Neutralization for Logs",
+ },
+ "502": {
+ ID: "502",
+ Description: "The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.",
+ Name: "Deserialization of Untrusted Data",
+ },
+ "614": {
+ ID: "614",
+ Description: "The Secure attribute for a sensitive cookie is not set, which could cause the user agent to send that cookie in plaintext over an HTTP session.",
+ Name: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute",
+ },
+ "918": {
+ ID: "918",
+ Description: "The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.",
+ Name: "Server-Side Request Forgery (SSRF)",
+ },
}
// Get Retrieves a CWE weakness by it's id
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/issue/issue.go b/hack/tools/vendor/github.com/securego/gosec/v2/issue/issue.go
index c0d485f7c97..f2cc986d2df 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/issue/issue.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/issue/issue.go
@@ -52,7 +52,9 @@ func GetCweByRule(id string) *cwe.Weakness {
return nil
}
-// ruleToCWE maps gosec rules to CWEs
+// ruleToCWE maps gosec rules to CWEs. The key is the rule ID
+// and the value is the CWE ID. If a rule does not have a CWE,
+// it will not be included in this map.
var ruleToCWE = map[string]string{
"G101": "798",
"G102": "200",
@@ -65,7 +67,10 @@ var ruleToCWE = map[string]string{
"G110": "409",
"G111": "22",
"G112": "400",
+ "G113": "444",
"G707": "93",
+ "G708": "94",
+ "G709": "502",
"G114": "676",
"G115": "190",
"G116": "838",
@@ -76,6 +81,7 @@ var ruleToCWE = map[string]string{
"G121": "346",
"G122": "367",
"G123": "295",
+ "G124": "614",
"G201": "89",
"G202": "89",
"G203": "79",
@@ -86,6 +92,7 @@ var ruleToCWE = map[string]string{
"G304": "22",
"G305": "22",
"G306": "276",
+ "G307": "276",
"G401": "328",
"G402": "295",
"G403": "310",
@@ -103,6 +110,13 @@ var ruleToCWE = map[string]string{
"G507": "327",
"G601": "118",
"G602": "118",
+ "G701": "89",
+ "G702": "78",
+ "G703": "22",
+ "G704": "918",
+ "G705": "79",
+ "G706": "117",
+ "G710": "601",
}
// Issue is returned by a gosec rule if it discovers an issue with the scanned code.
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go b/hack/tools/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go
index 06473faa31b..6389309cfd0 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go
@@ -21,10 +21,11 @@ type secretSerialization struct {
}
type formatSpec struct {
- name string
- tagKey string
- functionSinks []functionSink
- methodSinks []methodSink
+ name string
+ tagKey string
+ marshalerMethod string // e.g. "MarshalJSON"; empty if no standard interface exists
+ functionSinks []functionSink
+ methodSinks []methodSink
}
type functionSink struct {
@@ -44,15 +45,16 @@ type typeAnalysisCacheKey struct {
}
type sensitiveFieldMatch struct {
- fieldName string
- jsonKey string
- found bool
+ fieldName string
+ serializedKey string
+ found bool
}
var g117Formats = []formatSpec{
{
- name: "json",
- tagKey: "json",
+ name: "JSON",
+ tagKey: "json",
+ marshalerMethod: "MarshalJSON",
functionSinks: []functionSink{
{pkgPath: "encoding/json", names: []string{"Marshal", "MarshalIndent"}},
},
@@ -61,8 +63,9 @@ var g117Formats = []formatSpec{
},
},
{
- name: "yaml",
- tagKey: "yaml",
+ name: "YAML",
+ tagKey: "yaml",
+ marshalerMethod: "MarshalYAML",
functionSinks: []functionSink{
{pkgPath: "go.yaml.in/yaml/v3", names: []string{"Marshal"}},
{pkgPath: "gopkg.in/yaml.v3", names: []string{"Marshal"}},
@@ -76,8 +79,9 @@ var g117Formats = []formatSpec{
},
},
{
- name: "xml",
- tagKey: "xml",
+ name: "XML",
+ tagKey: "xml",
+ marshalerMethod: "MarshalXML",
functionSinks: []functionSink{
{pkgPath: "encoding/xml", names: []string{"Marshal", "MarshalIndent"}},
},
@@ -86,7 +90,7 @@ var g117Formats = []formatSpec{
},
},
{
- name: "toml",
+ name: "TOML",
tagKey: "toml",
functionSinks: []functionSink{
{pkgPath: "github.com/pelletier/go-toml", names: []string{"Marshal"}},
@@ -111,17 +115,146 @@ func (r *secretSerialization) Match(n ast.Node, ctx *gosec.Context) (*issue.Issu
return nil, nil
}
+ if isInsideCustomMarshaler(callExpr, ctx) {
+ return nil, nil
+ }
+
typ := ctx.Info.TypeOf(serializedArg)
if typ == nil {
return nil, nil
}
- if match := r.findSensitiveFieldForType(typ, format.tagKey); match.found {
- msg := fmt.Sprintf("Marshaled struct field %q (JSON key %q) matches secret pattern", match.fieldName, match.jsonKey)
- return ctx.NewIssue(callExpr, r.ID(), msg, r.Severity, r.Confidence), nil
+ if typeImplementsMarshaler(typ, format.marshalerMethod) {
+ return nil, nil
+ }
+
+ match := r.findSensitiveFieldForType(typ, format.tagKey)
+ if !match.found {
+ return nil, nil
+ }
+
+ if compositeLitFieldIsTransformed(serializedArg, match.fieldName) {
+ return nil, nil
+ }
+
+ msg := fmt.Sprintf("Marshaled struct field %q (%s key %q) matches secret pattern", match.fieldName, format.name, match.serializedKey)
+ return ctx.NewIssue(callExpr, r.ID(), msg, r.Severity, r.Confidence), nil
+}
+
+// customMarshalerMethods lists method names that indicate a custom marshaler
+// implementation. When a marshal call occurs inside one of these methods, the
+// developer is explicitly controlling serialization, so G117 should not flag it.
+var customMarshalerMethods = map[string]bool{
+ "MarshalJSON": true,
+ "MarshalYAML": true,
+ "MarshalXML": true,
+ "MarshalText": true,
+ "MarshalTOML": true,
+ "MarshalBSON": true,
+}
+
+// isInsideCustomMarshaler reports whether callExpr is located inside a method
+// whose name matches a known custom marshaler (e.g. MarshalJSON).
+func isInsideCustomMarshaler(callExpr *ast.CallExpr, ctx *gosec.Context) bool {
+ if ctx.Root == nil {
+ return false
+ }
+
+ pos := callExpr.Pos()
+ var found bool
+
+ ast.Inspect(ctx.Root, func(n ast.Node) bool {
+ if found {
+ return false
+ }
+ funcDecl, ok := n.(*ast.FuncDecl)
+ if !ok || funcDecl.Body == nil {
+ return true
+ }
+ // Check if the call is inside this function body.
+ if pos < funcDecl.Body.Pos() || pos >= funcDecl.Body.End() {
+ return true
+ }
+ // Must be a method (has a receiver) with a recognized marshaler name.
+ if funcDecl.Recv != nil && funcDecl.Recv.NumFields() > 0 {
+ if customMarshalerMethods[funcDecl.Name.Name] {
+ found = true
+ }
+ }
+ return false
+ })
+
+ return found
+}
+
+// typeImplementsMarshaler reports whether typ (or its element type for
+// containers) has a method with the given name, indicating it implements a
+// custom marshaler interface (e.g. json.Marshaler). When a type has a custom
+// marshaler, the serialization library calls that method instead of serializing
+// fields directly, making struct field analysis irrelevant.
+func typeImplementsMarshaler(typ types.Type, methodName string) bool {
+ if methodName == "" {
+ return false
+ }
+ named := elementNamedType(typ)
+ if named == nil {
+ return false
+ }
+ // Check both value and pointer receiver methods via the pointer method set,
+ // which is a superset of the value method set.
+ mset := types.NewMethodSet(types.NewPointer(named))
+ for i := 0; i < mset.Len(); i++ {
+ if mset.At(i).Obj().Name() == methodName {
+ return true
+ }
+ }
+ return false
+}
+
+// elementNamedType unwraps pointers, slices, arrays, and maps to find the
+// innermost Named type. Returns nil if no Named type is found.
+func elementNamedType(typ types.Type) *types.Named {
+ switch t := typ.(type) {
+ case *types.Named:
+ return t
+ case *types.Pointer:
+ return elementNamedType(t.Elem())
+ case *types.Slice:
+ return elementNamedType(t.Elem())
+ case *types.Array:
+ return elementNamedType(t.Elem())
+ case *types.Map:
+ return elementNamedType(t.Elem())
}
+ return nil
+}
- return nil, nil
+// compositeLitFieldIsTransformed checks whether expr is a composite literal
+// in which the given field name is assigned a function call result. A function
+// call indicates the value is being transformed (e.g. masked or redacted)
+// before serialization.
+func compositeLitFieldIsTransformed(expr ast.Expr, fieldName string) bool {
+ // Unwrap address-of operator: &Struct{...}
+ if unary, ok := expr.(*ast.UnaryExpr); ok {
+ expr = unary.X
+ }
+ lit, ok := expr.(*ast.CompositeLit)
+ if !ok {
+ return false
+ }
+ for _, elt := range lit.Elts {
+ kv, ok := elt.(*ast.KeyValueExpr)
+ if !ok {
+ continue
+ }
+ ident, ok := kv.Key.(*ast.Ident)
+ if !ok || ident.Name != fieldName {
+ continue
+ }
+ _, isCall := kv.Value.(*ast.CallExpr)
+ return isCall
+ }
+ return false
}
func isNamedTypeInPackage(typ types.Type, pkgPath, typeName string) bool {
@@ -382,7 +515,7 @@ func (r *secretSerialization) findSensitiveSerializedField(st *types.Struct, tag
}
if gosec.RegexMatchWithCache(r.pattern, field.Name()) || gosec.RegexMatchWithCache(r.pattern, effectiveKey) {
- return sensitiveFieldMatch{fieldName: field.Name(), jsonKey: effectiveKey, found: true}
+ return sensitiveFieldMatch{fieldName: field.Name(), serializedKey: effectiveKey, found: true}
}
}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/rules/tls.go b/hack/tools/vendor/github.com/securego/gosec/v2/rules/tls.go
index 96b243dfca6..6f7cb399e7a 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/rules/tls.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/rules/tls.go
@@ -236,22 +236,28 @@ func (t *insecureConfigTLS) findDefinition(obj types.Object, c *gosec.Context) a
return initializer
}
+func (t *insecureConfigTLS) isSafeDefault() bool {
+ major, minor, _ := gosec.GoVersion()
+ return major > 1 || (major == 1 && minor >= 18)
+}
+
func (t *insecureConfigTLS) checkVersion(n ast.Node, c *gosec.Context) *issue.Issue {
- // Flag explicitly low MinVersion (including explicit 0)
+ // Flag explicitly low MinVersion.
+ // Since Go 1.18+, MinVersion 0 means "use default" which is
+ // TLS 1.2 — safe and not worth flagging.
if t.minVersionSet && t.actualMinVersion < t.MinVersion {
+ if t.actualMinVersion == 0 && t.isSafeDefault() {
+ return nil
+ }
return c.NewIssue(n, t.ID(), "TLS MinVersion too low.", issue.High, issue.High)
}
- // Handle MaxVersion
+ // Handle MaxVersion.
+ // MaxVersion 0 means "use latest" which is always safe.
if t.maxVersionSet {
- // Special case for explicit MaxVersion: 0 (default latest) - suppress warning if MinVersion is securely set
if t.actualMaxVersion == 0 {
- if t.minVersionSet && t.actualMinVersion >= t.MinVersion {
- return nil
- }
- // Otherwise treat explicit 0 as potentially insecure (fall through to flag)
+ return nil
}
- // Flag if explicitly capped too low (non-zero low values always flagged)
if t.actualMaxVersion < t.MaxVersion {
return c.NewIssue(n, t.ID(), "TLS MaxVersion too low.", issue.High, issue.High)
}
@@ -271,6 +277,7 @@ func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*issue.Issue, e
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
actualType := c.Info.TypeOf(complit.Type)
if actualType != nil && actualType.String() == t.requiredType {
+ defer t.resetVersion()
for _, elt := range complit.Elts {
if issue := t.processTLSConf(elt, c); issue != nil {
return issue, nil
@@ -279,7 +286,6 @@ func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*issue.Issue, e
if issue := t.checkVersion(complit, c); issue != nil {
return issue, nil
}
- t.resetVersion()
return nil, nil
}
}
diff --git a/hack/tools/vendor/github.com/securego/gosec/v2/taint/taint.go b/hack/tools/vendor/github.com/securego/gosec/v2/taint/taint.go
index d53b14f2fa2..fab64ccc4bf 100644
--- a/hack/tools/vendor/github.com/securego/gosec/v2/taint/taint.go
+++ b/hack/tools/vendor/github.com/securego/gosec/v2/taint/taint.go
@@ -23,6 +23,12 @@ import (
// maxTaintDepth limits recursion depth to prevent stack overflow on large codebases
const maxTaintDepth = 50
+// maxCallerEdges caps the number of incoming call graph edges examined per function
+// in isParameterTainted. CHA over-approximates call graphs (every interface method
+// call fans out to ALL implementations), so a function can have thousands of callers.
+// Real taint flows come from direct/nearby callers, not the 33rd+ CHA-generated edge.
+const maxCallerEdges = 32
+
// isContextType checks if a type is context.Context.
// context.Context is a control-flow mechanism (deadlines, cancellation, request-scoped values)
// that does not carry user-controlled data relevant to taint sinks like XSS.
@@ -211,14 +217,21 @@ type Config struct {
}
// Analyzer performs taint analysis on SSA programs.
+// paramKey identifies a specific parameter of a function for memoization.
+type paramKey struct {
+ fn *ssa.Function
+ paramIdx int
+}
+
type Analyzer struct {
- config *Config
- sources map[string]Source // keyed by full type string
- funcSrcs map[string]Source // function sources keyed by "pkg.Func"
- sinks map[string]Sink // keyed by full function string
- sanitizers map[string]struct{} // keyed by full function string
- callGraph *callgraph.Graph
- prog *ssa.Program // set at Analyze time for ArgTypeGuards resolution
+ config *Config
+ sources map[string]Source // keyed by full type string
+ funcSrcs map[string]Source // function sources keyed by "pkg.Func"
+ sinks map[string]Sink // keyed by full function string
+ sanitizers map[string]struct{} // keyed by full function string
+ callGraph *callgraph.Graph
+ prog *ssa.Program // set at Analyze time for ArgTypeGuards resolution
+ paramTaintCache map[paramKey]bool // caches true results from isParameterTainted
}
// SetCallGraph injects a precomputed call graph.
@@ -309,6 +322,8 @@ func (a *Analyzer) Analyze(prog *ssa.Program, srcFuncs []*ssa.Function) []Result
a.callGraph = cha.CallGraph(prog)
}
+ a.paramTaintCache = make(map[paramKey]bool)
+
var results []Result
// Find all sink calls in the program
@@ -316,6 +331,8 @@ func (a *Analyzer) Analyze(prog *ssa.Program, srcFuncs []*ssa.Function) []Result
results = append(results, a.analyzeFunctionSinks(fn)...)
}
+ a.paramTaintCache = nil
+
return results
}
@@ -794,6 +811,33 @@ func (a *Analyzer) isSourceType(t types.Type) bool {
return false
}
+// mayHaveExternalCallers reports whether fn could be invoked by code outside
+// the analyzed package — code that is invisible to the call graph.
+//
+// Exported bare functions (non-methods) are the primary case: frameworks
+// register them via dynamic dispatch that CHA cannot resolve, so the call
+// graph may lack edges even though the function IS called at runtime.
+//
+// Methods with a receiver are excluded because CHA resolves interface dispatch
+// to concrete methods, so their callers are generally visible in the graph.
+// Unexported functions are only callable within the package, and the call graph
+// covers intra-package calls comprehensively.
+func mayHaveExternalCallers(fn *ssa.Function) bool {
+ if fn.Signature == nil {
+ return false
+ }
+ // Methods — CHA handles interface dispatch; callers are visible.
+ if fn.Signature.Recv() != nil {
+ return false
+ }
+ // Closures / anonymous functions are never exported.
+ if fn.Parent() != nil {
+ return false
+ }
+ // Exported bare function — may be called by external frameworks.
+ return token.IsExported(fn.Name())
+}
+
// isSourceFuncCall checks if a call invokes a known source function
// (a function explicitly configured as producing tainted data, e.g., os.Getenv).
func (a *Analyzer) isSourceFuncCall(call *ssa.Call) bool {
@@ -824,30 +868,65 @@ func (a *Analyzer) isParameterTainted(param *ssa.Parameter, fn *ssa.Function, vi
return false
}
- // Check if parameter type is a source type.
- // This is the ONLY place where type-based source matching should trigger
- // automatic taint — because parameters represent data flowing IN from
- // external callers we don't control.
- if a.isSourceType(param.Type()) {
- return true
+ // Resolve paramIdx early so we can use it for cache lookups.
+ paramIdx := -1
+ for i, p := range fn.Params {
+ if p == param {
+ paramIdx = i
+ break
+ }
+ }
+
+ // Check memoization cache (only true results are cached).
+ if paramIdx >= 0 && a.paramTaintCache != nil {
+ key := paramKey{fn: fn, paramIdx: paramIdx}
+ if a.paramTaintCache[key] {
+ return true
+ }
}
// Use call graph to find callers and check their arguments
if a.callGraph == nil {
+ // No call graph: fall back to type-based auto-taint for source-typed params
+ // (conservative — may produce false positives, but we have no callee info).
+ if a.isSourceType(param.Type()) {
+ if paramIdx >= 0 && a.paramTaintCache != nil {
+ a.paramTaintCache[paramKey{fn: fn, paramIdx: paramIdx}] = true
+ }
+ return true
+ }
return false
}
node := a.callGraph.Nodes[fn]
- if node == nil {
- return false
- }
- paramIdx := -1
- for i, p := range fn.Params {
- if p == param {
- paramIdx = i
- break
+ // Check if parameter type is a configured source type.
+ //
+ // Strategy:
+ // 1. No callers in call graph → definite entry point → auto-taint.
+ // 2. Exported bare function → may have invisible external callers
+ // (framework dispatch) → auto-taint to avoid false negatives.
+ // 3. Has callers, not exported bare func → fall through to caller check.
+ //
+ // Case 2 addresses a class of false negatives where an internal caller
+ // with safe args suppresses taint for an exported entry point that is
+ // also called externally by a framework (issue #1629 + Barry review).
+ // Methods are excluded because CHA resolves interface dispatch, making
+ // their callers visible in the call graph.
+ if a.isSourceType(param.Type()) {
+ isEntryPoint := (node == nil || len(node.In) == 0)
+ if isEntryPoint || mayHaveExternalCallers(fn) {
+ if paramIdx >= 0 && a.paramTaintCache != nil {
+ a.paramTaintCache[paramKey{fn: fn, paramIdx: paramIdx}] = true
+ }
+ return true
}
+ // Has known callers and is not a handler — fall through to verify
+ // taint via those callers.
+ }
+
+ if node == nil {
+ return false
}
if paramIdx < 0 {
@@ -867,8 +946,14 @@ func (a *Analyzer) isParameterTainted(param *ssa.Parameter, fn *ssa.Function, vi
adjustedIdx = paramIdx
}
- // Check each caller
+ // Check each caller, capping at maxCallerEdges to avoid combinatorial
+ // explosion from CHA over-approximation of interface method calls.
+ edgesChecked := 0
for _, inEdge := range node.In {
+ if edgesChecked >= maxCallerEdges {
+ break
+ }
+
site := inEdge.Site
if site == nil {
continue
@@ -877,7 +962,11 @@ func (a *Analyzer) isParameterTainted(param *ssa.Parameter, fn *ssa.Function, vi
callArgs := site.Common().Args
if adjustedIdx < len(callArgs) {
+ edgesChecked++
if a.isTainted(callArgs[adjustedIdx], inEdge.Caller.Func, visited, depth+1) {
+ if a.paramTaintCache != nil {
+ a.paramTaintCache[paramKey{fn: fn, paramIdx: paramIdx}] = true
+ }
return true
}
}
@@ -1018,6 +1107,10 @@ func (a *Analyzer) isFieldTaintedOnValue(v ssa.Value, fieldIdx int, fn *ssa.Func
case *ssa.Alloc:
return a.isFieldOfAllocTainted(val, fieldIdx, fn, visited, depth)
case *ssa.Phi:
+ if visited[v] {
+ return false
+ }
+ visited[v] = true
for _, edge := range val.Edges {
if a.isFieldTaintedOnValue(edge, fieldIdx, fn, visited, depth+1) {
return true
diff --git a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/diff.go b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/diff.go
index 81aa6557070..cc19fe52218 100644
--- a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/diff.go
+++ b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/diff.go
@@ -5,12 +5,18 @@ import (
"time"
)
+// ParseOptions specifies options for parsing diffs.
+type ParseOptions struct {
+ // KeepCR specifies whether to keep trailing carriage return characters (\r) in lines.
+ KeepCR bool
+}
+
// A FileDiff represents a unified diff for a single file.
//
// A file unified diff has a header that resembles the following:
//
-// --- oldname 2009-10-11 15:12:20.000000000 -0700
-// +++ newname 2009-10-11 15:12:30.000000000 -0700
+// --- oldname 2009-10-11 15:12:20.000000000 -0700
+// +++ newname 2009-10-11 15:12:30.000000000 -0700
type FileDiff struct {
// the original name of the file
OrigName string
diff --git a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/parse.go b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/parse.go
index 48eeb967029..b73e2301fbf 100644
--- a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/parse.go
+++ b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/parse.go
@@ -1,7 +1,6 @@
package diff
import (
- "bufio"
"bytes"
"errors"
"fmt"
@@ -17,13 +16,24 @@ import (
// case of per-file errors. If it cannot detect when the diff of the next file
// begins, the hunks are added to the FileDiff of the previous file.
func ParseMultiFileDiff(diff []byte) ([]*FileDiff, error) {
- return NewMultiFileDiffReader(bytes.NewReader(diff)).ReadAllFiles()
+ return ParseMultiFileDiffOptions(diff, ParseOptions{})
+}
+
+// ParseMultiFileDiffOptions parses a multi-file unified diff with the given options.
+func ParseMultiFileDiffOptions(diff []byte, opts ParseOptions) ([]*FileDiff, error) {
+ return NewMultiFileDiffReaderOptions(bytes.NewReader(diff), opts).ReadAllFiles()
}
// NewMultiFileDiffReader returns a new MultiFileDiffReader that reads
// a multi-file unified diff from r.
func NewMultiFileDiffReader(r io.Reader) *MultiFileDiffReader {
- return &MultiFileDiffReader{reader: newLineReader(r)}
+ return NewMultiFileDiffReaderOptions(r, ParseOptions{})
+}
+
+// NewMultiFileDiffReaderOptions returns a new MultiFileDiffReader that reads
+// a multi-file unified diff from r with the given options.
+func NewMultiFileDiffReaderOptions(r io.Reader, opts ParseOptions) *MultiFileDiffReader {
+ return &MultiFileDiffReader{reader: newLineReaderOptions(r, opts)}
}
// MultiFileDiffReader reads a multi-file unified diff.
@@ -153,13 +163,24 @@ func (r *MultiFileDiffReader) ReadAllFiles() ([]*FileDiff, error) {
// ParseFileDiff parses a file unified diff.
func ParseFileDiff(diff []byte) (*FileDiff, error) {
- return NewFileDiffReader(bytes.NewReader(diff)).Read()
+ return ParseFileDiffOptions(diff, ParseOptions{})
+}
+
+// ParseFileDiffOptions parses a file unified diff with the given options.
+func ParseFileDiffOptions(diff []byte, opts ParseOptions) (*FileDiff, error) {
+ return NewFileDiffReaderOptions(bytes.NewReader(diff), opts).Read()
}
// NewFileDiffReader returns a new FileDiffReader that reads a file
// unified diff.
func NewFileDiffReader(r io.Reader) *FileDiffReader {
- return &FileDiffReader{reader: &lineReader{reader: bufio.NewReader(r)}}
+ return NewFileDiffReaderOptions(r, ParseOptions{})
+}
+
+// NewFileDiffReaderOptions returns a new FileDiffReader that reads a file
+// unified diff with the given options.
+func NewFileDiffReaderOptions(r io.Reader, opts ParseOptions) *FileDiffReader {
+ return &FileDiffReader{reader: newLineReaderOptions(r, opts)}
}
// FileDiffReader reads a unified file diff.
@@ -405,6 +426,7 @@ func readQuotedFilename(text string) (value string, remainder string, err error)
// valid syntax, it may be impossible to extract filenames; if so, the
// function returns ("", "", true).
func parseDiffGitArgs(diffArgs string) (string, string, bool) {
+ diffArgs = strings.TrimSuffix(diffArgs, "\r")
length := len(diffArgs)
if length < 3 {
return "", "", false
@@ -540,6 +562,7 @@ func handleEmpty(fd *FileDiff) (wasEmpty bool) {
return
}
rawFilename := header[len(prefix):]
+ rawFilename = strings.TrimSuffix(rawFilename, "\r")
// extract the filename prefix (e.g. "a/") from the 'diff --git' line.
var prefixLetterIndex int
@@ -586,7 +609,12 @@ var (
// only of hunks and not include a file header; if it has a file
// header, use ParseFileDiff.
func ParseHunks(diff []byte) ([]*Hunk, error) {
- r := NewHunksReader(bytes.NewReader(diff))
+ return ParseHunksOptions(diff, ParseOptions{})
+}
+
+// ParseHunksOptions parses hunks from a unified diff with the given options.
+func ParseHunksOptions(diff []byte, opts ParseOptions) ([]*Hunk, error) {
+ r := NewHunksReaderOptions(bytes.NewReader(diff), opts)
hunks, err := r.ReadAllHunks()
if err != nil {
return nil, err
@@ -597,7 +625,13 @@ func ParseHunks(diff []byte) ([]*Hunk, error) {
// NewHunksReader returns a new HunksReader that reads unified diff hunks
// from r.
func NewHunksReader(r io.Reader) *HunksReader {
- return &HunksReader{reader: &lineReader{reader: bufio.NewReader(r)}}
+ return NewHunksReaderOptions(r, ParseOptions{})
+}
+
+// NewHunksReaderOptions returns a new HunksReader that reads unified diff hunks
+// from r with the given options.
+func NewHunksReaderOptions(r io.Reader, opts ParseOptions) *HunksReader {
+ return &HunksReader{reader: newLineReaderOptions(r, opts)}
}
// A HunksReader reads hunks from a unified diff.
@@ -701,7 +735,7 @@ func (r *HunksReader) ReadHunk() (*Hunk, error) {
// handle that case.
return r.hunk, &ParseError{r.line, r.offset, &ErrBadHunkLine{Line: line}}
}
- if bytes.Equal(line, []byte(noNewlineMessage)) {
+ if bytes.Equal(bytes.TrimSuffix(line, []byte("\r")), []byte(noNewlineMessage)) {
if lastLineFromOrig {
// Retain the newline in the body (otherwise the
// diff line would be like "-a+b", where "+b" is
@@ -755,6 +789,7 @@ func linePrefix(c byte) bool {
// if its value is 1. normalizeHeader returns an error if the header
// is not in the correct format.
func normalizeHeader(header string) (string, string, error) {
+ header = strings.TrimSuffix(header, "\r")
// Split the header into five parts: the first '@@', the two
// ranges, the last '@@', and the optional section.
pieces := strings.SplitN(header, " ", 5)
@@ -815,7 +850,8 @@ func parseOnlyInMessage(line []byte) (bool, []byte, []byte) {
if idx < 0 {
return false, nil, nil
}
- return true, line[:idx], line[idx+2:]
+ filename := bytes.TrimSuffix(line[idx+2:], []byte("\r"))
+ return true, line[:idx], filename
}
// A ParseError is a description of a unified diff syntax error.
diff --git a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
index 45300252b7c..3356283d681 100644
--- a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
+++ b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
@@ -13,6 +13,13 @@ func newLineReader(r io.Reader) *lineReader {
return &lineReader{reader: bufio.NewReader(r)}
}
+func newLineReaderOptions(r io.Reader, opts ParseOptions) *lineReader {
+ return &lineReader{
+ reader: bufio.NewReader(r),
+ keepCR: opts.KeepCR,
+ }
+}
+
// lineReader is a wrapper around a bufio.Reader that caches the next line to
// provide lookahead functionality for the next two lines.
type lineReader struct {
@@ -20,14 +27,20 @@ type lineReader struct {
cachedNextLine []byte
cachedNextLineErr error
+
+ keepCR bool
+}
+
+func (l *lineReader) ensureCachedNextLine() {
+ if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
+ l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader, l.keepCR)
+ }
}
// readLine returns the next unconsumed line and advances the internal cache of
// the lineReader.
func (l *lineReader) readLine() ([]byte, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
+ l.ensureCachedNextLine()
if l.cachedNextLineErr != nil {
return nil, l.cachedNextLineErr
@@ -35,7 +48,7 @@ func (l *lineReader) readLine() ([]byte, error) {
next := l.cachedNextLine
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
+ l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader, l.keepCR)
return next, nil
}
@@ -46,9 +59,7 @@ func (l *lineReader) readLine() ([]byte, error) {
// io.EOF and bufio.ErrBufferFull errors are ignored so that the function can
// be used when at the end of the file.
func (l *lineReader) nextLineStartsWith(prefix string) (bool, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
+ l.ensureCachedNextLine()
return l.lineHasPrefix(l.cachedNextLine, prefix, l.cachedNextLineErr)
}
@@ -58,14 +69,8 @@ func (l *lineReader) nextLineStartsWith(prefix string) (bool, error) {
//
// io.EOF and bufio.ErrBufferFull errors are ignored so that the function can
// be used when at the end of the file.
-//
-// The lineReader MUST be initialized by calling readLine at least once before
-// calling nextLineStartsWith. Otherwise ErrLineReaderUninitialized will be
-// returned.
func (l *lineReader) nextNextLineStartsWith(prefix string) (bool, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
+ l.ensureCachedNextLine()
next, err := l.reader.Peek(len(prefix))
return l.lineHasPrefix(next, prefix, err)
@@ -93,22 +98,21 @@ func (l *lineReader) lineHasPrefix(line []byte, prefix string, readErr error) (b
// the next line in the Reader with the trailing newline stripped. It will return an
// io.EOF error when there is nothing left to read (at the start of the function call). It
// will return any other errors it receives from the underlying call to ReadBytes.
-func readLine(r *bufio.Reader) ([]byte, error) {
- line_, err := r.ReadBytes('\n')
- if err == io.EOF {
- if len(line_) == 0 {
- return nil, io.EOF
- }
-
- // ReadBytes returned io.EOF, because it didn't find another newline, but there is
- // still the remainder of the file to return as a line.
- line := line_
- return line, nil
- } else if err != nil {
+func readLine(r *bufio.Reader, keepCR bool) ([]byte, error) {
+ line, err := r.ReadBytes('\n')
+ if err == io.EOF && len(line) == 0 {
+ return nil, io.EOF
+ }
+ if err != nil && err != io.EOF {
return nil, err
}
- line := line_[0 : len(line_)-1]
- return dropCR(line), nil
+ if line[len(line)-1] == '\n' {
+ line = line[:len(line)-1]
+ }
+ if !keepCR {
+ return dropCR(line), nil
+ }
+ return line, nil
}
// dropCR drops a terminal \r from the data.
diff --git a/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reverse.go b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reverse.go
new file mode 100644
index 00000000000..87715efb9be
--- /dev/null
+++ b/hack/tools/vendor/github.com/sourcegraph/go-diff/diff/reverse.go
@@ -0,0 +1,192 @@
+package diff
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+)
+
+// ReverseFileDiff takes a diff.FileDiff, and returns the reverse operation.
+// This is a FileDiff that undoes the edit of the original.
+func ReverseFileDiff(fd *FileDiff) (*FileDiff, error) {
+ reverse := FileDiff{
+ OrigName: fd.NewName,
+ OrigTime: fd.NewTime,
+ NewName: fd.OrigName,
+ NewTime: fd.OrigTime,
+ Extended: fd.Extended,
+ }
+ for _, hunk := range fd.Hunks {
+ invHunk, err := reverseHunk(hunk)
+ if err != nil {
+ return nil, err
+ }
+ reverse.Hunks = append(reverse.Hunks, invHunk)
+ }
+ return &reverse, nil
+}
+
+// ReverseMultiFileDiff reverses a series of FileDiffs.
+func ReverseMultiFileDiff(fds []*FileDiff) ([]*FileDiff, error) {
+ var reverse []*FileDiff
+ for _, fd := range fds {
+ r, err := ReverseFileDiff(fd)
+ if err != nil {
+ return nil, err
+ }
+ reverse = append(reverse, r)
+ }
+ return reverse, nil
+}
+
+// A subhunk represents a portion of a Hunk.Body, split into three sections.
+// It consists of zero or more context lines, followed by zero or more orig
+// lines and then zero or more new lines.
+//
+// Each line is stored WITHOUT its starting character, but with the newlines
+// included. The final entry in a section may be missing a trailing newline.
+//
+// A missing newline in orig is represented in a Hunk by OrigNoNewlineAt,
+// but is represented here as a missing newline.
+type contextLine struct {
+ body []byte
+ bare bool
+}
+
+type subhunk struct {
+ context []contextLine
+ orig [][]byte
+ new [][]byte
+}
+
+// reverseHunk converts a Hunk into its reverse operation.
+func reverseHunk(forward *Hunk) (*Hunk, error) {
+ reverse := Hunk{
+ OrigStartLine: forward.NewStartLine,
+ OrigLines: forward.NewLines,
+ OrigNoNewlineAt: 0, // we may change this below
+ NewStartLine: forward.OrigStartLine,
+ NewLines: forward.OrigLines,
+ Section: forward.Section,
+ StartPosition: forward.StartPosition,
+ }
+ subs, err := toSubhunks(forward)
+ if err != nil {
+ return nil, err
+ }
+ for _, sub := range subs {
+ invSub := subhunk{
+ context: sub.context,
+ orig: sub.new,
+ new: sub.orig,
+ }
+ for _, line := range invSub.context {
+ if line.bare {
+ reverse.Body = append(reverse.Body, line.body...)
+ continue
+ }
+ reverse.Body = append(reverse.Body, ' ')
+ reverse.Body = append(reverse.Body, line.body...)
+ }
+ for _, line := range invSub.orig {
+ reverse.Body = append(reverse.Body, '-')
+ reverse.Body = append(reverse.Body, line...)
+ }
+ if len(invSub.orig) > 0 && reverse.Body[len(reverse.Body)-1] != '\n' {
+ // There was a missing newline in `orig`, which we encode in a
+ // hunk with an offset.
+ reverse.Body = append(reverse.Body, '\n')
+ reverse.OrigNoNewlineAt = int32(len(reverse.Body))
+ }
+ for _, line := range invSub.new {
+ reverse.Body = append(reverse.Body, '+')
+ reverse.Body = append(reverse.Body, line...)
+ }
+ }
+ return &reverse, nil
+}
+
+func extractContextLines(from *[]byte) []contextLine {
+ var lines []contextLine
+ for len(*from) > 0 {
+ if (*from)[0] == '\n' {
+ lines = append(lines, contextLine{body: []byte{'\n'}, bare: true})
+ *from = (*from)[1:]
+ continue
+ }
+ if (*from)[0] != ' ' {
+ break
+ }
+
+ newline := bytes.IndexByte(*from, '\n')
+ if newline < 0 {
+ lines = append(lines, contextLine{body: (*from)[1:]})
+ *from = nil
+ continue
+ }
+
+ lines = append(lines, contextLine{body: (*from)[1 : newline+1]})
+ *from = (*from)[newline+1:]
+ }
+ return lines
+}
+
+func extractLinesStartingWith(from *[]byte, startingWith byte) [][]byte {
+ var lines [][]byte
+ for len(*from) > 0 {
+ if (*from)[0] != startingWith {
+ break
+ }
+
+ newline := bytes.IndexByte(*from, '\n')
+ if newline < 0 {
+ lines = append(lines, (*from)[1:])
+ *from = nil
+ continue
+ }
+
+ lines = append(lines, (*from)[1:newline+1])
+ *from = (*from)[newline+1:]
+ }
+ return lines
+}
+
+// Extracts the subhunks from a diff.Hunk.
+//
+// This groups a Hunk's buffer into one or more subhunks, matching the conditions
+// of `subhunk` above. This function groups, strips prefix characters, and strips
+// a newline for `OrigNoNewlineAt` if necessary.
+func toSubhunks(hunk *Hunk) ([]subhunk, error) {
+ var body []byte = hunk.Body
+ var subhunks []subhunk
+ if len(body) == 0 {
+ return nil, nil
+ }
+ for len(body) > 0 {
+ sh := subhunk{
+ context: extractContextLines(&body),
+ orig: extractLinesStartingWith(&body, '-'),
+ new: extractLinesStartingWith(&body, '+'),
+ }
+ if len(sh.context) == 0 && len(sh.orig) == 0 && len(sh.new) == 0 {
+ // The first line didn't start with any expected prefix.
+ return nil, fmt.Errorf("unexpected character %q at start of line", body[0])
+ }
+ subhunks = append(subhunks, sh)
+ }
+ if hunk.OrigNoNewlineAt > 0 {
+ // The Hunk represents a missing newline at the end of an "orig" line with a
+ // OrigNoNewlineAt index. We represent it here as an actual missing newline.
+ var lastSubhunk *subhunk = &subhunks[len(subhunks)-1]
+ s := len(lastSubhunk.orig)
+ if s == 0 {
+ return nil, errors.New("inconsistent OrigNoNewlineAt in input")
+ }
+ var cut bool
+ lastSubhunk.orig[s-1], cut = bytes.CutSuffix(lastSubhunk.orig[s-1], []byte("\n"))
+ if !cut {
+ return nil, errors.New("missing newline in input")
+ }
+ }
+ return subhunks, nil
+}
diff --git a/hack/tools/vendor/github.com/tetafro/godot/.golangci.yml b/hack/tools/vendor/github.com/tetafro/godot/.golangci.yml
index 2b6261868ac..9679efa79d5 100644
--- a/hack/tools/vendor/github.com/tetafro/godot/.golangci.yml
+++ b/hack/tools/vendor/github.com/tetafro/godot/.golangci.yml
@@ -1,9 +1,8 @@
+version: "2"
run:
concurrency: 2
- timeout: 5m
-
linters:
- disable-all: true
+ default: none
enable:
- asciicheck
- bodyclose
@@ -22,12 +21,8 @@ linters:
- gocritic
- gocyclo
- godot
- - gofmt
- - gofumpt
- - goimports
- goprintffuncname
- gosec
- - gosimple
- govet
- importas
- ineffassign
@@ -41,38 +36,39 @@ linters:
- revive
- rowserrcheck
- sqlclosecheck
- - sqlclosecheck
- staticcheck
- - stylecheck
- - typecheck
- unconvert
- unparam
- unused
- wastedassign
- whitespace
- wrapcheck
-
-linters-settings:
- godot:
- scope: toplevel
-
-issues:
- exclude-use-default: false
- exclude:
- - "do not define dynamic errors, use wrapped static errors instead"
- exclude-files:
- - ./testdata/
- exclude-rules:
- - path: _test\.go
- linters:
- - dupl
- - errcheck
- - funlen
- - gocognit
- - cyclop
- - gosec
- - noctx
- - path: main\.go
- linters:
- - cyclop
- - gomnd
+ exclusions:
+ rules:
+ - path: _test\.go
+ linters:
+ - cyclop
+ - dupl
+ - errcheck
+ - gocognit
+ - goconst
+ - gocyclo
+ - gosec
+ - noctx
+ - path: main\.go
+ linters:
+ - cyclop
+ - gocognit
+ - path: main\.go
+ text: '`defer cancel\(\)` will not run'
+ - path: (.+)\.go$
+ text: 'G404: Use of weak random number generator'
+ - path: (.+)\.go$
+ text: do not define dynamic errors, use wrapped static errors instead
+ - path: (.+)\.go$
+ text: Error return value of `.*.Body.Close` is not checked
+formatters:
+ enable:
+ - gofmt
+ - gofumpt
+ - goimports
diff --git a/hack/tools/vendor/github.com/tetafro/godot/.goreleaser.yml b/hack/tools/vendor/github.com/tetafro/godot/.goreleaser.yml
index 2f0c2466a5d..ff5992025f8 100644
--- a/hack/tools/vendor/github.com/tetafro/godot/.goreleaser.yml
+++ b/hack/tools/vendor/github.com/tetafro/godot/.goreleaser.yml
@@ -5,7 +5,7 @@ builds:
checksum:
name_template: checksums.txt
snapshot:
- name_template: "{{ .Tag }}"
+ version_template: "{{ .Tag }}"
changelog:
sort: asc
filters:
diff --git a/hack/tools/vendor/github.com/tetafro/godot/checks.go b/hack/tools/vendor/github.com/tetafro/godot/checks.go
index 0301fa93c78..13e867fb5a8 100644
--- a/hack/tools/vendor/github.com/tetafro/godot/checks.go
+++ b/hack/tools/vendor/github.com/tetafro/godot/checks.go
@@ -111,7 +111,9 @@ func checkPeriod(c comment) *Issue {
// Get the offset of the first symbol in the last line of the comment.
// This value is used only in golangci-lint to point to the problem,
// and to replace the line when running in auto-fix mode.
- offset := c.start.Offset
+ // For inline comments, the line starts before the comment, so we
+ // subtract the column offset to get the line start.
+ offset := c.start.Offset - (c.start.Column - 1)
for i := 0; i < pos.line-1; i++ {
offset += len(c.lines[i]) + 1
}
@@ -218,7 +220,9 @@ func checkCapital(c comment) []Issue {
// Get the offset of the first symbol in the current issue's line.
// This value is used only in golangci-lint to point to the problem,
// and to replace the line when running in auto-fix mode.
- offset := c.start.Offset
+ // For inline comments, the line starts before the comment, so we
+ // subtract the column offset to get the line start.
+ offset := c.start.Offset - (c.start.Column - 1)
for i := 0; i < pos.line-1; i++ {
offset += len(c.lines[i]) + 1
}
diff --git a/hack/tools/vendor/github.com/tetafro/godot/file.go b/hack/tools/vendor/github.com/tetafro/godot/file.go
index 19b0ebe92d4..7b878c2930c 100644
--- a/hack/tools/vendor/github.com/tetafro/godot/file.go
+++ b/hack/tools/vendor/github.com/tetafro/godot/file.go
@@ -87,6 +87,8 @@ func (pf *parsedFile) getComments(scope Scope, exclude []*regexp.Regexp) []comme
// getBlockComments gets comments from the inside of top level blocks:
// var (...), const (...).
+//
+//nolint:cyclop
func (pf *parsedFile) getBlockComments(exclude []*regexp.Regexp) []comment {
var comments []comment
for _, decl := range pf.file.Decls {
@@ -109,12 +111,14 @@ func (pf *parsedFile) getBlockComments(exclude []*regexp.Regexp) []comment {
// Skip comments that are not top-level for this block
// (the block itself is top level, so comments inside this block
// would be on column 2)
- //nolint:gomnd
if pf.fset.Position(c.Pos()).Column != 2 {
continue
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
text: getText(c, exclude),
@@ -127,7 +131,7 @@ func (pf *parsedFile) getBlockComments(exclude []*regexp.Regexp) []comment {
// getTopLevelComments gets all top level comments.
func (pf *parsedFile) getTopLevelComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, c := range pf.file.Comments {
if c == nil || len(c.List) == 0 {
continue
@@ -137,6 +141,9 @@ func (pf *parsedFile) getTopLevelComments(exclude []*regexp.Regexp) []comment {
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
text: getText(c, exclude),
@@ -148,7 +155,7 @@ func (pf *parsedFile) getTopLevelComments(exclude []*regexp.Regexp) []comment {
// getDeclarationComments gets top level declaration comments.
func (pf *parsedFile) getDeclarationComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, decl := range pf.file.Decls {
var cg *ast.CommentGroup
switch d := decl.(type) {
@@ -164,6 +171,9 @@ func (pf *parsedFile) getDeclarationComments(exclude []*regexp.Regexp) []comment
firstLine := pf.fset.Position(cg.Pos()).Line
lastLine := pf.fset.Position(cg.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
text: getText(cg, exclude),
@@ -175,13 +185,16 @@ func (pf *parsedFile) getDeclarationComments(exclude []*regexp.Regexp) []comment
// getNoInlineComments gets all except inline comments.
func (pf *parsedFile) getNoInlineComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, c := range pf.file.Comments {
if c == nil || len(c.List) == 0 {
continue
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
c := comment{
lines: pf.lines[firstLine-1 : lastLine],
@@ -203,13 +216,16 @@ func (pf *parsedFile) getNoInlineComments(exclude []*regexp.Regexp) []comment {
// getAllComments gets every single comment from the file.
func (pf *parsedFile) getAllComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, c := range pf.file.Comments {
if c == nil || len(c.List) == 0 {
continue
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
start: pf.fset.Position(c.List[0].Slash),
diff --git a/hack/tools/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go b/hack/tools/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go
index ae860d728c0..4a862521ff3 100644
--- a/hack/tools/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go
+++ b/hack/tools/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go
@@ -16,12 +16,18 @@ import (
var Analyzer = &analysis.Analyzer{
Name: "bodyclose",
Doc: Doc,
- Run: new(runner).run,
+ Run: run,
Requires: []*analysis.Analyzer{
buildssa.Analyzer,
},
}
+func init() {
+ Analyzer.Flags.BoolVar(&checkConsumptionFlag, "check-consumption", false, "also check that response body is consumed")
+}
+
+var checkConsumptionFlag bool
+
const (
Doc = "checks whether HTTP response body is closed successfully"
@@ -30,18 +36,21 @@ const (
)
type runner struct {
- pass *analysis.Pass
- resObj types.Object
- resTyp *types.Pointer
- bodyObj types.Object
- closeMthd *types.Func
- skipFile map[*ast.File]bool
+ pass *analysis.Pass
+ resObj types.Object
+ resTyp *types.Pointer
+ bodyObj types.Object
+ closeMthd *types.Func
+ skipFile map[*ast.File]bool
+ checkConsumption bool
}
-// run executes an analysis for the pass. The receiver is passed
-// by value because this func is called in parallel for different passes.
-func (r runner) run(pass *analysis.Pass) (interface{}, error) {
- r.pass = pass
+// run executes an analysis for the pass
+func run(pass *analysis.Pass) (interface{}, error) {
+ r := runner{
+ pass: pass,
+ checkConsumption: checkConsumptionFlag,
+ }
funcs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs
r.resObj = analysisutil.LookupFromImports(pass.Pkg.Imports(), nethttpPath, "Response")
@@ -96,7 +105,11 @@ FuncLoop:
for i := range b.Instrs {
pos := b.Instrs[i].Pos()
if r.isopen(b, i) {
- pass.Reportf(pos, "response body must be closed")
+ if r.checkConsumption {
+ pass.Reportf(pos, "response body must be closed and consumed")
+ } else {
+ pass.Reportf(pos, "response body must be closed")
+ }
}
}
}
@@ -216,11 +229,8 @@ func (r *runner) isopen(b *ssa.BasicBlock, i int) bool {
if len(*bOp.Referrers()) == 0 {
return true
}
- ccalls := *bOp.Referrers()
- for _, ccall := range ccalls {
- if r.isCloseCall(ccall) {
- return false
- }
+ if r.isBodyProperlyHandled(bOp) {
+ return false
}
}
case *ssa.Phi: // Called in the higher-level block
@@ -242,11 +252,8 @@ func (r *runner) isopen(b *ssa.BasicBlock, i int) bool {
if len(*bOp.Referrers()) == 0 {
return true
}
- ccalls := *bOp.Referrers()
- for _, ccall := range ccalls {
- if r.isCloseCall(ccall) {
- return false
- }
+ if r.isBodyProperlyHandled(bOp) {
+ return false
}
}
}
@@ -268,6 +275,7 @@ func (r *runner) getReqCall(instr ssa.Instruction) (*ssa.Call, bool) {
strings.Contains(callType, "net/http.ResponseController") {
return nil, false
}
+
return call, true
}
@@ -300,6 +308,102 @@ func (r *runner) getBodyOp(instr ssa.Instruction) (*ssa.UnOp, bool) {
return op, true
}
+// isBodyProperlyHandled checks if response body is properly handled (closed and optionally consumed based on flag)
+func (r *runner) isBodyProperlyHandled(bOp *ssa.UnOp) bool {
+ ccalls := *bOp.Referrers()
+
+ for _, ccall := range ccalls {
+ if r.isCloseCall(ccall) {
+ // Early return if consumption checking is disabled
+ if !r.checkConsumption {
+ return true
+ }
+ // Close found and consumption checking enabled - check consumption
+ return r.hasConsumptionForBody(bOp)
+ }
+ }
+
+ // No close call found
+ return false
+}
+
+// hasConsumptionForBody searches the function for consumption calls that use the specific response body
+func (r *runner) hasConsumptionForBody(bodyOp *ssa.UnOp) bool {
+ fn := bodyOp.Block().Parent()
+
+ // Search for consumption functions that specifically consume this response body
+ for _, block := range fn.Blocks {
+ for _, blockInstr := range block.Instrs {
+ if call, ok := blockInstr.(*ssa.Call); ok {
+ if r.isConsumptionFunction(call) && r.isCallUsingBody(call, bodyOp) {
+ return true
+ }
+ }
+ }
+ }
+
+ return false
+}
+
+// isCallUsingBody checks if a consumption function call uses the specific response body
+func (r *runner) isCallUsingBody(call *ssa.Call, responseBodyOp *ssa.UnOp) bool {
+ // Get the FieldAddr of the response body we're checking
+ responseBodyFieldAddr, ok := responseBodyOp.X.(*ssa.FieldAddr)
+ if !ok {
+ return false
+ }
+
+ // Check if any argument to the call refers to this specific response body
+ for _, arg := range call.Call.Args {
+ if r.isArgumentMatchingBody(arg, responseBodyFieldAddr) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// isArgumentMatchingBody checks if a function argument refers to the same response body instance
+func (r *runner) isArgumentMatchingBody(arg ssa.Value, responseBodyFieldAddr *ssa.FieldAddr) bool {
+ switch v := arg.(type) {
+ case *ssa.FieldAddr:
+ // Direct field access - check if it's accessing Body field of same response
+ return v.X == responseBodyFieldAddr.X && v.Field == responseBodyFieldAddr.Field
+ case *ssa.UnOp:
+ // Dereference of field access - check if it's dereferencing the same response body field
+ if fieldAddr, ok := v.X.(*ssa.FieldAddr); ok {
+ return fieldAddr.X == responseBodyFieldAddr.X && fieldAddr.Field == responseBodyFieldAddr.Field
+ }
+ case *ssa.ChangeInterface:
+ // Type conversion - check if it converts the response body
+ if unOp, ok := v.X.(*ssa.UnOp); ok {
+ if fieldAddr, ok := unOp.X.(*ssa.FieldAddr); ok {
+ return fieldAddr.X == responseBodyFieldAddr.X && fieldAddr.Field == responseBodyFieldAddr.Field
+ }
+ }
+ }
+ return false
+}
+
+func (r *runner) isConsumptionFunction(call *ssa.Call) bool {
+ if call.Call.StaticCallee() != nil {
+ callee := call.Call.StaticCallee()
+ if callee.Pkg != nil {
+ pkg := callee.Pkg.Pkg.Path()
+ name := callee.Name()
+
+ // Check for known consumption functions
+ if (pkg == "io" && (name == "Copy" || name == "ReadAll")) ||
+ (pkg == "io/ioutil" && name == "ReadAll") ||
+ (pkg == "encoding/json" && name == "NewDecoder") ||
+ (pkg == "bufio" && (name == "NewScanner" || name == "NewReader")) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func (r *runner) isCloseCall(ccall ssa.Instruction) bool {
switch ccall := ccall.(type) {
case *ssa.Defer:
diff --git a/hack/tools/vendor/github.com/uudashr/iface/identical/identical.go b/hack/tools/vendor/github.com/uudashr/iface/identical/identical.go
index 0f470e547f7..18c3ff060e3 100644
--- a/hack/tools/vendor/github.com/uudashr/iface/identical/identical.go
+++ b/hack/tools/vendor/github.com/uudashr/iface/identical/identical.go
@@ -55,27 +55,31 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
return
}
- if r.debug {
- fmt.Printf("GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
- }
+ r.debugf("GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
if decl.Tok != token.TYPE {
return
}
+ blockDir := directive.ParseIgnore(decl.Doc)
+ if blockDir != nil && blockDir.ShouldIgnore(pass.Analyzer.Name) {
+ return
+ }
+
for i, spec := range decl.Specs {
- if r.debug {
- fmt.Printf(" spec[%d]: %v %v\n", i, spec, reflect.TypeOf(spec))
- }
+ r.debugf(" spec[%d]: %v %T\n", i, spec, spec)
ts, ok := spec.(*ast.TypeSpec)
if !ok {
- return
+ // this code is unreachable since we already have guard the token type
+ continue
}
+ r.debugf(" -> ts.Type %T\n", ts.Type)
+
ifaceType, ok := ts.Type.(*ast.InterfaceType)
if !ok {
- return
+ continue
}
if r.debug {
@@ -93,9 +97,12 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
}
}
- dir := directive.ParseIgnore(decl.Doc)
+ dir := directive.ParseIgnore(ts.Doc)
+ if dir == nil {
+ dir = blockDir
+ }
+
if dir != nil && dir.ShouldIgnore(pass.Analyzer.Name) {
- // skip due to ignore directive
continue
}
@@ -103,12 +110,12 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
obj := pass.TypesInfo.Defs[ts.Name]
if obj == nil {
- return
+ continue
}
iface, ok := obj.Type().Underlying().(*types.Interface)
if !ok {
- return
+ continue
}
ifaceTypes[ts.Name.Name] = iface
@@ -147,3 +154,9 @@ func (r *runner) debugln(a ...any) {
fmt.Println(a...)
}
}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Printf(format, a...)
+ }
+}
diff --git a/hack/tools/vendor/github.com/uudashr/iface/unexported/unexported.go b/hack/tools/vendor/github.com/uudashr/iface/unexported/unexported.go
index 27a31ff1b0b..55bb7ab8af9 100644
--- a/hack/tools/vendor/github.com/uudashr/iface/unexported/unexported.go
+++ b/hack/tools/vendor/github.com/uudashr/iface/unexported/unexported.go
@@ -4,7 +4,6 @@ import (
"fmt"
"go/ast"
"go/types"
- "reflect"
"github.com/uudashr/iface/internal/directive"
"golang.org/x/tools/go/analysis"
@@ -21,7 +20,7 @@ func newAnalyzer() *analysis.Analyzer {
analyzer := &analysis.Analyzer{
Name: "unexported",
Doc: "Detects interfaces which are not exported but are used as parameters or return values in exported functions or methods.",
- URL: "https://pkg.go.dev/github.com/uudashr/iface/visibility",
+ URL: "https://pkg.go.dev/github.com/uudashr/iface/unexported",
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: r.run,
}
@@ -50,7 +49,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
dir := directive.ParseIgnore(funcDecl.Doc)
if dir != nil && dir.ShouldIgnore(pass.Analyzer.Name) {
// skip ignored function
- r.debugln(" skip ignored")
+ r.debugln(" skip ignored")
return
}
@@ -62,36 +61,36 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
if r.debug {
infoType := pass.TypesInfo.TypeOf(recvType)
- fmt.Println(" recvType:", recvType, "infoType:", infoType, "reflectType:", reflect.TypeOf(recvType))
+ fmt.Printf(" recvType: %v infoType: %v reflectType: %T\n", recvType, infoType, recvType)
}
switch typ := recvType.(type) {
case *ast.Ident:
- r.debugln(" recvIdent:", typ.Name)
+ r.debugln(" recvIdent:", typ.Name)
recvName = typ.Name
case *ast.StarExpr:
- r.debugln(" recvStarExpr:", typ.X)
+ r.debugln(" recvStarExpr:", typ.X)
if ident, ok := typ.X.(*ast.Ident); ok {
- r.debugln(" recvIdent:", ident.Name)
+ r.debugln(" recvIdent:", ident.Name)
recvName = ident.Name
} else {
- r.debugln(" unhandled")
+ r.debugln(" unhandled")
}
default:
- r.debugln(" unhandled")
+ r.debugln(" unhandled")
}
}
if !funcDecl.Name.IsExported() {
// skip unexported functions
- r.debugln(" skip non-exported")
+ r.debugln(" skip non-exported")
return
}
- r.debugln(" params:")
+ r.debugln(" params:")
params := funcDecl.Type.Params
@@ -99,25 +98,25 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
paramType := param.Type
infoType := pass.TypesInfo.TypeOf(paramType)
- r.debugln(" paramType:", paramType, "infoType:", infoType, "reflectType:", reflect.TypeOf(paramType))
+ r.debugf(" paramType: %v infoType: %v reflectType: %T\n", paramType, infoType, paramType)
if !types.IsInterface(infoType) {
// skip non-interface
- r.debugln(" skip non-interface")
+ r.debugln(" skip non-interface")
continue
}
if infoType.String() == "error" {
// skip error interface
- r.debugln(" skip error interface")
+ r.debugln(" skip error interface")
continue
}
if infoType.String() == "any" {
// skip any interface
- r.debugln(" skip any interface")
+ r.debugln(" skip any interface")
continue
}
@@ -125,7 +124,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
switch typ := paramType.(type) {
case *ast.Ident:
if !typ.IsExported() {
- r.debugln(" unexported")
+ r.debugln(" unexported")
funcMethod := "function"
funcMethodName := funcDecl.Name.Name
@@ -141,15 +140,15 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
})
}
default:
- r.debugln(" unhandled")
+ r.debugln(" unhandled")
}
}
- r.debugln(" results:")
+ r.debugln(" results:")
results := funcDecl.Type.Results
if results == nil {
- r.debugln(" no results")
+ r.debugln(" no results")
return
}
@@ -158,24 +157,24 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
resultType := result.Type
infoType := pass.TypesInfo.TypeOf(resultType)
- r.debugln(" resultType:", resultType, "infoType:", infoType, "reflectType:", reflect.TypeOf(resultType))
+ r.debugf(" resultType: %v infoType: %v reflectType: %T\n", resultType, infoType, resultType)
if !types.IsInterface(infoType) {
- r.debugln(" skip non-interface")
+ r.debugln(" skip non-interface")
continue
}
if infoType.String() == "error" {
// skip error interface
- r.debugln(" skip error interface")
+ r.debugln(" skip error interface")
continue
}
if infoType.String() == "any" {
// skip any interface
- r.debugln(" skip any interface")
+ r.debugln(" skip any interface")
continue
}
@@ -183,7 +182,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
switch typ := resultType.(type) {
case *ast.Ident:
if !typ.IsExported() {
- r.debugln(" unexported")
+ r.debugln(" unexported")
funcMethod := "function"
funcMethodName := funcDecl.Name.Name
@@ -199,7 +198,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
})
}
default:
- r.debugln(" unhandled")
+ r.debugln(" unhandled")
}
}
})
@@ -212,3 +211,9 @@ func (r *runner) debugln(a ...any) {
fmt.Println(a...)
}
}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Printf(format, a...)
+ }
+}
diff --git a/hack/tools/vendor/github.com/yuin/gopher-lua/README.md b/hack/tools/vendor/github.com/yuin/gopher-lua/README.md
new file mode 100644
index 00000000000..c51026cd42c
--- /dev/null
+++ b/hack/tools/vendor/github.com/yuin/gopher-lua/README.md
@@ -0,0 +1,833 @@
+# GopherLua: VM and compiler for Lua in Go.
+
+[](https://pkg.go.dev/github.com/yuin/gopher-lua) [](https://github.com/yuin/gopher-lua/actions?query=workflow:test) [](https://coveralls.io/github/yuin/gopher-lua)
+
+GopherLua is a Lua5.1(+ `goto` statement in Lua5.2) VM and compiler written in Go. GopherLua has a same goal
+with Lua: **Be a scripting language with extensible semantics** . It provides
+Go APIs that allow you to easily embed a scripting language to your Go host
+programs.
+
+## Table of Contents
+
+- [Design principle](#design-principle)
+- [How about performance?](#how-about-performance)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Differences between Lua and GopherLua](#differences-between-lua-and-gopherlua)
+- [Standalone interpreter](#standalone-interpreter)
+- [How to Contribute](#how-to-contribute)
+- [Libraries for GopherLua](#libraries-for-gopherlua)
+- [Donation](#donation)
+- [License](#license)
+- [Author](#author)
+
+## Design principle
+
+- Be a scripting language with extensible semantics.
+- User-friendly Go API
+ - The stack based API like the one used in the original Lua
+ implementation will cause a performance improvements in GopherLua
+ (It will reduce memory allocations and concrete type <-> interface conversions).
+ GopherLua API is **not** the stack based API.
+ GopherLua give preference to the user-friendliness over the performance.
+
+## How about performance?
+
+GopherLua is not fast but not too slow, I think.
+
+GopherLua has almost equivalent ( or little bit better ) performance as Python3 on micro benchmarks.
+
+There are some benchmarks on the [wiki page](https://github.com/yuin/gopher-lua/wiki/Benchmarks) .
+
+## Installation
+
+```bash
+$ go get github.com/yuin/gopher-lua
+```
+
+GopherLua supports >= Go1.9.
+
+## Usage
+
+GopherLua APIs perform in much the same way as Lua, **but the stack is used only
+for passing arguments and receiving returned values.**
+
+GopherLua supports channel operations. See **"Goroutines"** section.
+
+Import a package.
+
+```go
+import (
+ "github.com/yuin/gopher-lua"
+)
+```
+
+Run scripts in the VM.
+
+```go
+L := lua.NewState()
+defer L.Close()
+if err := L.DoString(`print("hello")`); err != nil {
+ panic(err)
+}
+```
+
+```go
+L := lua.NewState()
+defer L.Close()
+if err := L.DoFile("hello.lua"); err != nil {
+ panic(err)
+}
+```
+
+Refer to [Lua Reference Manual](http://www.lua.org/manual/5.1/) and [Go doc](http://godoc.org/github.com/yuin/gopher-lua) for further information.
+
+Note that elements that are not commented in [Go doc](http://godoc.org/github.com/yuin/gopher-lua) equivalent to [Lua Reference Manual](http://www.lua.org/manual/5.1/) , except GopherLua uses objects instead of Lua stack indices.
+
+### Data model
+
+All data in a GopherLua program is an `LValue` . `LValue` is an interface
+type that has following methods.
+
+- `String() string`
+- `Type() LValueType`
+
+Objects implement an LValue interface are
+
+| Type name | Go type | Type() value | Constants |
+|-------------|----------------|--------------|----------------------|
+| `LNilType` | (constants) | `LTNil` | `LNil` |
+| `LBool` | (constants) | `LTBool` | `LTrue`, `LFalse` |
+| `LNumber` | float64 | `LTNumber` | `-` |
+| `LString` | string | `LTString` | `-` |
+| `LFunction` | struct pointer | `LTFunction` | `-` |
+| `LUserData` | struct pointer | `LTUserData` | `-` |
+| `LState` | struct pointer | `LTThread` | `-` |
+| `LTable` | struct pointer | `LTTable` | `-` |
+| `LChannel` | chan LValue | `LTChannel` | `-` |
+
+You can test an object type in Go way(type assertion) or using a `Type()` value.
+
+```go
+lv := L.Get(-1) // get the value at the top of the stack
+if str, ok := lv.(lua.LString); ok {
+ // lv is LString
+ fmt.Println(string(str))
+}
+if lv.Type() != lua.LTString {
+ panic("string required.")
+}
+```
+
+```go
+lv := L.Get(-1) // get the value at the top of the stack
+if tbl, ok := lv.(*lua.LTable); ok {
+ // lv is LTable
+ fmt.Println(L.ObjLen(tbl))
+}
+```
+
+Note that `LBool` , `LNumber` , `LString` is not a pointer.
+
+To test `LNilType` and `LBool`, You **must** use pre-defined constants.
+
+```go
+lv := L.Get(-1) // get the value at the top of the stack
+
+if lv == lua.LTrue { // correct
+}
+
+if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong
+}
+```
+
+In Lua, both `nil` and `false` make a condition false. `LVIsFalse` and `LVAsBool` implement this specification.
+
+```go
+lv := L.Get(-1) // get the value at the top of the stack
+if lua.LVIsFalse(lv) { // lv is nil or false
+}
+
+if lua.LVAsBool(lv) { // lv is neither nil nor false
+}
+```
+
+Objects that based on go structs(`LFunction`. `LUserData`, `LTable`)
+have some public methods and fields. You can use these methods and fields for
+performance and debugging, but there are some limitations.
+
+- Metatable does not work.
+- No error handlings.
+
+### Callstack & Registry size
+
+The size of an `LState`'s callstack controls the maximum call depth for Lua functions within a script (Go function calls do not count).
+
+The registry of an `LState` implements stack storage for calling functions (both Lua and Go functions) and also for temporary variables in expressions. Its storage requirements will increase with callstack usage and also with code complexity.
+
+Both the registry and the callstack can be set to either a fixed size or to auto size.
+
+When you have a large number of `LStates` instantiated in a process, it's worth taking the time to tune the registry and callstack options.
+
+#### Registry
+
+The registry can have an initial size, a maximum size and a step size configured on a per `LState` basis. This will allow the registry to grow as needed. It will not shrink again after growing.
+
+```go
+L := lua.NewState(lua.Options{
+ RegistrySize: 1024 * 20, // this is the initial size of the registry
+ RegistryMaxSize: 1024 * 80, // this is the maximum size that the registry can grow to. If set to `0` (the default) then the registry will not auto grow
+ RegistryGrowStep: 32, // this is how much to step up the registry by each time it runs out of space. The default is `32`.
+})
+defer L.Close()
+```
+
+A registry which is too small for a given script will ultimately result in a panic. A registry which is too big will waste memory (which can be significant if many `LStates` are instantiated).
+Auto growing registries incur a small performance hit at the point they are resized but will not otherwise affect performance.
+
+#### Callstack
+
+The callstack can operate in two different modes, fixed or auto size.
+A fixed size callstack has the highest performance and has a fixed memory overhead.
+An auto sizing callstack will allocate and release callstack pages on demand which will ensure the minimum amount of memory is in use at any time. The downside is it will incur a small performance impact every time a new page of callframes is allocated.
+By default an `LState` will allocate and free callstack frames in pages of 8, so the allocation overhead is not incurred on every function call. It is very likely that the performance impact of an auto resizing callstack will be negligible for most use cases.
+
+```go
+L := lua.NewState(lua.Options{
+ CallStackSize: 120, // this is the maximum callstack size of this LState
+ MinimizeStackMemory: true, // Defaults to `false` if not specified. If set, the callstack will auto grow and shrink as needed up to a max of `CallStackSize`. If not set, the callstack will be fixed at `CallStackSize`.
+})
+defer L.Close()
+```
+
+#### Option defaults
+
+The above examples show how to customize the callstack and registry size on a per `LState` basis. You can also adjust some defaults for when options are not specified by altering the values of `lua.RegistrySize`, `lua.RegistryGrowStep` and `lua.CallStackSize`.
+
+An `LState` object that has been created by `*LState#NewThread()` inherits the callstack & registry size from the parent `LState` object.
+
+### Miscellaneous lua.NewState options
+
+- **Options.SkipOpenLibs bool(default false)**
+ - By default, GopherLua opens all built-in libraries when new LState is created.
+ - You can skip this behaviour by setting this to `true` .
+ - Using the various `OpenXXX(L *LState) int` functions you can open only those libraries that you require, for an example see below.
+- **Options.IncludeGoStackTrace bool(default false)**
+ - By default, GopherLua does not show Go stack traces when panics occur.
+ - You can get Go stack traces by setting this to `true` .
+
+### API
+
+Refer to [Lua Reference Manual](http://www.lua.org/manual/5.1/) and [Go doc(LState methods)](http://godoc.org/github.com/yuin/gopher-lua) for further information.
+
+#### Calling Go from Lua
+
+```go
+func Double(L *lua.LState) int {
+ lv := L.ToInt(1) /* get argument */
+ L.Push(lua.LNumber(lv * 2)) /* push result */
+ return 1 /* number of results */
+}
+
+func main() {
+ L := lua.NewState()
+ defer L.Close()
+ L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */
+}
+```
+
+```lua
+print(double(20)) -- > "40"
+```
+
+Any function registered with GopherLua is a `lua.LGFunction`, defined in `value.go`
+
+```go
+type LGFunction func(*LState) int
+```
+
+Working with coroutines.
+
+```go
+co, _ := L.NewThread() /* create a new thread */
+fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */
+for {
+ st, err, values := L.Resume(co, fn)
+ if st == lua.ResumeError {
+ fmt.Println("yield break(error)")
+ fmt.Println(err.Error())
+ break
+ }
+
+ for i, lv := range values {
+ fmt.Printf("%v : %v\n", i, lv)
+ }
+
+ if st == lua.ResumeOK {
+ fmt.Println("yield break(ok)")
+ break
+ }
+}
+```
+
+#### Opening a subset of builtin modules
+
+The following demonstrates how to open a subset of the built-in modules in Lua, say for example to avoid enabling modules with access to local files or system calls.
+
+main.go
+
+```go
+func main() {
+ L := lua.NewState(lua.Options{SkipOpenLibs: true})
+ defer L.Close()
+ for _, pair := range []struct {
+ n string
+ f lua.LGFunction
+ }{
+ {lua.LoadLibName, lua.OpenPackage}, // Must be first
+ {lua.BaseLibName, lua.OpenBase},
+ {lua.TabLibName, lua.OpenTable},
+ } {
+ if err := L.CallByParam(lua.P{
+ Fn: L.NewFunction(pair.f),
+ NRet: 0,
+ Protect: true,
+ }, lua.LString(pair.n)); err != nil {
+ panic(err)
+ }
+ }
+ if err := L.DoFile("main.lua"); err != nil {
+ panic(err)
+ }
+}
+```
+
+#### Creating a module by Go
+
+mymodule.go
+
+```go
+package mymodule
+
+import (
+ "github.com/yuin/gopher-lua"
+)
+
+func Loader(L *lua.LState) int {
+ // register functions to the table
+ mod := L.SetFuncs(L.NewTable(), exports)
+ // register other stuff
+ L.SetField(mod, "name", lua.LString("value"))
+
+ // returns the module
+ L.Push(mod)
+ return 1
+}
+
+var exports = map[string]lua.LGFunction{
+ "myfunc": myfunc,
+}
+
+func myfunc(L *lua.LState) int {
+ return 0
+}
+```
+
+mymain.go
+
+```go
+package main
+
+import (
+ "./mymodule"
+ "github.com/yuin/gopher-lua"
+)
+
+func main() {
+ L := lua.NewState()
+ defer L.Close()
+ L.PreloadModule("mymodule", mymodule.Loader)
+ if err := L.DoFile("main.lua"); err != nil {
+ panic(err)
+ }
+}
+```
+
+main.lua
+
+```lua
+local m = require("mymodule")
+m.myfunc()
+print(m.name)
+```
+
+#### Calling Lua from Go
+
+```go
+L := lua.NewState()
+defer L.Close()
+if err := L.DoFile("double.lua"); err != nil {
+ panic(err)
+}
+if err := L.CallByParam(lua.P{
+ Fn: L.GetGlobal("double"),
+ NRet: 1,
+ Protect: true,
+ }, lua.LNumber(10)); err != nil {
+ panic(err)
+}
+ret := L.Get(-1) // returned value
+L.Pop(1) // remove received value
+```
+
+If `Protect` is false, GopherLua will panic instead of returning an `error` value.
+
+#### User-Defined types
+
+You can extend GopherLua with new types written in Go.
+`LUserData` is provided for this purpose.
+
+```go
+type Person struct {
+ Name string
+}
+
+const luaPersonTypeName = "person"
+
+// Registers my person type to given L.
+func registerPersonType(L *lua.LState) {
+ mt := L.NewTypeMetatable(luaPersonTypeName)
+ L.SetGlobal("person", mt)
+ // static attributes
+ L.SetField(mt, "new", L.NewFunction(newPerson))
+ // methods
+ L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods))
+}
+
+// Constructor
+func newPerson(L *lua.LState) int {
+ person := &Person{L.CheckString(1)}
+ ud := L.NewUserData()
+ ud.Value = person
+ L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName))
+ L.Push(ud)
+ return 1
+}
+
+// Checks whether the first lua argument is a *LUserData with *Person and returns this *Person.
+func checkPerson(L *lua.LState) *Person {
+ ud := L.CheckUserData(1)
+ if v, ok := ud.Value.(*Person); ok {
+ return v
+ }
+ L.ArgError(1, "person expected")
+ return nil
+}
+
+var personMethods = map[string]lua.LGFunction{
+ "name": personGetSetName,
+}
+
+// Getter and setter for the Person#Name
+func personGetSetName(L *lua.LState) int {
+ p := checkPerson(L)
+ if L.GetTop() == 2 {
+ p.Name = L.CheckString(2)
+ return 0
+ }
+ L.Push(lua.LString(p.Name))
+ return 1
+}
+
+func main() {
+ L := lua.NewState()
+ defer L.Close()
+ registerPersonType(L)
+ if err := L.DoString(`
+ p = person.new("Steeve")
+ print(p:name()) -- "Steeve"
+ p:name("Alice")
+ print(p:name()) -- "Alice"
+ `); err != nil {
+ panic(err)
+ }
+}
+```
+
+#### Terminating a running LState
+
+GopherLua supports the [Go Concurrency Patterns: Context](https://blog.golang.org/context) .
+
+```go
+L := lua.NewState()
+defer L.Close()
+ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
+defer cancel()
+// set the context to our LState
+L.SetContext(ctx)
+err := L.DoString(`
+ local clock = os.clock
+ function sleep(n) -- seconds
+ local t0 = clock()
+ while clock() - t0 <= n do end
+ end
+ sleep(3)
+`)
+// err.Error() contains "context deadline exceeded"
+```
+
+With coroutines
+
+```go
+L := lua.NewState()
+defer L.Close()
+ctx, cancel := context.WithCancel(context.Background())
+L.SetContext(ctx)
+defer cancel()
+L.DoString(`
+ function coro()
+ local i = 0
+ while true do
+ coroutine.yield(i)
+ i = i+1
+ end
+ return i
+ end
+`)
+co, cocancel := L.NewThread()
+defer cocancel()
+fn := L.GetGlobal("coro").(*LFunction)
+
+_, err, values := L.Resume(co, fn) // err is nil
+
+cancel() // cancel the parent context
+
+_, err, values = L.Resume(co, fn) // err is NOT nil : child context was canceled
+```
+
+**Note that using a context causes performance degradation.**
+
+```
+time ./glua-with-context.exe fib.lua
+9227465
+0.01s user 0.11s system 1% cpu 7.505 total
+
+time ./glua-without-context.exe fib.lua
+9227465
+0.01s user 0.01s system 0% cpu 5.306 total
+```
+
+#### Sharing Lua byte code between LStates
+
+Calling `DoFile` will load a Lua script, compile it to byte code and run the byte code in a `LState`.
+
+If you have multiple `LStates` which are all required to run the same script, you can share the byte code between them,
+which will save on memory.
+Sharing byte code is safe as it is read only and cannot be altered by lua scripts.
+
+```go
+// CompileLua reads the passed lua file from disk and compiles it.
+func CompileLua(filePath string) (*lua.FunctionProto, error) {
+ file, err := os.Open(filePath)
+ defer file.Close()
+ if err != nil {
+ return nil, err
+ }
+ reader := bufio.NewReader(file)
+ chunk, err := parse.Parse(reader, filePath)
+ if err != nil {
+ return nil, err
+ }
+ proto, err := lua.Compile(chunk, filePath)
+ if err != nil {
+ return nil, err
+ }
+ return proto, nil
+}
+
+// DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent
+// to calling DoFile on the LState with the original source file.
+func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
+ lfunc := L.NewFunctionFromProto(proto)
+ L.Push(lfunc)
+ return L.PCall(0, lua.MultRet, nil)
+}
+
+// Example shows how to share the compiled byte code from a lua script between multiple VMs.
+func Example() {
+ codeToShare, err := CompileLua("mylua.lua")
+ if err != nil {
+ panic(err)
+ }
+ a := lua.NewState()
+ b := lua.NewState()
+ c := lua.NewState()
+ DoCompiledFile(a, codeToShare)
+ DoCompiledFile(b, codeToShare)
+ DoCompiledFile(c, codeToShare)
+}
+```
+
+#### Goroutines
+
+The `LState` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels.
+
+Channels are represented by `channel` objects in GopherLua. And a `channel` table provides functions for performing channel operations.
+
+Some objects can not be sent over channels due to having non-goroutine-safe objects inside itself.
+
+- a thread(state)
+- a function
+- an userdata
+- a table with a metatable
+
+You **must not** send these objects from Go APIs to channels.
+
+```go
+func receiver(ch, quit chan lua.LValue) {
+ L := lua.NewState()
+ defer L.Close()
+ L.SetGlobal("ch", lua.LChannel(ch))
+ L.SetGlobal("quit", lua.LChannel(quit))
+ if err := L.DoString(`
+ local exit = false
+ while not exit do
+ channel.select(
+ {"|<-", ch, function(ok, v)
+ if not ok then
+ print("channel closed")
+ exit = true
+ else
+ print("received:", v)
+ end
+ end},
+ {"|<-", quit, function(ok, v)
+ print("quit")
+ exit = true
+ end}
+ )
+ end
+ `); err != nil {
+ panic(err)
+ }
+}
+
+func sender(ch, quit chan lua.LValue) {
+ L := lua.NewState()
+ defer L.Close()
+ L.SetGlobal("ch", lua.LChannel(ch))
+ L.SetGlobal("quit", lua.LChannel(quit))
+ if err := L.DoString(`
+ ch:send("1")
+ ch:send("2")
+ `); err != nil {
+ panic(err)
+ }
+ ch <- lua.LString("3")
+ quit <- lua.LTrue
+}
+
+func main() {
+ ch := make(chan lua.LValue)
+ quit := make(chan lua.LValue)
+ go receiver(ch, quit)
+ go sender(ch, quit)
+ time.Sleep(3 * time.Second)
+}
+```
+
+##### Go API
+
+`ToChannel`, `CheckChannel`, `OptChannel` are available.
+
+Refer to [Go doc(LState methods)](http://godoc.org/github.com/yuin/gopher-lua) for further information.
+
+##### Lua API
+
+- **channel.make([buf:int]) -> ch:channel**
+ - Create new channel that has a buffer size of `buf`. By default, `buf` is 0.
+
+- **channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}**
+ - Same as the `select` statement in Go. It returns the index of the chosen case and, if that
+ case was a receive operation, the value received and a boolean indicating whether the channel has been closed.
+ - `case` is a table that outlined below.
+ - receiving: `{"|<-", ch:channel [, handler:func(ok, data:any)]}`
+ - sending: `{"<-|", ch:channel, data:any [, handler:func(data:any)]}`
+ - default: `{"default" [, handler:func()]}`
+
+`channel.select` examples:
+
+```lua
+local idx, recv, ok = channel.select(
+ {"|<-", ch1},
+ {"|<-", ch2}
+)
+if not ok then
+ print("closed")
+elseif idx == 1 then -- received from ch1
+ print(recv)
+elseif idx == 2 then -- received from ch2
+ print(recv)
+end
+```
+
+```lua
+channel.select(
+ {"|<-", ch1, function(ok, data)
+ print(ok, data)
+ end},
+ {"<-|", ch2, "value", function(data)
+ print(data)
+ end},
+ {"default", function()
+ print("default action")
+ end}
+)
+```
+
+- **channel:send(data:any)**
+ - Send `data` over the channel.
+- **channel:receive() -> ok:bool, data:any**
+ - Receive some data over the channel.
+- **channel:close()**
+ - Close the channel.
+
+##### The LState pool pattern
+
+To create per-thread LState instances, You can use the `sync.Pool` like mechanism.
+
+```go
+type lStatePool struct {
+ m sync.Mutex
+ saved []*lua.LState
+}
+
+func (pl *lStatePool) Get() *lua.LState {
+ pl.m.Lock()
+ defer pl.m.Unlock()
+ n := len(pl.saved)
+ if n == 0 {
+ return pl.New()
+ }
+ x := pl.saved[n-1]
+ pl.saved = pl.saved[0 : n-1]
+ return x
+}
+
+func (pl *lStatePool) New() *lua.LState {
+ L := lua.NewState()
+ // setting the L up here.
+ // load scripts, set global variables, share channels, etc...
+ return L
+}
+
+func (pl *lStatePool) Put(L *lua.LState) {
+ pl.m.Lock()
+ defer pl.m.Unlock()
+ pl.saved = append(pl.saved, L)
+}
+
+func (pl *lStatePool) Shutdown() {
+ for _, L := range pl.saved {
+ L.Close()
+ }
+}
+
+// Global LState pool
+var luaPool = &lStatePool{
+ saved: make([]*lua.LState, 0, 4),
+}
+```
+
+Now, you can get per-thread LState objects from the `luaPool` .
+
+```go
+func MyWorker() {
+ L := luaPool.Get()
+ defer luaPool.Put(L)
+ /* your code here */
+}
+
+func main() {
+ defer luaPool.Shutdown()
+ go MyWorker()
+ go MyWorker()
+ /* etc... */
+}
+```
+
+## Differences between Lua and GopherLua
+
+### Goroutines
+
+- GopherLua supports channel operations.
+ - GopherLua has a type named `channel`.
+ - The `channel` table provides functions for performing channel operations.
+
+### Unsupported functions
+
+- `string.dump`
+- `os.setlocale`
+- `lua_Debug.namewhat`
+- `package.loadlib`
+- debug hooks
+
+### Miscellaneous notes
+
+- `collectgarbage` does not take any arguments and runs the garbage collector for the entire Go program.
+- `file:setvbuf` does not support a line buffering.
+- Daylight saving time is not supported.
+- GopherLua has a function to set an environment variable : `os.setenv(name, value)`
+- GopherLua support `goto` and `::label::` statement in Lua5.2.
+ - `goto` is a keyword and not a valid variable name.
+
+## Standalone interpreter
+
+Lua has an interpreter called `lua` . GopherLua has an interpreter called `glua` .
+
+```bash
+go get github.com/yuin/gopher-lua/cmd/glua
+```
+
+`glua` has same options as `lua` .
+
+## How to Contribute
+
+See [Guidelines for contributors](https://github.com/yuin/gopher-lua/tree/master/.github/CONTRIBUTING.md) .
+
+## Libraries for GopherLua
+
+- [gopher-luar](https://github.com/layeh/gopher-luar) : Simplifies data passing to and from gopher-lua
+- [gluamapper](https://github.com/yuin/gluamapper) : Mapping a Lua table to a Go struct
+- [gluare](https://github.com/yuin/gluare) : Regular expressions for gopher-lua
+- [gluahttp](https://github.com/cjoudrey/gluahttp) : HTTP request module for gopher-lua
+- [gopher-json](https://github.com/layeh/gopher-json) : A simple JSON encoder/decoder for gopher-lua
+- [gluayaml](https://github.com/kohkimakimoto/gluayaml) : Yaml parser for gopher-lua
+- [glua-lfs](https://github.com/layeh/gopher-lfs) : Partially implements the luafilesystem module for gopher-lua
+- [gluaurl](https://github.com/cjoudrey/gluaurl) : A url parser/builder module for gopher-lua
+- [gluahttpscrape](https://github.com/felipejfc/gluahttpscrape) : A simple HTML scraper module for gopher-lua
+- [gluaxmlpath](https://github.com/ailncode/gluaxmlpath) : An xmlpath module for gopher-lua
+- [gmoonscript](https://github.com/rucuriousyet/gmoonscript) : Moonscript Compiler for the Gopher Lua VM
+- [loguago](https://github.com/rucuriousyet/loguago) : Zerolog wrapper for Gopher-Lua
+- [gluabit32](https://github.com/PeerDB-io/gluabit32) : [Port of Lua 5.2 bit32](https://www.lua.org/manual/5.2/manual.html#6.7)
+- [gluacrypto](https://github.com/tengattack/gluacrypto) : A native Go implementation of crypto library for the GopherLua VM.
+- [gluasql](https://github.com/tengattack/gluasql) : A native Go implementation of SQL client for the GopherLua VM.
+- [purr](https://github.com/leyafo/purr) : A http mock testing tool.
+- [vadv/gopher-lua-libs](https://github.com/vadv/gopher-lua-libs) : Some usefull libraries for GopherLua VM.
+- [gluasocket](https://gitlab.com/megalithic-llc/gluasocket) : A native Go implementation of LuaSocket for the GopherLua VM.
+- [glua-async](https://github.com/CuberL/glua-async) : An async/await implement for gopher-lua.
+- [gopherlua-debugger](https://github.com/edolphin-ydf/gopherlua-debugger) : A debugger for gopher-lua
+- [gluamahonia](https://github.com/super1207/gluamahonia) : An encoding converter for gopher-lua
+- [awesome-gopher-lua](https://github.com/Root-lee/awesome-gopher-lua) : Collections of awesome libraries for GopherLua.
+
+## Donation
+
+BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
+
+## License
+
+MIT
+
+## Author
+
+Yusuke Inuzuka
diff --git a/hack/tools/vendor/github.com/yuin/gopher-lua/README.rst b/hack/tools/vendor/github.com/yuin/gopher-lua/README.rst
deleted file mode 100644
index cc936311069..00000000000
--- a/hack/tools/vendor/github.com/yuin/gopher-lua/README.rst
+++ /dev/null
@@ -1,890 +0,0 @@
-
-===============================================================================
-GopherLua: VM and compiler for Lua in Go.
-===============================================================================
-
-.. image:: https://pkg.go.dev/badge/github.com/yuin/gopher-lua.svg
- :target: https://pkg.go.dev/github.com/yuin/gopher-lua
-
-.. image:: https://github.com/yuin/gopher-lua/workflows/test/badge.svg?branch=master&event=push
- :target: https://github.com/yuin/gopher-lua/actions?query=workflow:test
-
-.. image:: https://coveralls.io/repos/github/yuin/gopher-lua/badge.svg?branch=master
- :target: https://coveralls.io/github/yuin/gopher-lua
-
-.. image:: https://badges.gitter.im/Join%20Chat.svg
- :alt: Join the chat at https://gitter.im/yuin/gopher-lua
- :target: https://gitter.im/yuin/gopher-lua?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
-
-|
-
-
-GopherLua is a Lua5.1(+ `goto` statement in Lua5.2) VM and compiler written in Go. GopherLua has a same goal
-with Lua: **Be a scripting language with extensible semantics** . It provides
-Go APIs that allow you to easily embed a scripting language to your Go host
-programs.
-
-.. contents::
- :depth: 1
-
-----------------------------------------------------------------
-Design principle
-----------------------------------------------------------------
-
-- Be a scripting language with extensible semantics.
-- User-friendly Go API
- - The stack based API like the one used in the original Lua
- implementation will cause a performance improvements in GopherLua
- (It will reduce memory allocations and concrete type <-> interface conversions).
- GopherLua API is **not** the stack based API.
- GopherLua give preference to the user-friendliness over the performance.
-
-----------------------------------------------------------------
-How about performance?
-----------------------------------------------------------------
-GopherLua is not fast but not too slow, I think.
-
-GopherLua has almost equivalent ( or little bit better ) performance as Python3 on micro benchmarks.
-
-There are some benchmarks on the `wiki page `_ .
-
-----------------------------------------------------------------
-Installation
-----------------------------------------------------------------
-
-.. code-block:: bash
-
- go get github.com/yuin/gopher-lua
-
-GopherLua supports >= Go1.9.
-
-----------------------------------------------------------------
-Usage
-----------------------------------------------------------------
-GopherLua APIs perform in much the same way as Lua, **but the stack is used only
-for passing arguments and receiving returned values.**
-
-GopherLua supports channel operations. See **"Goroutines"** section.
-
-Import a package.
-
-.. code-block:: go
-
- import (
- "github.com/yuin/gopher-lua"
- )
-
-Run scripts in the VM.
-
-.. code-block:: go
-
- L := lua.NewState()
- defer L.Close()
- if err := L.DoString(`print("hello")`); err != nil {
- panic(err)
- }
-
-.. code-block:: go
-
- L := lua.NewState()
- defer L.Close()
- if err := L.DoFile("hello.lua"); err != nil {
- panic(err)
- }
-
-Refer to `Lua Reference Manual `_ and `Go doc `_ for further information.
-
-Note that elements that are not commented in `Go doc `_ equivalent to `Lua Reference Manual `_ , except GopherLua uses objects instead of Lua stack indices.
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Data model
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-All data in a GopherLua program is an ``LValue`` . ``LValue`` is an interface
-type that has following methods.
-
-- ``String() string``
-- ``Type() LValueType``
-
-
-Objects implement an LValue interface are
-
-================ ========================= ================== =======================
- Type name Go type Type() value Constants
-================ ========================= ================== =======================
- ``LNilType`` (constants) ``LTNil`` ``LNil``
- ``LBool`` (constants) ``LTBool`` ``LTrue``, ``LFalse``
- ``LNumber`` float64 ``LTNumber`` ``-``
- ``LString`` string ``LTString`` ``-``
- ``LFunction`` struct pointer ``LTFunction`` ``-``
- ``LUserData`` struct pointer ``LTUserData`` ``-``
- ``LState`` struct pointer ``LTThread`` ``-``
- ``LTable`` struct pointer ``LTTable`` ``-``
- ``LChannel`` chan LValue ``LTChannel`` ``-``
-================ ========================= ================== =======================
-
-You can test an object type in Go way(type assertion) or using a ``Type()`` value.
-
-.. code-block:: go
-
- lv := L.Get(-1) // get the value at the top of the stack
- if str, ok := lv.(lua.LString); ok {
- // lv is LString
- fmt.Println(string(str))
- }
- if lv.Type() != lua.LTString {
- panic("string required.")
- }
-
-.. code-block:: go
-
- lv := L.Get(-1) // get the value at the top of the stack
- if tbl, ok := lv.(*lua.LTable); ok {
- // lv is LTable
- fmt.Println(L.ObjLen(tbl))
- }
-
-Note that ``LBool`` , ``LNumber`` , ``LString`` is not a pointer.
-
-To test ``LNilType`` and ``LBool``, You **must** use pre-defined constants.
-
-.. code-block:: go
-
- lv := L.Get(-1) // get the value at the top of the stack
-
- if lv == lua.LTrue { // correct
- }
-
- if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong
- }
-
-In Lua, both ``nil`` and ``false`` make a condition false. ``LVIsFalse`` and ``LVAsBool`` implement this specification.
-
-.. code-block:: go
-
- lv := L.Get(-1) // get the value at the top of the stack
- if lua.LVIsFalse(lv) { // lv is nil or false
- }
-
- if lua.LVAsBool(lv) { // lv is neither nil nor false
- }
-
-Objects that based on go structs(``LFunction``. ``LUserData``, ``LTable``)
-have some public methods and fields. You can use these methods and fields for
-performance and debugging, but there are some limitations.
-
-- Metatable does not work.
-- No error handlings.
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Callstack & Registry size
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The size of an ``LState``'s callstack controls the maximum call depth for Lua functions within a script (Go function calls do not count).
-
-The registry of an ``LState`` implements stack storage for calling functions (both Lua and Go functions) and also for temporary variables in expressions. Its storage requirements will increase with callstack usage and also with code complexity.
-
-Both the registry and the callstack can be set to either a fixed size or to auto size.
-
-When you have a large number of ``LStates`` instantiated in a process, it's worth taking the time to tune the registry and callstack options.
-
-+++++++++
-Registry
-+++++++++
-
-The registry can have an initial size, a maximum size and a step size configured on a per ``LState`` basis. This will allow the registry to grow as needed. It will not shrink again after growing.
-
-.. code-block:: go
-
- L := lua.NewState(lua.Options{
- RegistrySize: 1024 * 20, // this is the initial size of the registry
- RegistryMaxSize: 1024 * 80, // this is the maximum size that the registry can grow to. If set to `0` (the default) then the registry will not auto grow
- RegistryGrowStep: 32, // this is how much to step up the registry by each time it runs out of space. The default is `32`.
- })
- defer L.Close()
-
-A registry which is too small for a given script will ultimately result in a panic. A registry which is too big will waste memory (which can be significant if many ``LStates`` are instantiated).
-Auto growing registries incur a small performance hit at the point they are resized but will not otherwise affect performance.
-
-+++++++++
-Callstack
-+++++++++
-
-The callstack can operate in two different modes, fixed or auto size.
-A fixed size callstack has the highest performance and has a fixed memory overhead.
-An auto sizing callstack will allocate and release callstack pages on demand which will ensure the minimum amount of memory is in use at any time. The downside is it will incur a small performance impact every time a new page of callframes is allocated.
-By default an ``LState`` will allocate and free callstack frames in pages of 8, so the allocation overhead is not incurred on every function call. It is very likely that the performance impact of an auto resizing callstack will be negligible for most use cases.
-
-.. code-block:: go
-
- L := lua.NewState(lua.Options{
- CallStackSize: 120, // this is the maximum callstack size of this LState
- MinimizeStackMemory: true, // Defaults to `false` if not specified. If set, the callstack will auto grow and shrink as needed up to a max of `CallStackSize`. If not set, the callstack will be fixed at `CallStackSize`.
- })
- defer L.Close()
-
-++++++++++++++++
-Option defaults
-++++++++++++++++
-
-The above examples show how to customize the callstack and registry size on a per ``LState`` basis. You can also adjust some defaults for when options are not specified by altering the values of ``lua.RegistrySize``, ``lua.RegistryGrowStep`` and ``lua.CallStackSize``.
-
-An ``LState`` object that has been created by ``*LState#NewThread()`` inherits the callstack & registry size from the parent ``LState`` object.
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Miscellaneous lua.NewState options
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- **Options.SkipOpenLibs bool(default false)**
- - By default, GopherLua opens all built-in libraries when new LState is created.
- - You can skip this behaviour by setting this to ``true`` .
- - Using the various `OpenXXX(L *LState) int` functions you can open only those libraries that you require, for an example see below.
-- **Options.IncludeGoStackTrace bool(default false)**
- - By default, GopherLua does not show Go stack traces when panics occur.
- - You can get Go stack traces by setting this to ``true`` .
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-API
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Refer to `Lua Reference Manual `_ and `Go doc(LState methods) `_ for further information.
-
-+++++++++++++++++++++++++++++++++++++++++
-Calling Go from Lua
-+++++++++++++++++++++++++++++++++++++++++
-
-.. code-block:: go
-
- func Double(L *lua.LState) int {
- lv := L.ToInt(1) /* get argument */
- L.Push(lua.LNumber(lv * 2)) /* push result */
- return 1 /* number of results */
- }
-
- func main() {
- L := lua.NewState()
- defer L.Close()
- L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */
- }
-
-.. code-block:: lua
-
- print(double(20)) -- > "40"
-
-Any function registered with GopherLua is a ``lua.LGFunction``, defined in ``value.go``
-
-.. code-block:: go
-
- type LGFunction func(*LState) int
-
-Working with coroutines.
-
-.. code-block:: go
-
- co, _ := L.NewThread() /* create a new thread */
- fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */
- for {
- st, err, values := L.Resume(co, fn)
- if st == lua.ResumeError {
- fmt.Println("yield break(error)")
- fmt.Println(err.Error())
- break
- }
-
- for i, lv := range values {
- fmt.Printf("%v : %v\n", i, lv)
- }
-
- if st == lua.ResumeOK {
- fmt.Println("yield break(ok)")
- break
- }
- }
-
-+++++++++++++++++++++++++++++++++++++++++
-Opening a subset of builtin modules
-+++++++++++++++++++++++++++++++++++++++++
-
-The following demonstrates how to open a subset of the built-in modules in Lua, say for example to avoid enabling modules with access to local files or system calls.
-
-main.go
-
-.. code-block:: go
-
- func main() {
- L := lua.NewState(lua.Options{SkipOpenLibs: true})
- defer L.Close()
- for _, pair := range []struct {
- n string
- f lua.LGFunction
- }{
- {lua.LoadLibName, lua.OpenPackage}, // Must be first
- {lua.BaseLibName, lua.OpenBase},
- {lua.TabLibName, lua.OpenTable},
- } {
- if err := L.CallByParam(lua.P{
- Fn: L.NewFunction(pair.f),
- NRet: 0,
- Protect: true,
- }, lua.LString(pair.n)); err != nil {
- panic(err)
- }
- }
- if err := L.DoFile("main.lua"); err != nil {
- panic(err)
- }
- }
-
-+++++++++++++++++++++++++++++++++++++++++
-Creating a module by Go
-+++++++++++++++++++++++++++++++++++++++++
-
-mymodule.go
-
-.. code-block:: go
-
- package mymodule
-
- import (
- "github.com/yuin/gopher-lua"
- )
-
- func Loader(L *lua.LState) int {
- // register functions to the table
- mod := L.SetFuncs(L.NewTable(), exports)
- // register other stuff
- L.SetField(mod, "name", lua.LString("value"))
-
- // returns the module
- L.Push(mod)
- return 1
- }
-
- var exports = map[string]lua.LGFunction{
- "myfunc": myfunc,
- }
-
- func myfunc(L *lua.LState) int {
- return 0
- }
-
-mymain.go
-
-.. code-block:: go
-
- package main
-
- import (
- "./mymodule"
- "github.com/yuin/gopher-lua"
- )
-
- func main() {
- L := lua.NewState()
- defer L.Close()
- L.PreloadModule("mymodule", mymodule.Loader)
- if err := L.DoFile("main.lua"); err != nil {
- panic(err)
- }
- }
-
-main.lua
-
-.. code-block:: lua
-
- local m = require("mymodule")
- m.myfunc()
- print(m.name)
-
-
-+++++++++++++++++++++++++++++++++++++++++
-Calling Lua from Go
-+++++++++++++++++++++++++++++++++++++++++
-
-.. code-block:: go
-
- L := lua.NewState()
- defer L.Close()
- if err := L.DoFile("double.lua"); err != nil {
- panic(err)
- }
- if err := L.CallByParam(lua.P{
- Fn: L.GetGlobal("double"),
- NRet: 1,
- Protect: true,
- }, lua.LNumber(10)); err != nil {
- panic(err)
- }
- ret := L.Get(-1) // returned value
- L.Pop(1) // remove received value
-
-If ``Protect`` is false, GopherLua will panic instead of returning an ``error`` value.
-
-+++++++++++++++++++++++++++++++++++++++++
-User-Defined types
-+++++++++++++++++++++++++++++++++++++++++
-You can extend GopherLua with new types written in Go.
-``LUserData`` is provided for this purpose.
-
-.. code-block:: go
-
- type Person struct {
- Name string
- }
-
- const luaPersonTypeName = "person"
-
- // Registers my person type to given L.
- func registerPersonType(L *lua.LState) {
- mt := L.NewTypeMetatable(luaPersonTypeName)
- L.SetGlobal("person", mt)
- // static attributes
- L.SetField(mt, "new", L.NewFunction(newPerson))
- // methods
- L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods))
- }
-
- // Constructor
- func newPerson(L *lua.LState) int {
- person := &Person{L.CheckString(1)}
- ud := L.NewUserData()
- ud.Value = person
- L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName))
- L.Push(ud)
- return 1
- }
-
- // Checks whether the first lua argument is a *LUserData with *Person and returns this *Person.
- func checkPerson(L *lua.LState) *Person {
- ud := L.CheckUserData(1)
- if v, ok := ud.Value.(*Person); ok {
- return v
- }
- L.ArgError(1, "person expected")
- return nil
- }
-
- var personMethods = map[string]lua.LGFunction{
- "name": personGetSetName,
- }
-
- // Getter and setter for the Person#Name
- func personGetSetName(L *lua.LState) int {
- p := checkPerson(L)
- if L.GetTop() == 2 {
- p.Name = L.CheckString(2)
- return 0
- }
- L.Push(lua.LString(p.Name))
- return 1
- }
-
- func main() {
- L := lua.NewState()
- defer L.Close()
- registerPersonType(L)
- if err := L.DoString(`
- p = person.new("Steeve")
- print(p:name()) -- "Steeve"
- p:name("Alice")
- print(p:name()) -- "Alice"
- `); err != nil {
- panic(err)
- }
- }
-
-+++++++++++++++++++++++++++++++++++++++++
-Terminating a running LState
-+++++++++++++++++++++++++++++++++++++++++
-GopherLua supports the `Go Concurrency Patterns: Context `_ .
-
-
-.. code-block:: go
-
- L := lua.NewState()
- defer L.Close()
- ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
- defer cancel()
- // set the context to our LState
- L.SetContext(ctx)
- err := L.DoString(`
- local clock = os.clock
- function sleep(n) -- seconds
- local t0 = clock()
- while clock() - t0 <= n do end
- end
- sleep(3)
- `)
- // err.Error() contains "context deadline exceeded"
-
-With coroutines
-
-.. code-block:: go
-
- L := lua.NewState()
- defer L.Close()
- ctx, cancel := context.WithCancel(context.Background())
- L.SetContext(ctx)
- defer cancel()
- L.DoString(`
- function coro()
- local i = 0
- while true do
- coroutine.yield(i)
- i = i+1
- end
- return i
- end
- `)
- co, cocancel := L.NewThread()
- defer cocancel()
- fn := L.GetGlobal("coro").(*LFunction)
-
- _, err, values := L.Resume(co, fn) // err is nil
-
- cancel() // cancel the parent context
-
- _, err, values = L.Resume(co, fn) // err is NOT nil : child context was canceled
-
-**Note that using a context causes performance degradation.**
-
-.. code-block::
-
- time ./glua-with-context.exe fib.lua
- 9227465
- 0.01s user 0.11s system 1% cpu 7.505 total
-
- time ./glua-without-context.exe fib.lua
- 9227465
- 0.01s user 0.01s system 0% cpu 5.306 total
-
-+++++++++++++++++++++++++++++++++++++++++
-Sharing Lua byte code between LStates
-+++++++++++++++++++++++++++++++++++++++++
-Calling ``DoFile`` will load a Lua script, compile it to byte code and run the byte code in a ``LState``.
-
-If you have multiple ``LStates`` which are all required to run the same script, you can share the byte code between them,
-which will save on memory.
-Sharing byte code is safe as it is read only and cannot be altered by lua scripts.
-
-.. code-block:: go
-
- // CompileLua reads the passed lua file from disk and compiles it.
- func CompileLua(filePath string) (*lua.FunctionProto, error) {
- file, err := os.Open(filePath)
- defer file.Close()
- if err != nil {
- return nil, err
- }
- reader := bufio.NewReader(file)
- chunk, err := parse.Parse(reader, filePath)
- if err != nil {
- return nil, err
- }
- proto, err := lua.Compile(chunk, filePath)
- if err != nil {
- return nil, err
- }
- return proto, nil
- }
-
- // DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent
- // to calling DoFile on the LState with the original source file.
- func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
- lfunc := L.NewFunctionFromProto(proto)
- L.Push(lfunc)
- return L.PCall(0, lua.MultRet, nil)
- }
-
- // Example shows how to share the compiled byte code from a lua script between multiple VMs.
- func Example() {
- codeToShare := CompileLua("mylua.lua")
- a := lua.NewState()
- b := lua.NewState()
- c := lua.NewState()
- DoCompiledFile(a, codeToShare)
- DoCompiledFile(b, codeToShare)
- DoCompiledFile(c, codeToShare)
- }
-
-+++++++++++++++++++++++++++++++++++++++++
-Goroutines
-+++++++++++++++++++++++++++++++++++++++++
-The ``LState`` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels.
-
-Channels are represented by ``channel`` objects in GopherLua. And a ``channel`` table provides functions for performing channel operations.
-
-Some objects can not be sent over channels due to having non-goroutine-safe objects inside itself.
-
-- a thread(state)
-- a function
-- an userdata
-- a table with a metatable
-
-You **must not** send these objects from Go APIs to channels.
-
-
-
-.. code-block:: go
-
- func receiver(ch, quit chan lua.LValue) {
- L := lua.NewState()
- defer L.Close()
- L.SetGlobal("ch", lua.LChannel(ch))
- L.SetGlobal("quit", lua.LChannel(quit))
- if err := L.DoString(`
- local exit = false
- while not exit do
- channel.select(
- {"|<-", ch, function(ok, v)
- if not ok then
- print("channel closed")
- exit = true
- else
- print("received:", v)
- end
- end},
- {"|<-", quit, function(ok, v)
- print("quit")
- exit = true
- end}
- )
- end
- `); err != nil {
- panic(err)
- }
- }
-
- func sender(ch, quit chan lua.LValue) {
- L := lua.NewState()
- defer L.Close()
- L.SetGlobal("ch", lua.LChannel(ch))
- L.SetGlobal("quit", lua.LChannel(quit))
- if err := L.DoString(`
- ch:send("1")
- ch:send("2")
- `); err != nil {
- panic(err)
- }
- ch <- lua.LString("3")
- quit <- lua.LTrue
- }
-
- func main() {
- ch := make(chan lua.LValue)
- quit := make(chan lua.LValue)
- go receiver(ch, quit)
- go sender(ch, quit)
- time.Sleep(3 * time.Second)
- }
-
-'''''''''''''''
-Go API
-'''''''''''''''
-
-``ToChannel``, ``CheckChannel``, ``OptChannel`` are available.
-
-Refer to `Go doc(LState methods) `_ for further information.
-
-'''''''''''''''
-Lua API
-'''''''''''''''
-
-- **channel.make([buf:int]) -> ch:channel**
- - Create new channel that has a buffer size of ``buf``. By default, ``buf`` is 0.
-
-- **channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}**
- - Same as the ``select`` statement in Go. It returns the index of the chosen case and, if that
- case was a receive operation, the value received and a boolean indicating whether the channel has been closed.
- - ``case`` is a table that outlined below.
- - receiving: `{"|<-", ch:channel [, handler:func(ok, data:any)]}`
- - sending: `{"<-|", ch:channel, data:any [, handler:func(data:any)]}`
- - default: `{"default" [, handler:func()]}`
-
-``channel.select`` examples:
-
-.. code-block:: lua
-
- local idx, recv, ok = channel.select(
- {"|<-", ch1},
- {"|<-", ch2}
- )
- if not ok then
- print("closed")
- elseif idx == 1 then -- received from ch1
- print(recv)
- elseif idx == 2 then -- received from ch2
- print(recv)
- end
-
-.. code-block:: lua
-
- channel.select(
- {"|<-", ch1, function(ok, data)
- print(ok, data)
- end},
- {"<-|", ch2, "value", function(data)
- print(data)
- end},
- {"default", function()
- print("default action")
- end}
- )
-
-- **channel:send(data:any)**
- - Send ``data`` over the channel.
-- **channel:receive() -> ok:bool, data:any**
- - Receive some data over the channel.
-- **channel:close()**
- - Close the channel.
-
-''''''''''''''''''''''''''''''
-The LState pool pattern
-''''''''''''''''''''''''''''''
-To create per-thread LState instances, You can use the ``sync.Pool`` like mechanism.
-
-.. code-block:: go
-
- type lStatePool struct {
- m sync.Mutex
- saved []*lua.LState
- }
-
- func (pl *lStatePool) Get() *lua.LState {
- pl.m.Lock()
- defer pl.m.Unlock()
- n := len(pl.saved)
- if n == 0 {
- return pl.New()
- }
- x := pl.saved[n-1]
- pl.saved = pl.saved[0 : n-1]
- return x
- }
-
- func (pl *lStatePool) New() *lua.LState {
- L := lua.NewState()
- // setting the L up here.
- // load scripts, set global variables, share channels, etc...
- return L
- }
-
- func (pl *lStatePool) Put(L *lua.LState) {
- pl.m.Lock()
- defer pl.m.Unlock()
- pl.saved = append(pl.saved, L)
- }
-
- func (pl *lStatePool) Shutdown() {
- for _, L := range pl.saved {
- L.Close()
- }
- }
-
- // Global LState pool
- var luaPool = &lStatePool{
- saved: make([]*lua.LState, 0, 4),
- }
-
-Now, you can get per-thread LState objects from the ``luaPool`` .
-
-.. code-block:: go
-
- func MyWorker() {
- L := luaPool.Get()
- defer luaPool.Put(L)
- /* your code here */
- }
-
- func main() {
- defer luaPool.Shutdown()
- go MyWorker()
- go MyWorker()
- /* etc... */
- }
-
-
-----------------------------------------------------------------
-Differences between Lua and GopherLua
-----------------------------------------------------------------
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Goroutines
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-- GopherLua supports channel operations.
- - GopherLua has a type named ``channel``.
- - The ``channel`` table provides functions for performing channel operations.
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Unsupported functions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-- ``string.dump``
-- ``os.setlocale``
-- ``lua_Debug.namewhat``
-- ``package.loadlib``
-- debug hooks
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Miscellaneous notes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-- ``collectgarbage`` does not take any arguments and runs the garbage collector for the entire Go program.
-- ``file:setvbuf`` does not support a line buffering.
-- Daylight saving time is not supported.
-- GopherLua has a function to set an environment variable : ``os.setenv(name, value)``
-- GopherLua support ``goto`` and ``::label::`` statement in Lua5.2.
- - `goto` is a keyword and not a valid variable name.
-
-----------------------------------------------------------------
-Standalone interpreter
-----------------------------------------------------------------
-Lua has an interpreter called ``lua`` . GopherLua has an interpreter called ``glua`` .
-
-.. code-block:: bash
-
- go get github.com/yuin/gopher-lua/cmd/glua
-
-``glua`` has same options as ``lua`` .
-
-----------------------------------------------------------------
-How to Contribute
-----------------------------------------------------------------
-See `Guidlines for contributors `_ .
-
-----------------------------------------------------------------
-Libraries for GopherLua
-----------------------------------------------------------------
-
-- `gopher-luar `_ : Simplifies data passing to and from gopher-lua
-- `gluamapper `_ : Mapping a Lua table to a Go struct
-- `gluare `_ : Regular expressions for gopher-lua
-- `gluahttp `_ : HTTP request module for gopher-lua
-- `gopher-json `_ : A simple JSON encoder/decoder for gopher-lua
-- `gluayaml `_ : Yaml parser for gopher-lua
-- `glua-lfs `_ : Partially implements the luafilesystem module for gopher-lua
-- `gluaurl `_ : A url parser/builder module for gopher-lua
-- `gluahttpscrape `_ : A simple HTML scraper module for gopher-lua
-- `gluaxmlpath `_ : An xmlpath module for gopher-lua
-- `gmoonscript `_ : Moonscript Compiler for the Gopher Lua VM
-- `loguago `_ : Zerolog wrapper for Gopher-Lua
-- `gluacrypto `_ : A native Go implementation of crypto library for the GopherLua VM.
-- `gluasql `_ : A native Go implementation of SQL client for the GopherLua VM.
-- `purr `_ : A http mock testing tool.
-- `vadv/gopher-lua-libs `_ : Some usefull libraries for GopherLua VM.
-- `gluaperiphery `_ : A periphery library for the GopherLua VM (GPIO, SPI, I2C, MMIO, and Serial peripheral I/O for Linux).
-- `glua-async `_ : An async/await implement for gopher-lua.
-- `gopherlua-debugger `_ : A debugger for gopher-lua
-- `gluamahonia `_ : An encoding converter for gopher-lua
-----------------------------------------------------------------
-Donation
-----------------------------------------------------------------
-
-BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
-
-----------------------------------------------------------------
-License
-----------------------------------------------------------------
-MIT
-
-----------------------------------------------------------------
-Author
-----------------------------------------------------------------
-Yusuke Inuzuka
diff --git a/hack/tools/vendor/github.com/yuin/gopher-lua/compile.go b/hack/tools/vendor/github.com/yuin/gopher-lua/compile.go
index c3736777a4d..f9fbf576205 100644
--- a/hack/tools/vendor/github.com/yuin/gopher-lua/compile.go
+++ b/hack/tools/vendor/github.com/yuin/gopher-lua/compile.go
@@ -236,12 +236,13 @@ func (cd *codeStore) PropagateMV(top int, save *int, reg *int, inc int) {
}
func (cd *codeStore) AddLoadNil(a, b, line int) {
- last := cd.Last()
- if opGetOpCode(last) == OP_LOADNIL && (opGetArgA(last)+opGetArgB(last)) == a {
- cd.SetB(cd.LastPC(), b)
- } else {
- cd.AddABC(OP_LOADNIL, a, b, 0, line)
- }
+ // this method used to merge multiple consecutive LOADNIL instructions
+ // of consecutive registers into a single LOADNIL instruction, but it
+ // caused issues when the merged instructions were JMP targets, and so
+ // generated invalid code; so the merging functionality has been removed.
+ // It is safe to merge the LOADNIL instructions under certain conditions,
+ // but additional logic / complexity would be needed here.
+ cd.AddABC(OP_LOADNIL, a, b, 0, line)
}
func (cd *codeStore) SetOpCode(pc int, v int) {
diff --git a/hack/tools/vendor/github.com/yuin/gopher-lua/iolib.go b/hack/tools/vendor/github.com/yuin/gopher-lua/iolib.go
index 3f5f295cedc..ba0b8334fc5 100644
--- a/hack/tools/vendor/github.com/yuin/gopher-lua/iolib.go
+++ b/hack/tools/vendor/github.com/yuin/gopher-lua/iolib.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"os/exec"
"syscall"
@@ -373,7 +372,7 @@ func fileReadAux(L *LState, file *lFile, idx int) int {
L.Push(v)
case 'a':
var buf []byte
- buf, err = ioutil.ReadAll(file.reader)
+ buf, err = io.ReadAll(file.reader)
if err == io.EOF {
L.Push(emptyLString)
goto normalreturn
@@ -404,10 +403,10 @@ normalreturn:
return L.GetTop() - top
errreturn:
- L.RaiseError(err.Error())
- //L.Push(LNil)
- //L.Push(LString(err.Error()))
- return 2
+ L.Push(LNil)
+ L.Push(LString(err.Error()))
+ L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack
+ return 3
}
var fileSeekOptions = []string{"set", "cur", "end"}
@@ -704,7 +703,7 @@ func ioType(L *LState) int {
}
func ioTmpFile(L *LState) int {
- file, err := ioutil.TempFile("", "")
+ file, err := os.CreateTemp("", "")
if err != nil {
L.Push(LNil)
L.Push(LString(err.Error()))
diff --git a/hack/tools/vendor/github.com/yuin/gopher-lua/oslib.go b/hack/tools/vendor/github.com/yuin/gopher-lua/oslib.go
index 5448cc1f8b2..b8ebaea56cf 100644
--- a/hack/tools/vendor/github.com/yuin/gopher-lua/oslib.go
+++ b/hack/tools/vendor/github.com/yuin/gopher-lua/oslib.go
@@ -1,7 +1,6 @@
package lua
import (
- "io/ioutil"
"os"
"strings"
"time"
@@ -223,7 +222,7 @@ func osTime(L *LState) int {
}
func osTmpname(L *LState) int {
- file, err := ioutil.TempFile("", "")
+ file, err := os.CreateTemp("", "")
if err != nil {
L.RaiseError("unable to generate a unique filename")
}
diff --git a/hack/tools/vendor/github.com/yuin/gopher-lua/pm/pm.go b/hack/tools/vendor/github.com/yuin/gopher-lua/pm/pm.go
index e5c651f942e..9abf57ec253 100644
--- a/hack/tools/vendor/github.com/yuin/gopher-lua/pm/pm.go
+++ b/hack/tools/vendor/github.com/yuin/gopher-lua/pm/pm.go
@@ -5,8 +5,11 @@ import (
"fmt"
)
-const EOS = -1
-const _UNKNOWN = -2
+const (
+ EOS = -1
+ _UNKNOWN = -2
+ maxRecursionLevel = 1000000
+)
/* Error {{{ */
@@ -524,7 +527,11 @@ func compilePattern(p pattern, ps ...*iptr) []inst {
// Simple recursive virtual machine based on the
// "Regular Expression Matching: the Virtual Machine Approach" (https://swtch.com/~rsc/regexp/regexp2.html)
-func recursiveVM(src []byte, insts []inst, pc, sp int, ms ...*MatchData) (bool, int, *MatchData) {
+func recursiveVM(src []byte, insts []inst, pc, sp, recLevel int, ms ...*MatchData) (bool, int, *MatchData) {
+ recLevel++
+ if recLevel > maxRecursionLevel {
+ panic(newError(_UNKNOWN, "pattern/input too complex"))
+ }
var m *MatchData
if len(ms) == 0 {
m = newMatchState()
@@ -549,14 +556,14 @@ redo:
pc = inst.Operand1
goto redo
case opSplit:
- if ok, nsp, _ := recursiveVM(src, insts, inst.Operand1, sp, m); ok {
+ if ok, nsp, _ := recursiveVM(src, insts, inst.Operand1, sp, recLevel, m); ok {
return true, nsp, m
}
pc = inst.Operand2
goto redo
case opSave:
s := m.setCapture(inst.Operand1, sp)
- if ok, nsp, _ := recursiveVM(src, insts, pc+1, sp, m); ok {
+ if ok, nsp, _ := recursiveVM(src, insts, pc+1, sp, recLevel, m); ok {
return true, nsp, m
}
m.restoreCapture(inst.Operand1, s)
@@ -620,7 +627,7 @@ func Find(p string, src []byte, offset, limit int) (matches []*MatchData, err er
insts := compilePattern(pat)
matches = []*MatchData{}
for sp := offset; sp <= len(src); {
- ok, nsp, ms := recursiveVM(src, insts, 0, sp)
+ ok, nsp, ms := recursiveVM(src, insts, 0, sp, 0)
sp++
if ok {
if sp < nsp {
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/LICENSE b/hack/tools/vendor/github.com/zclconf/go-cty/LICENSE
new file mode 100644
index 00000000000..9fa5cc744a7
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-2026 Martin Atkins and various other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/capsule.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/capsule.go
new file mode 100644
index 00000000000..2fdc15eaec1
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/capsule.go
@@ -0,0 +1,128 @@
+package cty
+
+import (
+ "fmt"
+ "reflect"
+)
+
+type capsuleType struct {
+ typeImplSigil
+ Name string
+ GoType reflect.Type
+ Ops *CapsuleOps
+}
+
+func (t *capsuleType) Equals(other Type) bool {
+ if otherP, ok := other.typeImpl.(*capsuleType); ok {
+ // capsule types compare by pointer identity
+ return otherP == t
+ }
+ return false
+}
+
+func (t *capsuleType) FriendlyName(mode friendlyTypeNameMode) string {
+ return t.Name
+}
+
+func (t *capsuleType) GoString() string {
+ impl := t.Ops.TypeGoString
+ if impl == nil {
+ // To get a useful representation of our native type requires some
+ // shenanigans.
+ victimVal := reflect.Zero(t.GoType)
+ if t.Ops == noCapsuleOps {
+ return fmt.Sprintf("cty.Capsule(%q, reflect.TypeOf(%#v))", t.Name, victimVal.Interface())
+ } else {
+ // Including the operations in the output will make this _very_ long,
+ // so in practice any capsule type with ops ought to provide a
+ // TypeGoString function to override this with something more
+ // reasonable.
+ return fmt.Sprintf("cty.CapsuleWithOps(%q, reflect.TypeOf(%#v), %#v)", t.Name, victimVal.Interface(), t.Ops)
+ }
+ }
+ return impl(t.GoType)
+}
+
+// Capsule creates a new Capsule type.
+//
+// A Capsule type is a special type that can be used to transport arbitrary
+// Go native values of a given type through the cty type system. A language
+// that uses cty as its type system might, for example, provide functions
+// that return capsule-typed values and then other functions that operate
+// on those values.
+//
+// From cty's perspective, Capsule types have a few interesting characteristics,
+// described in the following paragraphs.
+//
+// Each capsule type has an associated Go native type that it is able to
+// transport. Capsule types compare by identity, so each call to the
+// Capsule function creates an entirely-distinct cty Type, even if two calls
+// use the same native type.
+//
+// Each capsule-typed value contains a pointer to a value of the given native
+// type. A capsule-typed value by default supports no operations except
+// equality, and equality is implemented by pointer identity of the
+// encapsulated pointer. A capsule type can optionally have its own
+// implementations of certain operations if it is created with CapsuleWithOps
+// instead of Capsule.
+//
+// The given name is used as the new type's "friendly name". This can be any
+// string in principle, but will usually be a short, all-lowercase name aimed
+// at users of the embedding language (i.e. not mention Go-specific details)
+// and will ideally not create ambiguity with any predefined cty type.
+//
+// Capsule types are never introduced by any standard cty operation, so a
+// calling application opts in to including them within its own type system
+// by creating them and introducing them via its own functions. At that point,
+// the application is responsible for dealing with any capsule-typed values
+// that might be returned.
+func Capsule(name string, nativeType reflect.Type) Type {
+ return Type{
+ &capsuleType{
+ Name: name,
+ GoType: nativeType,
+ Ops: noCapsuleOps,
+ },
+ }
+}
+
+// CapsuleWithOps is like Capsule except the caller may provide an object
+// representing some overloaded operation implementations to associate with
+// the given capsule type.
+//
+// All of the other caveats and restrictions for capsule types still apply, but
+// overloaded operations can potentially help a capsule type participate better
+// in cty operations.
+func CapsuleWithOps(name string, nativeType reflect.Type, ops *CapsuleOps) Type {
+ // Copy the operations to make sure the caller can't modify them after
+ // we're constructed.
+ ourOps := *ops
+ ourOps.assertValid()
+
+ return Type{
+ &capsuleType{
+ Name: name,
+ GoType: nativeType,
+ Ops: &ourOps,
+ },
+ }
+}
+
+// IsCapsuleType returns true if this type is a capsule type, as created
+// by cty.Capsule .
+func (t Type) IsCapsuleType() bool {
+ _, ok := t.typeImpl.(*capsuleType)
+ return ok
+}
+
+// EncapsulatedType returns the encapsulated native type of a capsule type,
+// or panics if the receiver is not a Capsule type.
+//
+// Is IsCapsuleType to determine if this method is safe to call.
+func (t Type) EncapsulatedType() reflect.Type {
+ impl, ok := t.typeImpl.(*capsuleType)
+ if !ok {
+ panic("not a capsule type")
+ }
+ return impl.GoType
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go
new file mode 100644
index 00000000000..f6ee1981436
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go
@@ -0,0 +1,144 @@
+package cty
+
+import (
+ "reflect"
+)
+
+// CapsuleOps represents a set of overloaded operations for a capsule type.
+//
+// Each field is a reference to a function that can either be nil or can be
+// set to an implementation of the corresponding operation. If an operation
+// function is nil then it isn't supported for the given capsule type.
+type CapsuleOps struct {
+ // GoString provides the GoString implementation for values of the
+ // corresponding type. Conventionally this should return a string
+ // representation of an expression that would produce an equivalent
+ // value.
+ GoString func(val any) string
+
+ // TypeGoString provides the GoString implementation for the corresponding
+ // capsule type itself.
+ TypeGoString func(goTy reflect.Type) string
+
+ // Equals provides the implementation of the Equals operation. This is
+ // called only with known, non-null values of the corresponding type,
+ // but if the corresponding type is a compound type then it must be
+ // ready to detect and handle nested unknown or null values, usually
+ // by recursively calling Value.Equals on those nested values.
+ //
+ // The result value must always be of type cty.Bool, or the Equals
+ // operation will panic.
+ //
+ // If RawEquals is set without also setting Equals, the RawEquals
+ // implementation will be used as a fallback implementation. That fallback
+ // is appropriate only for leaf types that do not contain any nested
+ // cty.Value that would need to distinguish Equals vs. RawEquals for their
+ // own equality.
+ //
+ // If RawEquals is nil then Equals must also be nil, selecting the default
+ // pointer-identity comparison instead.
+ Equals func(a, b any) Value
+
+ // RawEquals provides the implementation of the RawEquals operation.
+ // This is called only with known, non-null values of the corresponding
+ // type, but if the corresponding type is a compound type then it must be
+ // ready to detect and handle nested unknown or null values, usually
+ // by recursively calling Value.RawEquals on those nested values.
+ //
+ // If RawEquals is nil, values of the corresponding type are compared by
+ // pointer identity of the encapsulated value.
+ RawEquals func(a, b any) bool
+
+ // HashKey provides a hashing function for values of the corresponding
+ // capsule type. If defined, cty will use the resulting hashes as part
+ // of the implementation of sets whose element type is or contains the
+ // corresponding capsule type.
+ //
+ // If a capsule type defines HashValue then the function _must_ return
+ // an equal hash value for any two values that would cause Equals or
+ // RawEquals to return true when given those values. If a given type
+ // does not uphold that assumption then sets including this type will
+ // not behave correctly.
+ HashKey func(v any) string
+
+ // ConversionFrom can provide conversions from the corresponding type to
+ // some other type when values of the corresponding type are used with
+ // the "convert" package. (The main cty package does not use this operation.)
+ //
+ // This function itself returns a function, allowing it to switch its
+ // behavior depending on the given source type. Return nil to indicate
+ // that no such conversion is available.
+ ConversionFrom func(src Type) func(any, Path) (Value, error)
+
+ // ConversionTo can provide conversions to the corresponding type from
+ // some other type when values of the corresponding type are used with
+ // the "convert" package. (The main cty package does not use this operation.)
+ //
+ // This function itself returns a function, allowing it to switch its
+ // behavior depending on the given destination type. Return nil to indicate
+ // that no such conversion is available.
+ ConversionTo func(dst Type) func(Value, Path) (any, error)
+
+ // ExtensionData is an extension point for applications that wish to
+ // create their own extension features using capsule types.
+ //
+ // The key argument is any value that can be compared with Go's ==
+ // operator, but should be of a named type in a package belonging to the
+ // application defining the key. An ExtensionData implementation must
+ // check to see if the given key is familar to it, and if so return a
+ // suitable value for the key.
+ //
+ // If the given key is unrecognized, the ExtensionData function must
+ // return a nil interface. (Importantly, not an interface containing a nil
+ // pointer of some other type.)
+ // The common implementation of ExtensionData is a single switch statement
+ // over "key" which has a default case returning nil.
+ //
+ // The meaning of any given key is entirely up to the application that
+ // defines it. Applications consuming ExtensionData from capsule types
+ // should do so defensively: if the result of ExtensionData is not valid,
+ // prefer to ignore it or gracefully produce an error rather than causing
+ // a panic.
+ ExtensionData func(key any) any
+}
+
+// noCapsuleOps is a pointer to a CapsuleOps with no functions set, which
+// is used as the default operations value when a type is created using
+// the Capsule function.
+var noCapsuleOps = &CapsuleOps{}
+
+func (ops *CapsuleOps) assertValid() {
+ if ops.RawEquals == nil && ops.Equals != nil {
+ panic("Equals cannot be set without RawEquals")
+ }
+}
+
+// CapsuleOps returns a pointer to the CapsuleOps value for a capsule type,
+// or panics if the receiver is not a capsule type.
+//
+// The caller must not modify the CapsuleOps.
+func (ty Type) CapsuleOps() *CapsuleOps {
+ if !ty.IsCapsuleType() {
+ panic("not a capsule-typed value")
+ }
+
+ return ty.typeImpl.(*capsuleType).Ops
+}
+
+// CapsuleExtensionData is a convenience interface to the ExtensionData
+// function that can be optionally implemented for a capsule type. It will
+// check to see if the underlying type implements ExtensionData and call it
+// if so. If not, it will return nil to indicate that the given key is not
+// supported.
+//
+// See the documentation for CapsuleOps.ExtensionData for more information
+// on the purpose of and usage of this mechanism.
+//
+// If CapsuleExtensionData is called on a non-capsule type then it will panic.
+func (ty Type) CapsuleExtensionData(key any) any {
+ ops := ty.CapsuleOps()
+ if ops.ExtensionData == nil {
+ return nil
+ }
+ return ops.ExtensionData(key)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/collection.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/collection.go
new file mode 100644
index 00000000000..ab3919b14b7
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/collection.go
@@ -0,0 +1,34 @@
+package cty
+
+import (
+ "errors"
+)
+
+type collectionTypeImpl interface {
+ ElementType() Type
+}
+
+// IsCollectionType returns true if the given type supports the operations
+// that are defined for all collection types.
+func (t Type) IsCollectionType() bool {
+ _, ok := t.typeImpl.(collectionTypeImpl)
+ return ok
+}
+
+// ElementType returns the element type of the receiver if it is a collection
+// type, or panics if it is not. Use IsCollectionType first to test whether
+// this method will succeed.
+func (t Type) ElementType() Type {
+ if ct, ok := t.typeImpl.(collectionTypeImpl); ok {
+ return ct.ElementType()
+ }
+ panic(errors.New("not a collection type"))
+}
+
+// ElementCallback is a callback type used for iterating over elements of
+// collections and attributes of objects.
+//
+// The types of key and value depend on what type is being iterated over.
+// Return true to stop iterating after the current element, or false to
+// continue iterating.
+type ElementCallback func(key Value, val Value) (stop bool)
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go
new file mode 100644
index 00000000000..d84f6ac1049
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/compare_types.go
@@ -0,0 +1,165 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// compareTypes implements a preference order for unification.
+//
+// The result of this method is not useful for anything other than unification
+// preferences, since it assumes that the caller will verify that any suggested
+// conversion is actually possible and it is thus able to to make certain
+// optimistic assumptions.
+func compareTypes(a cty.Type, b cty.Type) int {
+
+ // DynamicPseudoType always has lowest preference, because anything can
+ // convert to it (it acts as a placeholder for "any type") and we want
+ // to optimistically assume that any dynamics will converge on matching
+ // their neighbors.
+ if a == cty.DynamicPseudoType || b == cty.DynamicPseudoType {
+ if a != cty.DynamicPseudoType {
+ return -1
+ }
+ if b != cty.DynamicPseudoType {
+ return 1
+ }
+ return 0
+ }
+
+ if a.IsPrimitiveType() && b.IsPrimitiveType() {
+ // String is a supertype of all primitive types, because we can
+ // represent all primitive values as specially-formatted strings.
+ if a == cty.String || b == cty.String {
+ if a != cty.String {
+ return 1
+ }
+ if b != cty.String {
+ return -1
+ }
+ return 0
+ }
+ }
+
+ if a.IsListType() && b.IsListType() {
+ return compareTypes(a.ElementType(), b.ElementType())
+ }
+ if a.IsSetType() && b.IsSetType() {
+ return compareTypes(a.ElementType(), b.ElementType())
+ }
+ if a.IsMapType() && b.IsMapType() {
+ return compareTypes(a.ElementType(), b.ElementType())
+ }
+
+ // From this point on we may have swapped the two items in order to
+ // simplify our cases. Therefore any non-zero return after this point
+ // must be multiplied by "swap" to potentially invert the return value
+ // if needed.
+ swap := 1
+ switch {
+ case a.IsTupleType() && b.IsListType():
+ fallthrough
+ case a.IsObjectType() && b.IsMapType():
+ fallthrough
+ case a.IsSetType() && b.IsTupleType():
+ fallthrough
+ case a.IsSetType() && b.IsListType():
+ a, b = b, a
+ swap = -1
+ }
+
+ if b.IsSetType() && (a.IsTupleType() || a.IsListType()) {
+ // We'll just optimistically assume that the element types are
+ // unifyable/convertible, and let a second recursive pass
+ // figure out how to make that so.
+ return -1 * swap
+ }
+
+ if a.IsListType() && b.IsTupleType() {
+ // We'll just optimistically assume that the tuple's element types
+ // can be unified into something compatible with the list's element
+ // type.
+ return -1 * swap
+ }
+
+ if a.IsMapType() && b.IsObjectType() {
+ // We'll just optimistically assume that the object's attribute types
+ // can be unified into something compatible with the map's element
+ // type.
+ return -1 * swap
+ }
+
+ // For object and tuple types, comparing two types doesn't really tell
+ // the whole story because it may be possible to construct a new type C
+ // that is the supertype of both A and B by unifying each attribute/element
+ // separately. That possibility is handled by Unify as a follow-up if
+ // type sorting is insufficient to produce a valid result.
+ //
+ // Here we will take care of the simple possibilities where no new type
+ // is needed.
+ if a.IsObjectType() && b.IsObjectType() {
+ atysA := a.AttributeTypes()
+ atysB := b.AttributeTypes()
+
+ if len(atysA) != len(atysB) {
+ return 0
+ }
+
+ hasASuper := false
+ hasBSuper := false
+ for k := range atysA {
+ if _, has := atysB[k]; !has {
+ return 0
+ }
+
+ cmp := compareTypes(atysA[k], atysB[k])
+ if cmp < 0 {
+ hasASuper = true
+ } else if cmp > 0 {
+ hasBSuper = true
+ }
+ }
+
+ switch {
+ case hasASuper && hasBSuper:
+ return 0
+ case hasASuper:
+ return -1 * swap
+ case hasBSuper:
+ return 1 * swap
+ default:
+ return 0
+ }
+ }
+ if a.IsTupleType() && b.IsTupleType() {
+ etysA := a.TupleElementTypes()
+ etysB := b.TupleElementTypes()
+
+ if len(etysA) != len(etysB) {
+ return 0
+ }
+
+ hasASuper := false
+ hasBSuper := false
+ for i := range etysA {
+ cmp := compareTypes(etysA[i], etysB[i])
+ if cmp < 0 {
+ hasASuper = true
+ } else if cmp > 0 {
+ hasBSuper = true
+ }
+ }
+
+ switch {
+ case hasASuper && hasBSuper:
+ return 0
+ case hasASuper:
+ return -1 * swap
+ case hasBSuper:
+ return 1 * swap
+ default:
+ return 0
+ }
+ }
+
+ return 0
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
new file mode 100644
index 00000000000..423b62fc27d
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
@@ -0,0 +1,266 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// conversion is an internal variant of Conversion that carries around
+// a cty.Path to be used in error responses.
+type conversion func(cty.Value, cty.Path) (cty.Value, error)
+
+func getConversion(in cty.Type, out cty.Type, unsafe bool) conversion {
+ conv := getConversionKnown(in, out, unsafe)
+ if conv == nil {
+ return nil
+ }
+
+ // Wrap the conversion in some standard checks that we don't want to
+ // have to repeat in every conversion function.
+ var ret conversion
+ ret = func(in cty.Value, path cty.Path) (cty.Value, error) {
+ if in.IsMarked() {
+ // We must unmark during the conversion and then re-apply the
+ // same marks to the result.
+ in, inMarks := in.Unmark()
+ v, err := ret(in, path)
+ if v != cty.NilVal {
+ v = v.WithMarks(inMarks)
+ }
+ return v, err
+ }
+
+ if out == cty.DynamicPseudoType {
+ // Conversion to DynamicPseudoType always just passes through verbatim.
+ return in, nil
+ }
+ if isKnown, isNull := in.IsKnown(), in.IsNull(); !isKnown || isNull {
+ // Avoid constructing unknown or null values with types which
+ // include optional attributes. Known or non-null object values
+ // will be passed to a conversion function which drops the optional
+ // attributes from the type. Unknown and null pass through values
+ // must do the same to ensure that homogeneous collections have a
+ // single element type.
+ out = out.WithoutOptionalAttributesDeep()
+
+ if !isKnown {
+ return prepareUnknownResult(in.Range(), dynamicReplace(in.Type(), out)), nil
+ }
+
+ if isNull {
+ // We'll pass through nulls, albeit type converted, and let
+ // the caller deal with whatever handling they want to do in
+ // case null values are considered valid in some applications.
+ return cty.NullVal(dynamicReplace(in.Type(), out)), nil
+ }
+ }
+
+ return conv(in, path)
+ }
+
+ return ret
+}
+
+func getConversionKnown(in cty.Type, out cty.Type, unsafe bool) conversion {
+ switch {
+
+ case out == cty.DynamicPseudoType:
+ // Conversion *to* DynamicPseudoType means that the caller wishes
+ // to allow any type in this position, so we'll produce a do-nothing
+ // conversion that just passes through the value as-is.
+ return dynamicPassthrough
+
+ case unsafe && in == cty.DynamicPseudoType:
+ // Conversion *from* DynamicPseudoType means that we have a value
+ // whose type isn't yet known during type checking. For these we will
+ // assume that conversion will succeed and deal with any errors that
+ // result (which is why we can only do this when "unsafe" is set).
+ return dynamicFixup(out)
+
+ case in.IsPrimitiveType() && out.IsPrimitiveType():
+ conv := primitiveConversionsSafe[in][out]
+ if conv != nil {
+ return conv
+ }
+ if unsafe {
+ return primitiveConversionsUnsafe[in][out]
+ }
+ return nil
+
+ case out.IsObjectType() && in.IsObjectType():
+ return conversionObjectToObject(in, out, unsafe)
+
+ case out.IsTupleType() && in.IsTupleType():
+ return conversionTupleToTuple(in, out, unsafe)
+
+ case out.IsListType() && (in.IsListType() || in.IsSetType()):
+ inEty := in.ElementType()
+ outEty := out.ElementType()
+ if inEty.Equals(outEty) {
+ // This indicates that we're converting from list to set with
+ // the same element type, so we don't need an element converter.
+ return conversionCollectionToList(outEty, nil)
+ }
+
+ convEty := getConversion(inEty, outEty, unsafe)
+ if convEty == nil {
+ return nil
+ }
+ return conversionCollectionToList(outEty, convEty)
+
+ case out.IsSetType() && (in.IsListType() || in.IsSetType()):
+ if in.IsListType() && !unsafe {
+ // Conversion from list to map is unsafe because it will lose
+ // information: the ordering will not be preserved, and any
+ // duplicate elements will be conflated.
+ return nil
+ }
+ inEty := in.ElementType()
+ outEty := out.ElementType()
+ convEty := getConversion(inEty, outEty, unsafe)
+ if inEty.Equals(outEty) {
+ // This indicates that we're converting from set to list with
+ // the same element type, so we don't need an element converter.
+ return conversionCollectionToSet(outEty, nil)
+ }
+
+ if convEty == nil {
+ return nil
+ }
+ return conversionCollectionToSet(outEty, convEty)
+
+ case out.IsMapType() && in.IsMapType():
+ inEty := in.ElementType()
+ outEty := out.ElementType()
+ convEty := getConversion(inEty, outEty, unsafe)
+ if convEty == nil {
+ return nil
+ }
+ return conversionCollectionToMap(outEty, convEty)
+
+ case out.IsListType() && in.IsTupleType():
+ outEty := out.ElementType()
+ return conversionTupleToList(in, outEty, unsafe)
+
+ case out.IsSetType() && in.IsTupleType():
+ outEty := out.ElementType()
+ return conversionTupleToSet(in, outEty, unsafe)
+
+ case out.IsMapType() && in.IsObjectType():
+ outEty := out.ElementType()
+ return conversionObjectToMap(in, outEty, unsafe)
+
+ case out.IsObjectType() && in.IsMapType():
+ if !unsafe {
+ // Converting a map to an object is an "unsafe" conversion,
+ // because we don't know if all the map keys will correspond to
+ // object attributes.
+ return nil
+ }
+ return conversionMapToObject(in, out, unsafe)
+
+ case in.IsCapsuleType() || out.IsCapsuleType():
+ if !unsafe {
+ // Capsule types can only participate in "unsafe" conversions,
+ // because we don't know enough about their conversion behaviors
+ // to be sure that they will always be safe.
+ return nil
+ }
+ if in.Equals(out) {
+ // conversion to self is never allowed
+ return nil
+ }
+ if out.IsCapsuleType() {
+ if fn := out.CapsuleOps().ConversionTo; fn != nil {
+ if conv := conversionToCapsule(in, out, fn); conv != nil {
+ return conv
+ }
+ }
+ }
+ if in.IsCapsuleType() {
+ if fn := in.CapsuleOps().ConversionFrom; fn != nil {
+ if conv := conversionFromCapsule(in, out, fn); conv != nil {
+ return conv
+ }
+ }
+ }
+ // No conversion operation is available, then.
+ return nil
+
+ default:
+ return nil
+
+ }
+}
+
+// retConversion wraps a conversion (internal type) so it can be returned
+// as a Conversion (public type).
+func retConversion(conv conversion) Conversion {
+ if conv == nil {
+ return nil
+ }
+
+ return func(in cty.Value) (cty.Value, error) {
+ return conv(in, cty.Path(nil))
+ }
+}
+
+// prepareUnknownResult can apply value refinements to a returned unknown value
+// in certain cases where characteristics of the source value or type can
+// transfer into range constraints on the result value.
+func prepareUnknownResult(sourceRange cty.ValueRange, targetTy cty.Type) cty.Value {
+ sourceTy := sourceRange.TypeConstraint()
+
+ ret := cty.UnknownVal(targetTy)
+ if sourceRange.DefinitelyNotNull() {
+ ret = ret.RefineNotNull()
+ }
+
+ switch {
+ case sourceTy.IsObjectType() && targetTy.IsMapType():
+ // A map built from an object type always has the same number of
+ // elements as the source type has attributes.
+ return ret.Refine().CollectionLength(len(sourceTy.AttributeTypes())).NewValue()
+ case sourceTy.IsTupleType() && targetTy.IsListType():
+ // A list built from a typle type always has the same number of
+ // elements as the source type has elements.
+ return ret.Refine().CollectionLength(sourceTy.Length()).NewValue()
+ case sourceTy.IsTupleType() && targetTy.IsSetType():
+ // When building a set from a tuple type we can't exactly constrain
+ // the length because some elements might coalesce, but we can
+ // guarantee an upper limit. We can also guarantee at least one
+ // element if the tuple isn't empty.
+ switch l := sourceTy.Length(); l {
+ case 0, 1:
+ return ret.Refine().CollectionLength(l).NewValue()
+ default:
+ return ret.Refine().
+ CollectionLengthLowerBound(1).
+ CollectionLengthUpperBound(sourceTy.Length()).
+ NewValue()
+ }
+ case sourceTy.IsCollectionType() && targetTy.IsCollectionType():
+ // NOTE: We only reach this function if there is an available
+ // conversion between the source and target type, so we don't
+ // need to repeat element type compatibility checks and such here.
+ //
+ // If the source value already has a refined length then we'll
+ // transfer those refinements to the result, because conversion
+ // does not change length (aside from set element coalescing).
+ b := ret.Refine()
+ if targetTy.IsSetType() {
+ if sourceRange.LengthLowerBound() > 0 {
+ // If the source has at least one element then the result
+ // must always have at least one too, because value coalescing
+ // cannot totally empty the set.
+ b = b.CollectionLengthLowerBound(1)
+ }
+ } else {
+ b = b.CollectionLengthLowerBound(sourceRange.LengthLowerBound())
+ }
+ b = b.CollectionLengthUpperBound(sourceRange.LengthUpperBound())
+ return b.NewValue()
+ default:
+ return ret
+ }
+
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_capsule.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_capsule.go
new file mode 100644
index 00000000000..411ea3fa6f7
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_capsule.go
@@ -0,0 +1,31 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+func conversionToCapsule(inTy, outTy cty.Type, fn func(inTy cty.Type) func(cty.Value, cty.Path) (any, error)) conversion {
+ rawConv := fn(inTy)
+ if rawConv == nil {
+ return nil
+ }
+
+ return func(in cty.Value, path cty.Path) (cty.Value, error) {
+ rawV, err := rawConv(in, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ return cty.CapsuleVal(outTy, rawV), nil
+ }
+}
+
+func conversionFromCapsule(inTy, outTy cty.Type, fn func(outTy cty.Type) func(any, cty.Path) (cty.Value, error)) conversion {
+ rawConv := fn(outTy)
+ if rawConv == nil {
+ return nil
+ }
+
+ return func(in cty.Value, path cty.Path) (cty.Value, error) {
+ return rawConv(in.EncapsulatedValue(), path)
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
new file mode 100644
index 00000000000..451367c7d7e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
@@ -0,0 +1,629 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// conversionCollectionToList returns a conversion that will apply the given
+// conversion to all of the elements of a collection (something that supports
+// ForEachElement and LengthInt) and then returns the result as a list.
+//
+// "conv" can be nil if the elements are expected to already be of the
+// correct type and just need to be re-wrapped into a list. (For example,
+// if we're converting from a set into a list of the same element type.)
+func conversionCollectionToList(ety cty.Type, conv conversion) conversion {
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ if !val.Length().IsKnown() {
+ // If the input collection has an unknown length (which is true
+ // for a set containing unknown values) then our result must be
+ // an unknown list, because we can't predict how many elements
+ // the resulting list should have.
+ return cty.UnknownVal(cty.List(val.Type().ElementType())), nil
+ }
+
+ elems := make([]cty.Value, 0, val.LengthInt())
+ i := int64(0)
+ elemPath := append(path.Copy(), nil)
+ it := val.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(i),
+ }
+
+ if conv != nil {
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if val.IsNull() {
+ val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep())
+ }
+
+ elems = append(elems, val)
+
+ i++
+ }
+
+ if len(elems) == 0 {
+ // Prefer a concrete type over a dynamic type when returning an
+ // empty list
+ if ety == cty.DynamicPseudoType {
+ return cty.ListValEmpty(val.Type().ElementType()), nil
+ }
+ return cty.ListValEmpty(ety.WithoutOptionalAttributesDeep()), nil
+ }
+
+ if !cty.CanListVal(elems) {
+ return cty.NilVal, path.NewErrorf("element types must all match for conversion to list")
+ }
+
+ return cty.ListVal(elems), nil
+ }
+}
+
+// conversionCollectionToSet returns a conversion that will apply the given
+// conversion to all of the elements of a collection (something that supports
+// ForEachElement and LengthInt) and then returns the result as a set.
+//
+// "conv" can be nil if the elements are expected to already be of the
+// correct type and just need to be re-wrapped into a set. (For example,
+// if we're converting from a list into a set of the same element type.)
+func conversionCollectionToSet(ety cty.Type, conv conversion) conversion {
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elems := make([]cty.Value, 0, val.LengthInt())
+ i := int64(0)
+ elemPath := append(path.Copy(), nil)
+ it := val.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(i),
+ }
+
+ if conv != nil {
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if val.IsNull() {
+ val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep())
+ }
+
+ elems = append(elems, val)
+
+ i++
+ }
+
+ if len(elems) == 0 {
+ // Prefer a concrete type over a dynamic type when returning an
+ // empty set
+ if ety == cty.DynamicPseudoType {
+ return cty.SetValEmpty(val.Type().ElementType()), nil
+ }
+ return cty.SetValEmpty(ety.WithoutOptionalAttributesDeep()), nil
+ }
+
+ if !cty.CanSetVal(elems) {
+ return cty.NilVal, path.NewErrorf("element types must all match for conversion to set")
+ }
+
+ return cty.SetVal(elems), nil
+ }
+}
+
+// conversionCollectionToMap returns a conversion that will apply the given
+// conversion to all of the elements of a collection (something that supports
+// ForEachElement and LengthInt) and then returns the result as a map.
+//
+// "conv" can be nil if the elements are expected to already be of the
+// correct type and just need to be re-wrapped into a map.
+func conversionCollectionToMap(ety cty.Type, conv conversion) conversion {
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elems := make(map[string]cty.Value, 0)
+ elemPath := append(path.Copy(), nil)
+ it := val.ElementIterator()
+ for it.Next() {
+ key, val := it.Element()
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: key,
+ }
+
+ keyStr, err := Convert(key, cty.String)
+ if err != nil {
+ // Should never happen, because keys can only be numbers or
+ // strings and both can convert to string.
+ return cty.DynamicVal, elemPath.NewErrorf("cannot convert key type %s to string for map", key.Type().FriendlyName())
+ }
+
+ if conv != nil {
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ elems[keyStr.AsString()] = val
+ }
+
+ if len(elems) == 0 {
+ // Prefer a concrete type over a dynamic type when returning an
+ // empty map
+ if ety == cty.DynamicPseudoType {
+ return cty.MapValEmpty(val.Type().ElementType()), nil
+ }
+ return cty.MapValEmpty(ety.WithoutOptionalAttributesDeep()), nil
+ }
+
+ if ety.IsCollectionType() || ety.IsObjectType() {
+ var err error
+ if elems, err = conversionUnifyCollectionElements(elems, path, false); err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if !cty.CanMapVal(elems) {
+ return cty.NilVal, path.NewErrorf("element types must all match for conversion to map")
+ }
+
+ return cty.MapVal(elems), nil
+ }
+}
+
+// conversionTupleToSet returns a conversion that will take a value of the
+// given tuple type and return a set of the given element type.
+//
+// Will panic if the given tupleType isn't actually a tuple type.
+func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conversion {
+ tupleEtys := tupleType.TupleElementTypes()
+
+ if len(tupleEtys) == 0 {
+ // Empty tuple short-circuit
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ return cty.SetValEmpty(setEty.WithoutOptionalAttributesDeep()), nil
+ }
+ }
+
+ if setEty == cty.DynamicPseudoType {
+ // This is a special case where the caller wants us to find
+ // a suitable single type that all elements can convert to, if
+ // possible.
+ setEty, _ = unify(tupleEtys, unsafe)
+ if setEty == cty.NilType {
+ return nil
+ }
+
+ // If the set element type after unification is still the dynamic
+ // type, the only way this can result in a valid set is if all values
+ // are of dynamic type
+ if setEty == cty.DynamicPseudoType {
+ for _, tupleEty := range tupleEtys {
+ if !tupleEty.Equals(cty.DynamicPseudoType) {
+ return nil
+ }
+ }
+ }
+ }
+
+ elemConvs := make([]conversion, len(tupleEtys))
+ for i, tupleEty := range tupleEtys {
+ if tupleEty.Equals(setEty) {
+ // no conversion required
+ continue
+ }
+
+ elemConvs[i] = getConversion(tupleEty, setEty, unsafe)
+ if elemConvs[i] == nil {
+ // If any of our element conversions are impossible, then the our
+ // whole conversion is impossible.
+ return nil
+ }
+ }
+
+ // If we fall out here then a conversion is possible, using the
+ // element conversions in elemConvs
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elems := make([]cty.Value, 0, len(elemConvs))
+ elemPath := append(path.Copy(), nil)
+ i := int64(0)
+ it := val.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(i),
+ }
+
+ conv := elemConvs[i]
+ if conv != nil {
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if val.IsNull() {
+ val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep())
+ }
+
+ elems = append(elems, val)
+
+ i++
+ }
+
+ if !cty.CanSetVal(elems) {
+ return cty.NilVal, path.NewErrorf("element types must all match for conversion to set")
+ }
+
+ return cty.SetVal(elems), nil
+ }
+}
+
+// conversionTupleToList returns a conversion that will take a value of the
+// given tuple type and return a list of the given element type.
+//
+// Will panic if the given tupleType isn't actually a tuple type.
+func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) conversion {
+ tupleEtys := tupleType.TupleElementTypes()
+
+ if len(tupleEtys) == 0 {
+ // Empty tuple short-circuit
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ return cty.ListValEmpty(listEty.WithoutOptionalAttributesDeep()), nil
+ }
+ }
+
+ if listEty == cty.DynamicPseudoType {
+ // This is a special case where the caller wants us to find
+ // a suitable single type that all elements can convert to, if
+ // possible.
+ listEty, _ = unify(tupleEtys, unsafe)
+ if listEty == cty.NilType {
+ return nil
+ }
+
+ // If the list element type after unification is still the dynamic
+ // type, the only way this can result in a valid list is if all values
+ // are of dynamic type
+ if listEty == cty.DynamicPseudoType {
+ for _, tupleEty := range tupleEtys {
+ if !tupleEty.Equals(cty.DynamicPseudoType) {
+ return nil
+ }
+ }
+ }
+ }
+
+ elemConvs := make([]conversion, len(tupleEtys))
+ for i, tupleEty := range tupleEtys {
+ if tupleEty.Equals(listEty) {
+ // no conversion required
+ continue
+ }
+
+ elemConvs[i] = getConversion(tupleEty, listEty, unsafe)
+ if elemConvs[i] == nil {
+ // If any of our element conversions are impossible, then the our
+ // whole conversion is impossible.
+ return nil
+ }
+ }
+
+ // If we fall out here then a conversion is possible, using the
+ // element conversions in elemConvs
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elems := make([]cty.Value, 0, len(elemConvs))
+ elemTys := make([]cty.Type, 0, len(elems))
+ elemPath := append(path.Copy(), nil)
+ i := int64(0)
+ it := val.ElementIterator()
+ for it.Next() {
+ _, val := it.Element()
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(i),
+ }
+
+ conv := elemConvs[i]
+ if conv != nil {
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+ elems = append(elems, val)
+ elemTys = append(elemTys, val.Type())
+
+ i++
+ }
+
+ elems, err := conversionUnifyListElements(elems, elemPath, unsafe)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ if !cty.CanListVal(elems) {
+ return cty.NilVal, path.NewErrorf("element types must all match for conversion to list")
+ }
+
+ return cty.ListVal(elems), nil
+ }
+}
+
+// conversionObjectToMap returns a conversion that will take a value of the
+// given object type and return a map of the given element type.
+//
+// Will panic if the given objectType isn't actually an object type.
+func conversionObjectToMap(objectType cty.Type, mapEty cty.Type, unsafe bool) conversion {
+ objectAtys := objectType.AttributeTypes()
+
+ if len(objectAtys) == 0 {
+ // Empty object short-circuit
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ return cty.MapValEmpty(mapEty.WithoutOptionalAttributesDeep()), nil
+ }
+ }
+
+ if mapEty == cty.DynamicPseudoType {
+ // This is a special case where the caller wants us to find
+ // a suitable single type that all elements can convert to, if
+ // possible.
+ objectAtysList := make([]cty.Type, 0, len(objectAtys))
+ for _, aty := range objectAtys {
+ objectAtysList = append(objectAtysList, aty)
+ }
+ mapEty, _ = unify(objectAtysList, unsafe)
+ if mapEty == cty.NilType {
+ return nil
+ }
+ }
+
+ elemConvs := make(map[string]conversion, len(objectAtys))
+ for name, objectAty := range objectAtys {
+ if objectAty.Equals(mapEty) {
+ // no conversion required
+ continue
+ }
+
+ elemConvs[name] = getConversion(objectAty, mapEty, unsafe)
+ if elemConvs[name] == nil {
+ // If any of our element conversions are impossible, then the our
+ // whole conversion is impossible.
+ return nil
+ }
+ }
+
+ // If we fall out here then a conversion is possible, using the
+ // element conversions in elemConvs
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elems := make(map[string]cty.Value, len(elemConvs))
+ elemPath := append(path.Copy(), nil)
+ it := val.ElementIterator()
+ for it.Next() {
+ name, val := it.Element()
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: name,
+ }
+
+ conv := elemConvs[name.AsString()]
+ if conv != nil {
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+ elems[name.AsString()] = val
+ }
+
+ if mapEty.IsCollectionType() || mapEty.IsObjectType() {
+ var err error
+ if elems, err = conversionUnifyCollectionElements(elems, path, unsafe); err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if !cty.CanMapVal(elems) {
+ return cty.NilVal, path.NewErrorf("attribute types must all match for conversion to map")
+ }
+
+ return cty.MapVal(elems), nil
+ }
+}
+
+// conversionMapToObject returns a conversion that will take a value of the
+// given map type and return an object of the given type. The object attribute
+// types must all be compatible with the map element type.
+//
+// Will panic if the given mapType and objType are not maps and objects
+// respectively.
+func conversionMapToObject(mapType cty.Type, objType cty.Type, unsafe bool) conversion {
+ objectAtys := objType.AttributeTypes()
+ mapEty := mapType.ElementType()
+
+ elemConvs := make(map[string]conversion, len(objectAtys))
+ for name, objectAty := range objectAtys {
+ if objectAty.Equals(mapEty) {
+ // no conversion required
+ continue
+ }
+
+ elemConvs[name] = getConversion(mapEty, objectAty, unsafe)
+ if elemConvs[name] == nil {
+ // This means that this conversion is impossible. Typically, we
+ // would give up at this point and declare the whole conversion
+ // impossible. But, if this attribute is optional then maybe we will
+ // be able to do this conversion anyway provided the actual concrete
+ // map doesn't have this value set.
+ //
+ // We only do this in "unsafe" mode, because we cannot guarantee
+ // that the returned conversion will actually succeed once applied.
+ if objType.AttributeOptional(name) && unsafe {
+ // This attribute is optional, so let's leave this conversion in
+ // as a nil, and we can error later if we actually have to
+ // convert this.
+ continue
+ }
+
+ // Otherwise, give up. This conversion is impossible as we have a
+ // required attribute that doesn't match the map's inner type.
+ return nil
+ }
+ }
+
+ // If we fall out here then a conversion may be possible, using the
+ // element conversions in elemConvs
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elems := make(map[string]cty.Value, len(elemConvs))
+ elemPath := append(path.Copy(), nil)
+ it := val.ElementIterator()
+ for it.Next() {
+ name, val := it.Element()
+
+ // if there is no corresponding attribute, we skip this key
+ if _, ok := objectAtys[name.AsString()]; !ok {
+ continue
+ }
+
+ var err error
+
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: name,
+ }
+
+ // There are 3 cases here:
+ // 1. This attribute is not in elemConvs
+ // 2. This attribute is in elemConvs and is not nil
+ // 3. This attribute is in elemConvs and is nil.
+
+ // In case 1, we do not enter any of the branches below. This case
+ // means the attribute type is the same between the map and the
+ // object, and we don't need to do any conversion.
+
+ if conv, ok := elemConvs[name.AsString()]; conv != nil {
+ // This is case 2. The attribute type is different between the
+ // map and the object, and we know how to convert between them.
+ // So, we reset val to be the converted value and carry on.
+ val, err = conv(val, elemPath)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ } else if ok {
+ // This is case 3 and it is an error. The attribute types are
+ // different between the map and the object, but we cannot
+ // convert between them.
+ //
+ // Now typically, this would be picked earlier on when we were
+ // building elemConvs. However, in the case of optional
+ // attributes there was a chance we could still convert the
+ // overall object even if this particular attribute was not
+ // convertable. This is because it could have not been set in
+ // the map, and we could skip over it here and set a null value.
+ //
+ // Since we reached this branch, we know that map did actually
+ // contain a non-convertable optional attribute. This means we
+ // error.
+ return cty.NilVal, path.NewErrorf("map element type is incompatible with attribute %q: %s", name.AsString(), MismatchMessage(val.Type(), objType.AttributeType(name.AsString())))
+ }
+
+ if val.IsNull() {
+ val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep())
+ }
+
+ elems[name.AsString()] = val
+ }
+
+ for name, aty := range objectAtys {
+ if _, exists := elems[name]; !exists {
+ if optional := objType.AttributeOptional(name); optional {
+ elems[name] = cty.NullVal(aty)
+ } else {
+ return cty.NilVal, path.NewErrorf("map has no element for required attribute %q", name)
+ }
+ }
+ }
+
+ return cty.ObjectVal(elems), nil
+ }
+}
+
+func conversionUnifyCollectionElements(elems map[string]cty.Value, path cty.Path, unsafe bool) (map[string]cty.Value, error) {
+ elemTypes := make([]cty.Type, 0, len(elems))
+ for _, elem := range elems {
+ elemTypes = append(elemTypes, elem.Type())
+ }
+ unifiedType, _ := unify(elemTypes, unsafe)
+ if unifiedType == cty.NilType {
+ return nil, path.NewErrorf("cannot find a common base type for all elements")
+ }
+
+ unifiedElems := make(map[string]cty.Value)
+ elemPath := append(path.Copy(), nil)
+
+ for name, elem := range elems {
+ if elem.Type().Equals(unifiedType) {
+ unifiedElems[name] = elem
+ continue
+ }
+ conv := getConversion(elem.Type(), unifiedType, unsafe)
+ if conv == nil {
+ }
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: cty.StringVal(name),
+ }
+ val, err := conv(elem, elemPath)
+ if err != nil {
+ return nil, err
+ }
+ unifiedElems[name] = val
+ }
+
+ return unifiedElems, nil
+}
+
+func conversionUnifyListElements(elems []cty.Value, path cty.Path, unsafe bool) ([]cty.Value, error) {
+ elemTypes := make([]cty.Type, len(elems))
+ for i, elem := range elems {
+ elemTypes[i] = elem.Type()
+ }
+ unifiedType, _ := unify(elemTypes, unsafe)
+ if unifiedType == cty.NilType {
+ return nil, path.NewErrorf("cannot find a common base type for all elements")
+ }
+
+ ret := make([]cty.Value, len(elems))
+ elemPath := append(path.Copy(), nil)
+
+ for i, elem := range elems {
+ if elem.Type().Equals(unifiedType) {
+ ret[i] = elem
+ continue
+ }
+ conv := getConversion(elem.Type(), unifiedType, unsafe)
+ if conv == nil {
+ }
+ elemPath[len(elemPath)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+ val, err := conv(elem, elemPath)
+ if err != nil {
+ return nil, err
+ }
+ ret[i] = val
+ }
+
+ return ret, nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go
new file mode 100644
index 00000000000..95f3925b599
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go
@@ -0,0 +1,136 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// dynamicFixup deals with just-in-time conversions of values that were
+// input-typed as cty.DynamicPseudoType during analysis, ensuring that
+// we end up with the desired output type once the value is known, or
+// failing with an error if that is not possible.
+//
+// This is in the spirit of the cty philosophy of optimistically assuming that
+// DynamicPseudoType values will become the intended value eventually, and
+// dealing with any inconsistencies during final evaluation.
+func dynamicFixup(wantType cty.Type) conversion {
+ return func(in cty.Value, path cty.Path) (cty.Value, error) {
+ ret, err := Convert(in, wantType)
+ if err != nil {
+ // Re-wrap this error so that the returned path is relative
+ // to the caller's original value, rather than relative to our
+ // conversion value here.
+ return cty.NilVal, path.NewError(err)
+ }
+ return ret, nil
+ }
+}
+
+// dynamicPassthrough is an identity conversion that is used when the
+// target type is DynamicPseudoType, indicating that the caller doesn't care
+// which type is returned.
+func dynamicPassthrough(in cty.Value, path cty.Path) (cty.Value, error) {
+ return in, nil
+}
+
+// dynamicReplace aims to return the out type unchanged, but if it finds a
+// dynamic type either directly or in any descendent elements it replaces them
+// with the equivalent type from in.
+//
+// This function assumes that in and out are compatible from a Convert
+// perspective, and will panic if it finds that they are not. For example if
+// in is an object and out is a map, this function will still attempt to iterate
+// through both as if they were the same.
+// While the outermost in and out types may be compatible from a Convert
+// perspective, inner types may not match when converting between maps and
+// objects with optional attributes when the optional attributes don't match
+// the map element type. Therefor in the case of a non-primitive type mismatch,
+// we have to assume conversion was possible and pass the out type through.
+func dynamicReplace(in, out cty.Type) cty.Type {
+ if in == cty.DynamicPseudoType || in == cty.NilType {
+ // Short circuit this case, there's no point worrying about this if in
+ // is a dynamic type or a nil type. Out is the best we can do.
+ return out
+ }
+
+ switch {
+ case out == cty.DynamicPseudoType:
+ // So replace out with in.
+ return in
+ case out.IsPrimitiveType(), out.IsCapsuleType():
+ // out is not dynamic and it doesn't contain descendent elements so just
+ // return it unchanged.
+ return out
+ case out.IsMapType():
+ // Maps are compatible with other maps or objects.
+ if in.IsMapType() {
+ return cty.Map(dynamicReplace(in.ElementType(), out.ElementType()))
+ }
+
+ if in.IsObjectType() {
+ var types []cty.Type
+ for _, t := range in.AttributeTypes() {
+ types = append(types, t)
+ }
+ unifiedType, _ := unify(types, true)
+ return cty.Map(dynamicReplace(unifiedType, out.ElementType()))
+ }
+
+ return out
+ case out.IsObjectType():
+ // Objects are compatible with other objects and maps.
+ outTypes := map[string]cty.Type{}
+ if in.IsMapType() {
+ for attr, attrType := range out.AttributeTypes() {
+ outTypes[attr] = dynamicReplace(in.ElementType(), attrType)
+ }
+ }
+
+ if in.IsObjectType() {
+ for attr, attrType := range out.AttributeTypes() {
+ if !in.HasAttribute(attr) {
+ // If in does not have this attribute, then it is an
+ // optional attribute and there is nothing we can do except
+ // to return the type from out even if it is dynamic.
+ outTypes[attr] = attrType
+ continue
+ }
+ outTypes[attr] = dynamicReplace(in.AttributeType(attr), attrType)
+ }
+ }
+
+ return cty.Object(outTypes)
+ case out.IsSetType():
+ // Sets are compatible with other sets, lists, tuples.
+ if in.IsSetType() || in.IsListType() {
+ return cty.Set(dynamicReplace(in.ElementType(), out.ElementType()))
+ }
+
+ if in.IsTupleType() {
+ unifiedType, _ := unify(in.TupleElementTypes(), true)
+ return cty.Set(dynamicReplace(unifiedType, out.ElementType()))
+ }
+
+ return out
+ case out.IsListType():
+ // Lists are compatible with other lists, sets, and tuples.
+ if in.IsSetType() || in.IsListType() {
+ return cty.List(dynamicReplace(in.ElementType(), out.ElementType()))
+ }
+
+ if in.IsTupleType() {
+ unifiedType, _ := unify(in.TupleElementTypes(), true)
+ return cty.List(dynamicReplace(unifiedType, out.ElementType()))
+ }
+
+ return out
+ case out.IsTupleType():
+ // Tuples are only compatible with other tuples
+ var types []cty.Type
+ for ix := 0; ix < len(out.TupleElementTypes()); ix++ {
+ types = append(types, dynamicReplace(in.TupleElementType(ix), out.TupleElementType(ix)))
+ }
+ return cty.Tuple(types)
+ default:
+ panic("unrecognized type " + out.FriendlyName())
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go
new file mode 100644
index 00000000000..51958ef4b42
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go
@@ -0,0 +1,101 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// conversionObjectToObject returns a conversion that will make the input
+// object type conform to the output object type, if possible.
+//
+// Conversion is possible only if the output type is a subset of the input
+// type, meaning that each attribute of the output type has a corresponding
+// attribute in the input type where a recursive conversion is available.
+//
+// If the "out" type has any optional attributes, those attributes may be
+// absent in the "in" type, in which case null values will be used in their
+// place in the result.
+//
+// Shallow object conversions work the same for both safe and unsafe modes,
+// but the safety flag is passed on to recursive conversions and may thus
+// limit the above definition of "subset".
+func conversionObjectToObject(in, out cty.Type, unsafe bool) conversion {
+ inAtys := in.AttributeTypes()
+ outAtys := out.AttributeTypes()
+ outOptionals := out.OptionalAttributes()
+ attrConvs := make(map[string]conversion)
+
+ for name, outAty := range outAtys {
+ inAty, exists := inAtys[name]
+ if !exists {
+ if _, optional := outOptionals[name]; optional {
+ // If it's optional then we'll skip inserting an
+ // attribute conversion and then deal with inserting
+ // the default value in our overall conversion logic
+ // later.
+ continue
+ }
+ // No conversion is available, then.
+ return nil
+ }
+
+ if inAty.Equals(outAty) {
+ // No conversion needed, but we'll still record the attribute
+ // in our map for later reference.
+ attrConvs[name] = nil
+ continue
+ }
+
+ attrConvs[name] = getConversion(inAty, outAty, unsafe)
+ if attrConvs[name] == nil {
+ // If a recursive conversion isn't available, then our top-level
+ // configuration is impossible too.
+ return nil
+ }
+ }
+
+ // If we get here then a conversion is possible, using the attribute
+ // conversions given in attrConvs.
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ attrVals := make(map[string]cty.Value, len(attrConvs))
+ path = append(path, nil)
+ pathStep := &path[len(path)-1]
+
+ for it := val.ElementIterator(); it.Next(); {
+ nameVal, val := it.Element()
+ var err error
+
+ name := nameVal.AsString()
+ *pathStep = cty.GetAttrStep{
+ Name: name,
+ }
+
+ conv, exists := attrConvs[name]
+ if !exists {
+ continue
+ }
+ if conv != nil {
+ val, err = conv(val, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if val.IsNull() {
+ // Strip optional attributes out of the embedded type for null
+ // values.
+ val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep())
+ }
+
+ attrVals[name] = val
+ }
+
+ for name := range outOptionals {
+ if _, exists := attrVals[name]; !exists {
+ wantTy := outAtys[name]
+ attrVals[name] = cty.NullVal(wantTy.WithoutOptionalAttributesDeep())
+ }
+ }
+
+ return cty.ObjectVal(attrVals), nil
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go
new file mode 100644
index 00000000000..0d6fae9647c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_primitive.go
@@ -0,0 +1,57 @@
+package convert
+
+import (
+ "strings"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+var stringTrue = cty.StringVal("true")
+var stringFalse = cty.StringVal("false")
+
+var primitiveConversionsSafe = map[cty.Type]map[cty.Type]conversion{
+ cty.Number: {
+ cty.String: func(val cty.Value, path cty.Path) (cty.Value, error) {
+ f := val.AsBigFloat()
+ return cty.StringVal(f.Text('f', -1)), nil
+ },
+ },
+ cty.Bool: {
+ cty.String: func(val cty.Value, path cty.Path) (cty.Value, error) {
+ if val.True() {
+ return stringTrue, nil
+ } else {
+ return stringFalse, nil
+ }
+ },
+ },
+}
+
+var primitiveConversionsUnsafe = map[cty.Type]map[cty.Type]conversion{
+ cty.String: {
+ cty.Number: func(val cty.Value, path cty.Path) (cty.Value, error) {
+ v, err := cty.ParseNumberVal(val.AsString())
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("a number is required")
+ }
+ return v, nil
+ },
+ cty.Bool: func(val cty.Value, path cty.Path) (cty.Value, error) {
+ switch val.AsString() {
+ case "true", "1":
+ return cty.True, nil
+ case "false", "0":
+ return cty.False, nil
+ default:
+ switch strings.ToLower(val.AsString()) {
+ case "true":
+ return cty.NilVal, path.NewErrorf("a bool is required; to convert from string, use lowercase \"true\"")
+ case "false":
+ return cty.NilVal, path.NewErrorf("a bool is required; to convert from string, use lowercase \"false\"")
+ default:
+ return cty.NilVal, path.NewErrorf("a bool is required")
+ }
+ }
+ },
+ },
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go
new file mode 100644
index 00000000000..592980a7012
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/conversion_tuple.go
@@ -0,0 +1,71 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// conversionTupleToTuple returns a conversion that will make the input
+// tuple type conform to the output tuple type, if possible.
+//
+// Conversion is possible only if the two tuple types have the same number
+// of elements and the corresponding elements by index can be converted.
+//
+// Shallow tuple conversions work the same for both safe and unsafe modes,
+// but the safety flag is passed on to recursive conversions and may thus
+// limit which element type conversions are possible.
+func conversionTupleToTuple(in, out cty.Type, unsafe bool) conversion {
+ inEtys := in.TupleElementTypes()
+ outEtys := out.TupleElementTypes()
+
+ if len(inEtys) != len(outEtys) {
+ return nil // no conversion is possible
+ }
+
+ elemConvs := make([]conversion, len(inEtys))
+
+ for i, outEty := range outEtys {
+ inEty := inEtys[i]
+
+ if inEty.Equals(outEty) {
+ // No conversion needed, so we can leave this one nil.
+ continue
+ }
+
+ elemConvs[i] = getConversion(inEty, outEty, unsafe)
+ if elemConvs[i] == nil {
+ // If a recursive conversion isn't available, then our top-level
+ // configuration is impossible too.
+ return nil
+ }
+ }
+
+ // If we get here then a conversion is possible, using the element
+ // conversions given in elemConvs.
+ return func(val cty.Value, path cty.Path) (cty.Value, error) {
+ elemVals := make([]cty.Value, len(elemConvs))
+ path = append(path, nil)
+ pathStep := &path[len(path)-1]
+
+ i := 0
+ for it := val.ElementIterator(); it.Next(); i++ {
+ _, val := it.Element()
+ var err error
+
+ *pathStep = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+
+ conv := elemConvs[i]
+ if conv != nil {
+ val, err = conv(val, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ elemVals[i] = val
+ }
+
+ return cty.TupleVal(elemVals), nil
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/doc.go
new file mode 100644
index 00000000000..2037299bab4
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/doc.go
@@ -0,0 +1,15 @@
+// Package convert contains some routines for converting between cty types.
+// The intent of providing this package is to encourage applications using
+// cty to have consistent type conversion behavior for maximal interoperability
+// when Values pass from one application to another.
+//
+// The conversions are categorized into two categories. "Safe" conversions are
+// ones that are guaranteed to succeed if given a non-null value of the
+// appropriate source type. "Unsafe" conversions, on the other hand, are valid
+// for only a subset of input values, and thus may fail with an error when
+// called for values outside of that valid subset.
+//
+// The functions whose names end in Unsafe support all of the conversions that
+// are supported by the corresponding functions whose names do not have that
+// suffix, and then additional unsafe conversions as well.
+package convert
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go
new file mode 100644
index 00000000000..81538b0a47a
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/mismatch_msg.go
@@ -0,0 +1,281 @@
+package convert
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// MismatchMessage is a helper to return an English-language description of
+// the differences between got and want, phrased as a reason why got does
+// not conform to want.
+//
+// This function does not itself attempt conversion, and so it should generally
+// be used only after a conversion has failed, to report the conversion failure
+// to an English-speaking user. The result will be confusing got is actually
+// conforming to or convertable to want.
+//
+// The shorthand helper function Convert uses this function internally to
+// produce its error messages, so callers of that function do not need to
+// also use MismatchMessage.
+//
+// This function is similar to Type.TestConformance, but it is tailored to
+// describing conversion failures and so the messages it generates relate
+// specifically to the conversion rules implemented in this package.
+func MismatchMessage(got, want cty.Type) string {
+ switch {
+
+ case got.IsObjectType() && want.IsObjectType():
+ // If both types are object types then we may be able to say something
+ // about their respective attributes.
+ return mismatchMessageObjects(got, want)
+
+ case got.IsTupleType() && want.IsListType() && want.ElementType() == cty.DynamicPseudoType:
+ // If conversion from tuple to list failed then it's because we couldn't
+ // find a common type to convert all of the tuple elements to.
+ return "all list elements must have the same type"
+
+ case got.IsTupleType() && want.IsSetType() && want.ElementType() == cty.DynamicPseudoType:
+ // If conversion from tuple to set failed then it's because we couldn't
+ // find a common type to convert all of the tuple elements to.
+ return "all set elements must have the same type"
+
+ case got.IsObjectType() && want.IsMapType() && want.ElementType() == cty.DynamicPseudoType:
+ // If conversion from object to map failed then it's because we couldn't
+ // find a common type to convert all of the object attributes to.
+ return "all map elements must have the same type"
+
+ case (got.IsTupleType() || got.IsObjectType()) && want.IsCollectionType():
+ return mismatchMessageCollectionsFromStructural(got, want)
+
+ case got.IsCollectionType() && want.IsCollectionType():
+ return mismatchMessageCollectionsFromCollections(got, want)
+
+ case !typesAreLikelyToCauseConfusion(got, want):
+ return fmt.Sprintf("%s required, but have %s", want.FriendlyName(), got.FriendlyName())
+
+ default:
+ // If we have nothing better to say, we'll just state what was required.
+ return want.FriendlyNameForConstraint() + " required"
+ }
+}
+
+func mismatchMessageObjects(got, want cty.Type) string {
+ // Per our conversion rules, "got" is allowed to be a superset of "want",
+ // and so we'll produce error messages here under that assumption.
+ gotAtys := got.AttributeTypes()
+ wantAtys := want.AttributeTypes()
+
+ // If we find missing attributes then we'll report those in preference,
+ // but if not then we will report a maximum of one non-conforming
+ // attribute, just to keep our messages relatively terse.
+ // We'll also prefer to report a recursive type error from an _unsafe_
+ // conversion over a safe one, because these are subjectively more
+ // "serious".
+ var missingAttrs []string
+ var unsafeMismatchAttr string
+ var safeMismatchAttr string
+
+ for name, wantAty := range wantAtys {
+ gotAty, exists := gotAtys[name]
+ if !exists {
+ if !want.AttributeOptional(name) {
+ missingAttrs = append(missingAttrs, name)
+ }
+ continue
+ }
+
+ if gotAty.Equals(wantAty) {
+ continue // exact match, so no problem
+ }
+
+ // We'll now try to convert these attributes in isolation and
+ // see if we have a nested conversion error to report.
+ // We'll try an unsafe conversion first, and then fall back on
+ // safe if unsafe is possible.
+
+ // If we already have an unsafe mismatch attr error then we won't bother
+ // hunting for another one.
+ if unsafeMismatchAttr != "" {
+ continue
+ }
+ if conv := GetConversionUnsafe(gotAty, wantAty); conv == nil {
+ unsafeMismatchAttr = fmt.Sprintf("attribute %q: %s", name, MismatchMessage(gotAty, wantAty))
+ }
+
+ // If we already have a safe mismatch attr error then we won't bother
+ // hunting for another one.
+ if safeMismatchAttr != "" {
+ continue
+ }
+ if conv := GetConversion(gotAty, wantAty); conv == nil {
+ safeMismatchAttr = fmt.Sprintf("attribute %q: %s", name, MismatchMessage(gotAty, wantAty))
+ }
+ }
+
+ // We should now have collected at least one problem. If we have more than
+ // one then we'll use our preference order to decide what is most important
+ // to report.
+ switch {
+
+ case len(missingAttrs) != 0:
+ sort.Strings(missingAttrs)
+ switch len(missingAttrs) {
+ case 1:
+ return fmt.Sprintf("attribute %q is required", missingAttrs[0])
+ case 2:
+ return fmt.Sprintf("attributes %q and %q are required", missingAttrs[0], missingAttrs[1])
+ default:
+ sort.Strings(missingAttrs)
+ var buf bytes.Buffer
+ for _, name := range missingAttrs[:len(missingAttrs)-1] {
+ fmt.Fprintf(&buf, "%q, ", name)
+ }
+ fmt.Fprintf(&buf, "and %q", missingAttrs[len(missingAttrs)-1])
+ return fmt.Sprintf("attributes %s are required", buf.Bytes())
+ }
+
+ case unsafeMismatchAttr != "":
+ return unsafeMismatchAttr
+
+ case safeMismatchAttr != "":
+ return safeMismatchAttr
+
+ default:
+ // We should never get here, but if we do then we'll return
+ // just a generic message.
+ return "incorrect object attributes"
+ }
+}
+
+func mismatchMessageCollectionsFromStructural(got, want cty.Type) string {
+ // First some straightforward cases where the kind is just altogether wrong.
+ switch {
+ case want.IsListType() && !got.IsTupleType():
+ return want.FriendlyNameForConstraint() + " required"
+ case want.IsSetType() && !got.IsTupleType():
+ return want.FriendlyNameForConstraint() + " required"
+ case want.IsMapType() && !got.IsObjectType():
+ return want.FriendlyNameForConstraint() + " required"
+ }
+
+ // If the kinds are matched well enough then we'll move on to checking
+ // individual elements.
+ wantEty := want.ElementType()
+ switch {
+ case got.IsTupleType():
+ for i, gotEty := range got.TupleElementTypes() {
+ if gotEty.Equals(wantEty) {
+ continue // exact match, so no problem
+ }
+ if conv := getConversion(gotEty, wantEty, true); conv != nil {
+ continue // conversion is available, so no problem
+ }
+ return fmt.Sprintf("element %d: %s", i, MismatchMessage(gotEty, wantEty))
+ }
+
+ // If we get down here then something weird is going on but we'll
+ // return a reasonable fallback message anyway.
+ return fmt.Sprintf("all elements must be %s", wantEty.FriendlyNameForConstraint())
+
+ case got.IsObjectType():
+ for name, gotAty := range got.AttributeTypes() {
+ if gotAty.Equals(wantEty) {
+ continue // exact match, so no problem
+ }
+ if conv := getConversion(gotAty, wantEty, true); conv != nil {
+ continue // conversion is available, so no problem
+ }
+ return fmt.Sprintf("element %q: %s", name, MismatchMessage(gotAty, wantEty))
+ }
+
+ // If we get down here then something weird is going on but we'll
+ // return a reasonable fallback message anyway.
+ return fmt.Sprintf("all elements must be %s", wantEty.FriendlyNameForConstraint())
+
+ default:
+ // Should not be possible to get here since we only call this function
+ // with got as structural types, but...
+ return want.FriendlyNameForConstraint() + " required"
+ }
+}
+
+func mismatchMessageCollectionsFromCollections(got, want cty.Type) string {
+ // First some straightforward cases where the kind is just altogether wrong.
+ switch {
+ case want.IsListType() && !(got.IsListType() || got.IsSetType()):
+ return want.FriendlyNameForConstraint() + " required"
+ case want.IsSetType() && !(got.IsListType() || got.IsSetType()):
+ return want.FriendlyNameForConstraint() + " required"
+ case want.IsMapType() && !got.IsMapType():
+ return want.FriendlyNameForConstraint() + " required"
+ }
+
+ // If the kinds are matched well enough then we'll check the element types.
+ gotEty := got.ElementType()
+ wantEty := want.ElementType()
+ noun := "element type"
+ switch {
+ case want.IsListType():
+ noun = "list element type"
+ case want.IsSetType():
+ noun = "set element type"
+ case want.IsMapType():
+ noun = "map element type"
+ }
+ return fmt.Sprintf("incorrect %s: %s", noun, MismatchMessage(gotEty, wantEty))
+}
+
+func typesAreLikelyToCauseConfusion(got, want cty.Type) bool {
+ // NOTE: This function is intended to be used as the penultemate test
+ // in MismatchMessage, and so it intentionally does not address
+ // combinations that are already addressed by the more specific
+ // earlier tests.
+ if gotP, wantP := got.IsPrimitiveType(), want.IsPrimitiveType(); gotP != wantP {
+ // There's never any situation where a primitive type could successfully
+ // convert to a non-primitive one, so this is very unlikely to be
+ // intended as an automatic type conversion. This case is doing most
+ // of the useful work of this function, allowing us to report such
+ // things as "string required, but got tuple".
+ return false
+ }
+ if want == cty.String {
+ // All of the primitive types can always successfully convert to
+ // string, regardless of value.
+ return false
+ }
+ if (want == cty.Bool && got == cty.Number) || (got == cty.Bool && want == cty.Number) {
+ // There are no automatic conversions between bool and number, so
+ // describing both directions of this is unlikely to cause confusion.
+ return false
+ }
+ if got.IsCollectionType() && want.IsCollectionType() && !got.ElementType().HasDynamicTypes() && want.ElementType().HasDynamicTypes() {
+ // Describing mismatches of collection element types is helpful
+ // when we have specific types to report, but confusing when
+ // there are any inexact types involved because readers tend to
+ // then think the inexactness of the element type is the problem,
+ // when it's far more likely to be the collection type kind that's
+ // causing the problem.
+ return false
+ }
+ if got.IsTupleType() && want.IsObjectType() || got.IsObjectType() && got.IsTupleType() {
+ // The structural type kinds get described just by their bare names,
+ // "tuple" or "object", and so they are not confusing when they
+ // differ. They _are_ potentially confusing when we have matching kinds
+ // but different element types within, but thankfully that's most
+ // often handled by one of the earlier cases in MismatchMessage.
+ return false
+ }
+ // We are intentionally a little more vague for string-to-number and
+ // string-to-bool conversions because the rules for those are a little
+ // too subtle to be described purely as "need X but want Y", and historical
+ // experience shows that describing it that way causes folks to focus
+ // on the wrong problem (their value is wrong, not their type).
+
+ // If we find that we're getting here in additional specific cases where
+ // it would be more helpful than confusing to report both types then
+ // we'll add additional rules here in a future version.
+ return true
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/public.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/public.go
new file mode 100644
index 00000000000..aab0d0ec9a9
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/public.go
@@ -0,0 +1,83 @@
+package convert
+
+import (
+ "errors"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// This file contains the public interface of this package, which is intended
+// to be a small, convenient interface designed for easy integration into
+// a hypothetical language type checker and interpreter.
+
+// Conversion is a named function type representing a conversion from a
+// value of one type to a value of another type.
+//
+// The source type for a conversion is always the source type given to
+// the function that returned the Conversion, but there is no way to recover
+// that from a Conversion value itself. If a Conversion is given a value
+// that is not of its expected type (with the exception of DynamicPseudoType,
+// which is always supported) then the function may panic or produce undefined
+// results.
+type Conversion func(in cty.Value) (out cty.Value, err error)
+
+// GetConversion returns a Conversion between the given in and out Types if
+// a safe one is available, or returns nil otherwise.
+func GetConversion(in cty.Type, out cty.Type) Conversion {
+ return retConversion(getConversion(in, out, false))
+}
+
+// GetConversionUnsafe returns a Conversion between the given in and out Types
+// if either a safe or unsafe one is available, or returns nil otherwise.
+func GetConversionUnsafe(in cty.Type, out cty.Type) Conversion {
+ return retConversion(getConversion(in, out, true))
+}
+
+// Convert returns the result of converting the given value to the given type
+// if an safe or unsafe conversion is available, or returns an error if such a
+// conversion is impossible.
+//
+// This is a convenience wrapper around calling GetConversionUnsafe and then
+// immediately passing the given value to the resulting function.
+func Convert(in cty.Value, want cty.Type) (cty.Value, error) {
+ if in.Type().Equals(want.WithoutOptionalAttributesDeep()) {
+ return in, nil
+ }
+
+ conv := GetConversionUnsafe(in.Type(), want)
+ if conv == nil {
+ return cty.NilVal, errors.New(MismatchMessage(in.Type(), want))
+ }
+ return conv(in)
+}
+
+// Unify attempts to find the most general type that can be converted from
+// all of the given types. If this is possible, that type is returned along
+// with a slice of necessary conversions for some of the given types.
+//
+// If no common supertype can be found, this function returns cty.NilType and
+// a nil slice.
+//
+// If a common supertype *can* be found, the returned slice will always be
+// non-nil and will contain a non-nil conversion for each given type that
+// needs to be converted, with indices corresponding to the input slice.
+// Any given type that does *not* need conversion (because it is already of
+// the appropriate type) will have a nil Conversion.
+//
+// cty.DynamicPseudoType is, as usual, a special case. If the given type list
+// contains a mixture of dynamic and non-dynamic types, the dynamic types are
+// disregarded for type selection and a conversion is returned for them that
+// will attempt a late conversion of the given value to the target type,
+// failing with a conversion error if the eventual concrete type is not
+// compatible. If *all* given types are DynamicPseudoType, or in the
+// degenerate case of an empty slice of types, the returned type is itself
+// cty.DynamicPseudoType and no conversions are attempted.
+func Unify(types []cty.Type) (cty.Type, []Conversion) {
+ return unify(types, false)
+}
+
+// UnifyUnsafe is the same as Unify except that it may return unsafe
+// conversions in situations where a safe conversion isn't also available.
+func UnifyUnsafe(types []cty.Type) (cty.Type, []Conversion) {
+ return unify(types, true)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go
new file mode 100644
index 00000000000..b7769106d11
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/sort_types.go
@@ -0,0 +1,69 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// sortTypes produces an ordering of the given types that serves as a
+// preference order for the result of unification of the given types.
+// The return value is a slice of indices into the given slice, and will
+// thus always be the same length as the given slice.
+//
+// The goal is that the most general of the given types will appear first
+// in the ordering. If there are uncomparable pairs of types in the list
+// then they will appear in an undefined order, and the unification pass
+// will presumably then fail.
+func sortTypes(tys []cty.Type) []int {
+ l := len(tys)
+
+ // First we build a graph whose edges represent "more general than",
+ // which we will then do a topological sort of.
+ edges := make([][]int, l)
+ for i := 0; i < (l - 1); i++ {
+ for j := i + 1; j < l; j++ {
+ cmp := compareTypes(tys[i], tys[j])
+ switch {
+ case cmp < 0:
+ edges[i] = append(edges[i], j)
+ case cmp > 0:
+ edges[j] = append(edges[j], i)
+ }
+ }
+ }
+
+ // Compute the in-degree of each node
+ inDegree := make([]int, l)
+ for _, outs := range edges {
+ for _, j := range outs {
+ inDegree[j]++
+ }
+ }
+
+ // The array backing our result will double as our queue for visiting
+ // the nodes, with the queue slice moving along this array until it
+ // is empty and positioned at the end of the array. Thus our visiting
+ // order is also our result order.
+ result := make([]int, l)
+ queue := result[0:0]
+
+ // Initialize the queue with any item of in-degree 0, preserving
+ // their relative order.
+ for i, n := range inDegree {
+ if n == 0 {
+ queue = append(queue, i)
+ }
+ }
+
+ for len(queue) != 0 {
+ i := queue[0]
+ queue = queue[1:]
+ for _, j := range edges[i] {
+ inDegree[j]--
+ if inDegree[j] == 0 {
+ queue = append(queue, j)
+ }
+ }
+ }
+
+ return result
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/unify.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
new file mode 100644
index 00000000000..ac6b64db5ab
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
@@ -0,0 +1,500 @@
+package convert
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// The current unify implementation is somewhat inefficient, but we accept this
+// under the assumption that it will generally be used with small numbers of
+// types and with types of reasonable complexity. However, it does have a
+// "happy path" where all of the given types are equal.
+//
+// This function is likely to have poor performance in cases where any given
+// types are very complex (lots of deeply-nested structures) or if the list
+// of types itself is very large. In particular, it will walk the nested type
+// structure under the given types several times, especially when given a
+// list of types for which unification is not possible, since each permutation
+// will be tried to determine that result.
+func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
+ if len(types) == 0 {
+ // Degenerate case
+ return cty.NilType, nil
+ }
+
+ // If all of the given types are of the same structural kind, we may be
+ // able to construct a new type that they can all be unified to, even if
+ // that is not one of the given types. We must try this before the general
+ // behavior below because in unsafe mode we can convert an object type to
+ // a subset of that type, which would be a much less useful conversion for
+ // unification purposes.
+ {
+ mapCt := 0
+ listCt := 0
+ setCt := 0
+ objectCt := 0
+ tupleCt := 0
+ dynamicCt := 0
+ for _, ty := range types {
+ switch {
+ case ty.IsMapType():
+ mapCt++
+ case ty.IsListType():
+ listCt++
+ case ty.IsSetType():
+ setCt++
+ case ty.IsObjectType():
+ objectCt++
+ case ty.IsTupleType():
+ tupleCt++
+ case ty == cty.DynamicPseudoType:
+ dynamicCt++
+ default:
+ break
+ }
+ }
+ switch {
+ case mapCt > 0 && (mapCt+dynamicCt) == len(types):
+ return unifyCollectionTypes(cty.Map, types, unsafe, dynamicCt > 0)
+
+ case mapCt > 0 && (mapCt+objectCt+dynamicCt) == len(types):
+ // Objects often contain map data, but are not directly typed as
+ // such due to language constructs or function types. Try to unify
+ // them as maps first before falling back to heterogeneous type
+ // conversion.
+ ty, convs := unifyObjectsAsMaps(types, unsafe)
+ // If we got a map back, we know the unification was successful.
+ if ty.IsMapType() {
+ return ty, convs
+ }
+ case listCt > 0 && (listCt+dynamicCt) == len(types):
+ return unifyCollectionTypes(cty.List, types, unsafe, dynamicCt > 0)
+ case listCt > 0 && (listCt+tupleCt+dynamicCt) == len(types):
+ // Tuples are often lists in disguise, and we may be able to
+ // unify them as such.
+ ty, convs := unifyTuplesAsList(types, unsafe)
+ // if we got a list back, we know the unification was successful.
+ // Otherwise we will fall back to the heterogeneous type codepath.
+ if ty.IsListType() {
+ return ty, convs
+ }
+ case setCt > 0 && (setCt+dynamicCt) == len(types):
+ return unifyCollectionTypes(cty.Set, types, unsafe, dynamicCt > 0)
+ case objectCt > 0 && (objectCt+dynamicCt) == len(types):
+ return unifyObjectTypes(types, unsafe, dynamicCt > 0)
+ case tupleCt > 0 && (tupleCt+dynamicCt) == len(types):
+ return unifyTupleTypes(types, unsafe, dynamicCt > 0)
+ case objectCt > 0 && tupleCt > 0:
+ // Can never unify object and tuple types since they have incompatible kinds
+ return cty.NilType, nil
+ }
+ }
+
+ prefOrder := sortTypes(types)
+
+ // sortTypes gives us an order where earlier items are preferable as
+ // our result type. We'll now walk through these and choose the first
+ // one we encounter for which conversions exist for all source types.
+ conversions := make([]Conversion, len(types))
+Preferences:
+ for _, wantTypeIdx := range prefOrder {
+ wantType := types[wantTypeIdx]
+ for i, tryType := range types {
+ if i == wantTypeIdx {
+ // Don't need to convert our wanted type to itself
+ conversions[i] = nil
+ continue
+ }
+
+ if tryType.Equals(wantType) {
+ conversions[i] = nil
+ continue
+ }
+
+ if unsafe {
+ conversions[i] = GetConversionUnsafe(tryType, wantType)
+ } else {
+ conversions[i] = GetConversion(tryType, wantType)
+ }
+
+ if conversions[i] == nil {
+ // wantType is not a suitable unification type, so we'll
+ // try the next one in our preference order.
+ continue Preferences
+ }
+ }
+
+ return wantType, conversions
+ }
+
+ // If we fall out here, no unification is possible
+ return cty.NilType, nil
+}
+
+// unifyTuplesAsList attempts to first see if the tuples unify as lists, then
+// re-unifies the given types with the list in place of the tuples.
+func unifyTuplesAsList(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
+ var tuples []cty.Type
+ var tupleIdxs []int
+ for i, t := range types {
+ if t.IsTupleType() {
+ tuples = append(tuples, t)
+ tupleIdxs = append(tupleIdxs, i)
+ }
+ }
+
+ ty, tupleConvs := unifyTupleTypesToList(tuples, unsafe)
+ if !ty.IsListType() {
+ return cty.NilType, nil
+ }
+
+ // the tuples themselves unified as a list, get the overall
+ // unification with this list type instead of the tuple.
+ // make a copy of the types, so we can fallback to the standard
+ // codepath if something went wrong
+ listed := make([]cty.Type, len(types))
+ copy(listed, types)
+ for _, idx := range tupleIdxs {
+ listed[idx] = ty
+ }
+
+ newTy, convs := unify(listed, unsafe)
+ if !newTy.IsListType() {
+ return cty.NilType, nil
+ }
+
+ // we have a good conversion, wrap the nested tuple conversions.
+ // We know the tuple conversion is not nil, because we went from tuple to
+ // list
+ for i, idx := range tupleIdxs {
+ listConv := convs[idx]
+ tupleConv := tupleConvs[i]
+
+ if listConv == nil {
+ convs[idx] = tupleConv
+ continue
+ }
+
+ convs[idx] = func(in cty.Value) (out cty.Value, err error) {
+ out, err = tupleConv(in)
+ if err != nil {
+ return out, err
+ }
+
+ return listConv(in)
+ }
+ }
+
+ return newTy, convs
+}
+
+// unifyObjectsAsMaps attempts to first see if the objects unify as maps, then
+// re-unifies the given types with the map in place of the objects.
+func unifyObjectsAsMaps(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
+ var objs []cty.Type
+ var objIdxs []int
+ for i, t := range types {
+ if t.IsObjectType() {
+ objs = append(objs, t)
+ objIdxs = append(objIdxs, i)
+ }
+ }
+
+ ty, objConvs := unifyObjectTypesToMap(objs, unsafe)
+ if !ty.IsMapType() {
+ return cty.NilType, nil
+ }
+
+ // the objects themselves unified as a map, get the overall
+ // unification with this map type instead of the object.
+ // Make a copy of the types, so we can fallback to the standard codepath if
+ // something went wrong without changing the original types.
+ mapped := make([]cty.Type, len(types))
+ copy(mapped, types)
+ for _, idx := range objIdxs {
+ mapped[idx] = ty
+ }
+
+ newTy, convs := unify(mapped, unsafe)
+ if !newTy.IsMapType() {
+ return cty.NilType, nil
+ }
+
+ // we have a good conversion, so wrap the nested object conversions.
+ // We know the object conversion is not nil, because we went from object to
+ // map.
+ for i, idx := range objIdxs {
+ mapConv := convs[idx]
+ objConv := objConvs[i]
+
+ if mapConv == nil {
+ convs[idx] = objConv
+ continue
+ }
+
+ convs[idx] = func(in cty.Value) (out cty.Value, err error) {
+ out, err = objConv(in)
+ if err != nil {
+ return out, err
+ }
+
+ return mapConv(in)
+ }
+ }
+
+ return newTy, convs
+}
+
+func unifyCollectionTypes(collectionType func(cty.Type) cty.Type, types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
+ // If we had any dynamic types in the input here then we can't predict
+ // what path we'll take through here once these become known types, so
+ // we'll conservatively produce DynamicVal for these.
+ if hasDynamic {
+ return unifyAllAsDynamic(types)
+ }
+
+ elemTypes := make([]cty.Type, 0, len(types))
+ for _, ty := range types {
+ elemTypes = append(elemTypes, ty.ElementType())
+ }
+ retElemType, _ := unify(elemTypes, unsafe)
+ if retElemType == cty.NilType {
+ return cty.NilType, nil
+ }
+
+ retTy := collectionType(retElemType)
+
+ conversions := make([]Conversion, len(types))
+ for i, ty := range types {
+ if ty.Equals(retTy) {
+ continue
+ }
+ if unsafe {
+ conversions[i] = GetConversionUnsafe(ty, retTy)
+ } else {
+ conversions[i] = GetConversion(ty, retTy)
+ }
+ if conversions[i] == nil {
+ // Shouldn't be reachable, since we were able to unify
+ return cty.NilType, nil
+ }
+ }
+
+ return retTy, conversions
+}
+
+func unifyObjectTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
+ // If we had any dynamic types in the input here then we can't predict
+ // what path we'll take through here once these become known types, so
+ // we'll conservatively produce DynamicVal for these.
+ if hasDynamic {
+ return unifyAllAsDynamic(types)
+ }
+
+ // There are two different ways we can succeed here:
+ // - If all of the given object types have the same set of attribute names
+ // and the corresponding types are all unifyable, then we construct that
+ // type.
+ // - If the given object types have different attribute names or their
+ // corresponding types are not unifyable, we'll instead try to unify
+ // all of the attribute types together to produce a map type.
+ //
+ // Our unification behavior is intentionally stricter than our conversion
+ // behavior for subset object types because user intent is different with
+ // unification use-cases: it makes sense to allow {"foo":true} to convert
+ // to emptyobjectval, but unifying an object with an attribute with the
+ // empty object type should be an error because unifying to the empty
+ // object type would be suprising and useless.
+
+ firstAttrs := types[0].AttributeTypes()
+ for _, ty := range types[1:] {
+ thisAttrs := ty.AttributeTypes()
+ if len(thisAttrs) != len(firstAttrs) {
+ // If number of attributes is different then there can be no
+ // object type in common.
+ return unifyObjectTypesToMap(types, unsafe)
+ }
+ for name := range thisAttrs {
+ if _, ok := firstAttrs[name]; !ok {
+ // If attribute names don't exactly match then there can be
+ // no object type in common.
+ return unifyObjectTypesToMap(types, unsafe)
+ }
+ }
+ }
+
+ // If we get here then we've proven that all of the given object types
+ // have exactly the same set of attribute names, though the types may
+ // differ.
+ retAtys := make(map[string]cty.Type)
+ atysAcross := make([]cty.Type, len(types))
+ for name := range firstAttrs {
+ for i, ty := range types {
+ atysAcross[i] = ty.AttributeType(name)
+ }
+ retAtys[name], _ = unify(atysAcross, unsafe)
+ if retAtys[name] == cty.NilType {
+ // Cannot unify this attribute alone, which means that unification
+ // of everything down to a map type can't be possible either.
+ return cty.NilType, nil
+ }
+ }
+ retTy := cty.Object(retAtys)
+
+ conversions := make([]Conversion, len(types))
+ for i, ty := range types {
+ if ty.Equals(retTy) {
+ continue
+ }
+ if unsafe {
+ conversions[i] = GetConversionUnsafe(ty, retTy)
+ } else {
+ conversions[i] = GetConversion(ty, retTy)
+ }
+ if conversions[i] == nil {
+ // Shouldn't be reachable, since we were able to unify
+ return unifyObjectTypesToMap(types, unsafe)
+ }
+ }
+
+ return retTy, conversions
+}
+
+func unifyObjectTypesToMap(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
+ // This is our fallback case for unifyObjectTypes, where we see if we can
+ // construct a map type that can accept all of the attribute types.
+
+ var atys []cty.Type
+ for _, ty := range types {
+ for _, aty := range ty.AttributeTypes() {
+ atys = append(atys, aty)
+ }
+ }
+
+ ety, _ := unify(atys, unsafe)
+ if ety == cty.NilType {
+ return cty.NilType, nil
+ }
+
+ retTy := cty.Map(ety)
+ conversions := make([]Conversion, len(types))
+ for i, ty := range types {
+ if ty.Equals(retTy) {
+ continue
+ }
+ if unsafe {
+ conversions[i] = GetConversionUnsafe(ty, retTy)
+ } else {
+ conversions[i] = GetConversion(ty, retTy)
+ }
+ if conversions[i] == nil {
+ return cty.NilType, nil
+ }
+ }
+ return retTy, conversions
+}
+
+func unifyTupleTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
+ // If we had any dynamic types in the input here then we can't predict
+ // what path we'll take through here once these become known types, so
+ // we'll conservatively produce DynamicVal for these.
+ if hasDynamic {
+ return unifyAllAsDynamic(types)
+ }
+
+ // There are two different ways we can succeed here:
+ // - If all of the given tuple types have the same sequence of element types
+ // and the corresponding types are all unifyable, then we construct that
+ // type.
+ // - If the given tuple types have different element types or their
+ // corresponding types are not unifyable, we'll instead try to unify
+ // all of the elements types together to produce a list type.
+
+ firstEtys := types[0].TupleElementTypes()
+ for _, ty := range types[1:] {
+ thisEtys := ty.TupleElementTypes()
+ if len(thisEtys) != len(firstEtys) {
+ // If number of elements is different then there can be no
+ // tuple type in common.
+ return unifyTupleTypesToList(types, unsafe)
+ }
+ }
+
+ // If we get here then we've proven that all of the given tuple types
+ // have the same number of elements, though the types may differ.
+ retEtys := make([]cty.Type, len(firstEtys))
+ atysAcross := make([]cty.Type, len(types))
+ for idx := range firstEtys {
+ for tyI, ty := range types {
+ atysAcross[tyI] = ty.TupleElementTypes()[idx]
+ }
+ retEtys[idx], _ = unify(atysAcross, unsafe)
+ if retEtys[idx] == cty.NilType {
+ // Cannot unify this element alone, which means that unification
+ // of everything down to a map type can't be possible either.
+ return cty.NilType, nil
+ }
+ }
+ retTy := cty.Tuple(retEtys)
+
+ conversions := make([]Conversion, len(types))
+ for i, ty := range types {
+ if ty.Equals(retTy) {
+ continue
+ }
+ if unsafe {
+ conversions[i] = GetConversionUnsafe(ty, retTy)
+ } else {
+ conversions[i] = GetConversion(ty, retTy)
+ }
+ if conversions[i] == nil {
+ return unifyTupleTypesToList(types, unsafe)
+ }
+ }
+
+ return retTy, conversions
+}
+
+func unifyTupleTypesToList(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
+ // This is our fallback case for unifyTupleTypes, where we see if we can
+ // construct a list type that can accept all of the element types.
+
+ var etys []cty.Type
+ for _, ty := range types {
+ for _, ety := range ty.TupleElementTypes() {
+ etys = append(etys, ety)
+ }
+ }
+
+ ety, _ := unify(etys, unsafe)
+ if ety == cty.NilType {
+ return cty.NilType, nil
+ }
+
+ retTy := cty.List(ety)
+ conversions := make([]Conversion, len(types))
+ for i, ty := range types {
+ if ty.Equals(retTy) {
+ continue
+ }
+ if unsafe {
+ conversions[i] = GetConversionUnsafe(ty, retTy)
+ } else {
+ conversions[i] = GetConversion(ty, retTy)
+ }
+ if conversions[i] == nil {
+ // no conversion was found
+ return cty.NilType, nil
+ }
+ }
+ return retTy, conversions
+}
+
+func unifyAllAsDynamic(types []cty.Type) (cty.Type, []Conversion) {
+ conversions := make([]Conversion, len(types))
+ for i := range conversions {
+ conversions[i] = func(cty.Value) (cty.Value, error) {
+ return cty.DynamicVal, nil
+ }
+ }
+ return cty.DynamicPseudoType, conversions
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctymarks/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctymarks/doc.go
new file mode 100644
index 00000000000..ff4c6c1a0c4
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctymarks/doc.go
@@ -0,0 +1,3 @@
+// Package ctymarks contains some ancillary types, values, and constants for
+// use with mark-related parts of the main cty package.
+package ctymarks
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctymarks/wrangle.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctymarks/wrangle.go
new file mode 100644
index 00000000000..8b3d6ed328a
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctymarks/wrangle.go
@@ -0,0 +1,58 @@
+package ctymarks
+
+// WrangleAction values each describe an action to be taken for a particular
+// mark at a particular path that has been visited by a [WrangleFunc].
+//
+// A nil value of this type represents taking no action at all, and thereby
+// potentially allowing other later functions to decide an action instead.
+type WrangleAction interface {
+ wrangleAction()
+}
+
+type simpleWrangleAction rune
+
+func (w simpleWrangleAction) wrangleAction() {}
+
+// WrangleKeep is a [WrangleAction] that indicates that the given mark
+// should be retained at the given path and that no subsequent wrangle functions
+// in the same operation should be given an opportunity to visit the same mark.
+const WrangleKeep = simpleWrangleAction('k')
+
+// WrangleDrop is a [WrangleAction] that indicates that the given mark
+// should be dropped at the given path, and that no subsequent wrangle functions
+// in the same operation should be given an opportunity to visit the same mark.
+const WrangleDrop = simpleWrangleAction('d')
+
+// WrangleExpand is a [WrangleAction] that indicates that the given mark
+// should be transferred to the top-level value that the current mark wrangling
+// process is operating on.
+//
+// This effectively means that the mark then applies to all parts of the
+// original top-level value, rather than to only a small part of the nested
+// data structure within it.
+const WrangleExpand = simpleWrangleAction('e')
+
+// WrangleReplace returns a [WrangleAction] that indicates that the given
+// mark should be removed and the given mark inserted in its place.
+//
+// This could be useful when values must cross between systems that use
+// different marks to represent similar concepts, for example.
+func WrangleReplace(newMark any) WrangleAction {
+ if newMark == nil {
+ panic("ctymarks.WrangleReplace with nil mark")
+ }
+ return wrangleReplaceAction{newMark}
+}
+
+// WrangleReplaceMark returns the new mark for the given action if it was
+// created using [WrangleReplace], or nil if it is any other kind of action.
+func WrangleReplaceMark(action WrangleAction) any {
+ replace, _ := action.(wrangleReplaceAction)
+ return replace.newMark
+}
+
+type wrangleReplaceAction struct {
+ newMark any
+}
+
+func (w wrangleReplaceAction) wrangleAction() {}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/doc.go
new file mode 100644
index 00000000000..0ea7f984e41
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/doc.go
@@ -0,0 +1,26 @@
+// Package ctystrings is a collection of string manipulation utilities which
+// intend to help application developers implement string-manipulation
+// functionality in a way that respects the cty model of strings, even when
+// they are working in the realm of Go strings.
+//
+// cty strings are, internally, NFC-normalized as defined in Unicode Standard
+// Annex #15 and encoded as UTF-8.
+//
+// When working with [cty.Value] of string type cty manages this
+// automatically as an implementation detail, but when applications call
+// [Value.AsString] they will receive a value that has been subjected to that
+// normalization, and so may need to take that normalization into account when
+// manipulating the resulting string or comparing it with other Go strings
+// that did not originate in a [cty.Value].
+//
+// Although the core representation of [cty.String] only considers whole
+// strings, it's also conventional in other locations such as the standard
+// library functions to consider strings as being sequences of grapheme
+// clusters as defined by Unicode Standard Annex #29, which adds further
+// rules about combining multiple consecutive codepoints together into a
+// single user-percieved character. Functions that work with substrings should
+// always use grapheme clusters as their smallest unit of splitting strings,
+// and never break strings in the middle of a grapheme cluster. The functions
+// in this package respect that convention unless otherwise stated in their
+// documentation.
+package ctystrings
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/normalize.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/normalize.go
new file mode 100644
index 00000000000..9b3bce9031c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/normalize.go
@@ -0,0 +1,14 @@
+package ctystrings
+
+import (
+ "golang.org/x/text/unicode/norm"
+)
+
+// Normalize applies NFC normalization to the given string, returning the
+// transformed string.
+//
+// This function achieves the same effect as wrapping a string in a value
+// using [cty.StringVal] and then unwrapping it again using [Value.AsString].
+func Normalize(str string) string {
+ return norm.NFC.String(str)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/prefix.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/prefix.go
new file mode 100644
index 00000000000..bbf045233b4
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/ctystrings/prefix.go
@@ -0,0 +1,135 @@
+package ctystrings
+
+import (
+ "fmt"
+ "unicode/utf8"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+ "golang.org/x/text/unicode/norm"
+)
+
+// SafeKnownPrefix takes a string intended to represent a known prefix of
+// another string and modifies it so that it would be safe to use with
+// byte-based prefix matching against another NFC-normalized string. It
+// also takes into account grapheme cluster boundaries and trims off any
+// suffix that could potentially be an incomplete grapheme cluster.
+//
+// Specifically, SafeKnownPrefix first applies NFC normalization to the prefix
+// and then trims off one or more characters from the end of the string which
+// could potentially be transformed into a different character if another
+// string were appended to it. For example, a trailing latin letter will
+// typically be trimmed because appending a combining diacritic mark would
+// transform it into a different character.
+//
+// This transformation is important whenever the remainder of the string is
+// arbitrary user input not directly controlled by the application. If an
+// application can guarantee that the remainder of the string will not begin
+// with combining marks then it is safe to instead just normalize the prefix
+// string with [Normalize].
+func SafeKnownPrefix(prefix string) string {
+ prefix = Normalize(prefix)
+
+ // Our starting approach here is essentially what a streaming parser would
+ // do when consuming a Unicode string in chunks and needing to determine
+ // what prefix of the current buffer is safe to process without waiting for
+ // more information, which is described in TR15 section 13.1
+ // "Buffering with Unicode Normalization":
+ // https://unicode.org/reports/tr15/#Buffering_with_Unicode_Normalization
+ //
+ // The general idea here is to find the last character in the string that
+ // could potentially start a sequence of codepoints that would combine
+ // together, and then truncate the string to exclude that character and
+ // everything after it.
+
+ form := norm.NFC
+ lastBoundary := form.LastBoundary([]byte(prefix))
+ if lastBoundary != -1 && lastBoundary != len(prefix) {
+ prefix = prefix[:lastBoundary]
+ // If we get here then we've already shortened the prefix and so
+ // further analysis below is unnecessary because it would be relying
+ // on an incomplete prefix anyway.
+ return prefix
+ }
+
+ // Now we'll use the textseg package's grapheme cluster scanner to scan
+ // as far through the string as we can without the scanner telling us
+ // that it would need more bytes to decide.
+ //
+ // This step is conservative because the grapheme cluster rules are not
+ // designed with prefix-matching in mind. In the base case we'll just
+ // always discard the last grapheme cluster, although we do have some
+ // special cases for trailing codepoints that can't possibly combine with
+ // subsequent codepoints to form a single grapheme cluster and which seem
+ // likely to arise often in practical use.
+ remain := []byte(prefix)
+ prevBoundary := 0
+ thisBoundary := 0
+ for len(remain) > 0 {
+ advance, _, err := textseg.ScanGraphemeClusters(remain, false)
+ if err != nil {
+ // ScanGraphemeClusters should never return an error because
+ // any sequence of valid UTF-8 encodings is valid input.
+ panic(fmt.Sprintf("textseg.ScanGraphemeClusters returned error: %s", err))
+ }
+ if advance == 0 {
+ // If we have at least one byte remaining but the scanner cannot
+ // advance then that means the remainder might be an incomplete
+ // grapheme cluster and so we need to stop here, discarding the
+ // rest of the input. However, we do now know that we can safely
+ // include what we found on the previous iteration of this loop.
+ prevBoundary = thisBoundary
+ break
+ }
+ prevBoundary = thisBoundary
+ thisBoundary += advance
+ remain = remain[advance:]
+ }
+
+ // This is our heuristic for detecting cases where we can be sure that
+ // the above algorithm was too conservative because the last segment
+ // we found is definitely not subject to the grapheme cluster "do not split"
+ // rules.
+ suspect := prefix[prevBoundary:thisBoundary]
+ if sequenceMustEndGraphemeCluster(suspect) {
+ prevBoundary = thisBoundary
+ }
+
+ return prefix[:prevBoundary]
+}
+
+// sequenceMustEndGraphemeCluster is a heuristic we use to avoid discarding
+// the final grapheme cluster of a prefix in SafeKnownPrefix by recognizing
+// that a particular sequence is one known to not be subject to any of
+// the UAX29 "do not break" rules.
+//
+// If this function returns true then it is safe to include the given byte
+// sequence at the end of a safe prefix. Otherwise we don't know whether or
+// not it is safe.
+func sequenceMustEndGraphemeCluster(s string) bool {
+ // For now we're only considering sequences that represent a single
+ // codepoint. We'll assume that any sequence of two or more codepoints
+ // that could be a grapheme cluster might be extendable.
+ if utf8.RuneCountInString(s) != 1 {
+ return false
+ }
+
+ r, _ := utf8.DecodeRuneInString(s)
+
+ // Our initial ruleset is focused on characters that are commonly used
+ // as delimiters in text intended for both human and machine use, such
+ // as JSON documents.
+ //
+ // We don't include any letters or digits of any script here intentionally
+ // because those are the ones most likely to be subject to combining rules
+ // in either current or future Unicode specifications.
+ //
+ // We can safely grow this set over time, but we should be very careful
+ // about shrinking it because it could cause value refinements to loosen
+ // and thus cause results that were once known to become unknown.
+ switch r {
+ case '-', '_', ':', ';', '/', '\\', ',', '.', '(', ')', '{', '}', '[', ']', '|', '?', '!', '~', ' ', '\t', '@', '#', '$', '%', '^', '&', '*', '+', '"', '\'':
+ return true
+ default:
+ return false
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/doc.go
new file mode 100644
index 00000000000..d31f0547bf4
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/doc.go
@@ -0,0 +1,18 @@
+// Package cty (pronounced see-tie) provides some infrastructure for a type
+// system that might be useful for applications that need to represent
+// configuration values provided by the user whose types are not known
+// at compile time, particularly if the calling application also allows
+// such values to be used in expressions.
+//
+// The type system consists of primitive types Number, String and Bool, as
+// well as List and Map collection types and Object types that can have
+// arbitrarily-typed sets of attributes.
+//
+// A set of operations is defined on these types, which is accessible via
+// the wrapper struct Value, which annotates the raw, internal representation
+// of a value with its corresponding type.
+//
+// This package is oriented towards being a building block for configuration
+// languages used to bootstrap an application. It is not optimized for use
+// in tight loops where CPU time or memory pressure are a concern.
+package cty
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/element_iterator.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
new file mode 100644
index 00000000000..2f7ec4bfe1e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
@@ -0,0 +1,194 @@
+package cty
+
+import (
+ "sort"
+
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// ElementIterator is the interface type returned by Value.ElementIterator to
+// allow the caller to iterate over elements of a collection-typed value.
+//
+// Its usage pattern is as follows:
+//
+// it := val.ElementIterator()
+// for it.Next() {
+// key, val := it.Element()
+// // ...
+// }
+type ElementIterator interface {
+ Next() bool
+ Element() (key Value, value Value)
+}
+
+func canElementIterator(val Value) bool {
+ switch {
+ case val.IsMarked():
+ return false
+ case val.ty.IsListType():
+ return true
+ case val.ty.IsMapType():
+ return true
+ case val.ty.IsSetType():
+ return true
+ case val.ty.IsTupleType():
+ return true
+ case val.ty.IsObjectType():
+ return true
+ default:
+ return false
+ }
+}
+
+func elementIterator(val Value) ElementIterator {
+ val.assertUnmarked()
+ switch {
+ case val.ty.IsListType():
+ return &listElementIterator{
+ ety: val.ty.ElementType(),
+ vals: val.v.([]any),
+ idx: -1,
+ }
+ case val.ty.IsMapType():
+ // We iterate the keys in a predictable lexicographical order so
+ // that results will always be stable given the same input map.
+ rawMap := val.v.(map[string]any)
+ keys := make([]string, 0, len(rawMap))
+ for key := range rawMap {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ return &mapElementIterator{
+ ety: val.ty.ElementType(),
+ vals: rawMap,
+ keys: keys,
+ idx: -1,
+ }
+ case val.ty.IsSetType():
+ rawSet := val.v.(set.Set[any])
+ return &setElementIterator{
+ ety: val.ty.ElementType(),
+ setIt: rawSet.Iterator(),
+ }
+ case val.ty.IsTupleType():
+ return &tupleElementIterator{
+ etys: val.ty.TupleElementTypes(),
+ vals: val.v.([]any),
+ idx: -1,
+ }
+ case val.ty.IsObjectType():
+ // We iterate the keys in a predictable lexicographical order so
+ // that results will always be stable given the same object type.
+ atys := val.ty.AttributeTypes()
+ keys := make([]string, 0, len(atys))
+ for key := range atys {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ return &objectElementIterator{
+ atys: atys,
+ vals: val.v.(map[string]any),
+ attrNames: keys,
+ idx: -1,
+ }
+ default:
+ panic("attempt to iterate on non-collection, non-tuple type")
+ }
+}
+
+type listElementIterator struct {
+ ety Type
+ vals []any
+ idx int
+}
+
+func (it *listElementIterator) Element() (Value, Value) {
+ i := it.idx
+ return NumberIntVal(int64(i)), Value{
+ ty: it.ety,
+ v: it.vals[i],
+ }
+}
+
+func (it *listElementIterator) Next() bool {
+ it.idx++
+ return it.idx < len(it.vals)
+}
+
+type mapElementIterator struct {
+ ety Type
+ vals map[string]any
+ keys []string
+ idx int
+}
+
+func (it *mapElementIterator) Element() (Value, Value) {
+ key := it.keys[it.idx]
+ return StringVal(key), Value{
+ ty: it.ety,
+ v: it.vals[key],
+ }
+}
+
+func (it *mapElementIterator) Next() bool {
+ it.idx++
+ return it.idx < len(it.keys)
+}
+
+type setElementIterator struct {
+ ety Type
+ setIt *set.Iterator[any]
+}
+
+func (it *setElementIterator) Element() (Value, Value) {
+ val := Value{
+ ty: it.ety,
+ v: it.setIt.Value(),
+ }
+ return val, val
+}
+
+func (it *setElementIterator) Next() bool {
+ return it.setIt.Next()
+}
+
+type tupleElementIterator struct {
+ etys []Type
+ vals []any
+ idx int
+}
+
+func (it *tupleElementIterator) Element() (Value, Value) {
+ i := it.idx
+ return NumberIntVal(int64(i)), Value{
+ ty: it.etys[i],
+ v: it.vals[i],
+ }
+}
+
+func (it *tupleElementIterator) Next() bool {
+ it.idx++
+ return it.idx < len(it.vals)
+}
+
+type objectElementIterator struct {
+ atys map[string]Type
+ vals map[string]any
+ attrNames []string
+ idx int
+}
+
+func (it *objectElementIterator) Element() (Value, Value) {
+ key := it.attrNames[it.idx]
+ return StringVal(key), Value{
+ ty: it.atys[key],
+ v: it.vals[key],
+ }
+}
+
+func (it *objectElementIterator) Next() bool {
+ it.idx++
+ return it.idx < len(it.attrNames)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/error.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/error.go
new file mode 100644
index 00000000000..920084c3c8c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/error.go
@@ -0,0 +1,55 @@
+package cty
+
+import (
+ "fmt"
+)
+
+// PathError is a specialization of error that represents where in a
+// potentially-deep data structure an error occured, using a Path.
+type PathError struct {
+ error
+ Path Path
+}
+
+func errorf(path Path, f string, args ...any) error {
+ // We need to copy the Path because often our caller builds it by
+ // continually mutating the same underlying buffer.
+ sPath := make(Path, len(path))
+ copy(sPath, path)
+ return PathError{
+ error: fmt.Errorf(f, args...),
+ Path: sPath,
+ }
+}
+
+// NewErrorf creates a new PathError for the current path by passing the
+// given format and arguments to fmt.Errorf and then wrapping the result
+// similarly to NewError.
+func (p Path) NewErrorf(f string, args ...any) error {
+ return errorf(p, f, args...)
+}
+
+// NewError creates a new PathError for the current path, wrapping the given
+// error.
+func (p Path) NewError(err error) error {
+ // if we're being asked to wrap an existing PathError then our new
+ // PathError will be the concatenation of the two paths, ensuring
+ // that we still get a single flat PathError that's thus easier for
+ // callers to deal with.
+ perr, wrappingPath := err.(PathError)
+ pathLen := len(p)
+ if wrappingPath {
+ pathLen = pathLen + len(perr.Path)
+ }
+
+ sPath := make(Path, pathLen)
+ copy(sPath, p)
+ if wrappingPath {
+ copy(sPath[len(p):], perr.Path)
+ }
+
+ return PathError{
+ error: err,
+ Path: sPath,
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/argument.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/argument.go
new file mode 100644
index 00000000000..61a1cf97df1
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/argument.go
@@ -0,0 +1,73 @@
+package function
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// Parameter represents a parameter to a function.
+type Parameter struct {
+ // Name is an optional name for the argument. This package ignores this
+ // value, but callers may use it for documentation, etc.
+ Name string
+
+ // Description is an optional description for the argument.
+ Description string
+
+ // A type that any argument for this parameter must conform to.
+ // cty.DynamicPseudoType can be used, either at top-level or nested
+ // in a parameterized type, to indicate that any type should be
+ // permitted, to allow the definition of type-generic functions.
+ Type cty.Type
+
+ // If AllowNull is set then null values may be passed into this
+ // argument's slot in both the type-check function and the implementation
+ // function. If not set, such values are rejected by the built-in
+ // checking rules.
+ AllowNull bool
+
+ // If AllowUnknown is set then unknown values may be passed into this
+ // argument's slot in the implementation function. If not set, any
+ // unknown values will cause the function to immediately return
+ // an unkonwn value without calling the implementation function, thus
+ // freeing the function implementer from dealing with this case.
+ AllowUnknown bool
+
+ // If AllowDynamicType is set then DynamicVal may be passed into this
+ // argument's slot in the implementation function. If not set, any
+ // dynamic values will cause the function to immediately return
+ // DynamicVal value without calling the implementation function, thus
+ // freeing the function implementer from dealing with this case.
+ //
+ // Note that DynamicVal is also unknown, so in order to receive dynamic
+ // *values* it is also necessary to set AllowUnknown.
+ //
+ // However, it is valid to set AllowDynamicType without AllowUnknown, in
+ // which case a dynamic value may be passed to the type checking function
+ // but will not make it to the *implementation* function. Instead, an
+ // unknown value of the type returned by the type-check function will be
+ // returned. This is suggested for functions that have a static return
+ // type since it allows the return value to be typed even if the input
+ // values are not, thus improving the type-check accuracy of derived
+ // values.
+ AllowDynamicType bool
+
+ // If AllowMarked is set then marked values may be passed into this
+ // argument's slot in the implementation function. If not set, any
+ // marked value will be unmarked before calling and then the markings
+ // from that value will be applied automatically to the function result,
+ // ensuring that the marks get propagated in a simplistic way even if
+ // a function is unable to handle them.
+ //
+ // For any argument whose parameter has AllowMarked set, it's the
+ // function implementation's responsibility to Unmark the given value
+ // and propagate the marks appropriatedly to the result in order to
+ // avoid losing the marks. Application-specific functions might use
+ // special rules to selectively propagate particular marks.
+ //
+ // The automatic unmarking of values applies only to the main
+ // implementation function. In an application that uses marked values,
+ // the Type implementation for a function must always be prepared to accept
+ // marked values, which is easy to achieve by consulting only the type
+ // and ignoring the value itself.
+ AllowMarked bool
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/doc.go
new file mode 100644
index 00000000000..393b3110bc5
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/doc.go
@@ -0,0 +1,6 @@
+// Package function builds on the functionality of cty by modeling functions
+// that operate on cty Values.
+//
+// Functions are, at their core, Go anonymous functions. However, this package
+// wraps around them utility functions for parameter type checking, etc.
+package function
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/error.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/error.go
new file mode 100644
index 00000000000..4ed96bde37e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/error.go
@@ -0,0 +1,50 @@
+package function
+
+import (
+ "fmt"
+ "runtime/debug"
+)
+
+// ArgError represents an error with one of the arguments in a call. The
+// attribute Index represents the zero-based index of the argument in question.
+//
+// Its error *may* be a cty.PathError, in which case the error actually
+// pertains to a nested value within the data structure passed as the argument.
+type ArgError struct {
+ error
+ Index int
+}
+
+func NewArgErrorf(i int, f string, args ...any) error {
+ return ArgError{
+ error: fmt.Errorf(f, args...),
+ Index: i,
+ }
+}
+
+func NewArgError(i int, err error) error {
+ return ArgError{
+ error: err,
+ Index: i,
+ }
+}
+
+// PanicError indicates that a panic occurred while executing either a
+// function's type or implementation function. This is captured and wrapped
+// into a normal error so that callers (expected to be language runtimes)
+// are freed from having to deal with panics in buggy functions.
+type PanicError struct {
+ Value any
+ Stack []byte
+}
+
+func errorForPanic(val any) error {
+ return PanicError{
+ Value: val,
+ Stack: debug.Stack(),
+ }
+}
+
+func (e PanicError) Error() string {
+ return fmt.Sprintf("panic in function implementation: %s\n%s", e.Value, e.Stack)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/function.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/function.go
new file mode 100644
index 00000000000..4d7c61d01ea
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/function.go
@@ -0,0 +1,463 @@
+package function
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// Function represents a function. This is the main type in this package.
+type Function struct {
+ spec *Spec
+}
+
+// Spec is the specification of a function, used to instantiate
+// a new Function.
+type Spec struct {
+ // Description is an optional description for the function specification.
+ Description string
+
+ // Params is a description of the positional parameters for the function.
+ // The standard checking logic rejects any calls that do not provide
+ // arguments conforming to this definition, freeing the function
+ // implementer from dealing with such inconsistencies.
+ Params []Parameter
+
+ // VarParam is an optional specification of additional "varargs" the
+ // function accepts. If this is non-nil then callers may provide an
+ // arbitrary number of additional arguments (after those matching with
+ // the fixed parameters in Params) that conform to the given specification,
+ // which will appear as additional values in the slices of values
+ // provided to the type and implementation functions.
+ VarParam *Parameter
+
+ // Type is the TypeFunc that decides the return type of the function
+ // given its arguments, which may be Unknown. See the documentation
+ // of TypeFunc for more information.
+ //
+ // Use StaticReturnType if the function's return type does not vary
+ // depending on its arguments.
+ Type TypeFunc
+
+ // RefineResult is an optional callback for describing additional
+ // refinements for the result value beyond what can be described using
+ // a type constraint.
+ //
+ // A refinement callback should always return the same builder it was
+ // given, typically after modifying it using the methods of
+ // [cty.RefinementBuilder].
+ //
+ // Any refinements described by this callback must hold for the entire
+ // range of results from the function. For refinements that only apply
+ // to certain results, use direct refinement within [Impl] instead.
+ RefineResult func(*cty.RefinementBuilder) *cty.RefinementBuilder
+
+ // Impl is the ImplFunc that implements the function's behavior.
+ //
+ // Functions are expected to behave as pure functions, and not create
+ // any visible side-effects.
+ //
+ // If a TypeFunc is also provided, the value returned from Impl *must*
+ // conform to the type it returns, or a call to the function will panic.
+ Impl ImplFunc
+}
+
+// New creates a new function with the given specification.
+//
+// After passing a Spec to this function, the caller must no longer read from
+// or mutate it.
+func New(spec *Spec) Function {
+ f := Function{
+ spec: spec,
+ }
+ return f
+}
+
+// TypeFunc is a callback type for determining the return type of a function
+// given its arguments.
+//
+// Any of the values passed to this function may be unknown, even if the
+// parameters are not configured to accept unknowns.
+//
+// If any of the given values are *not* unknown, the TypeFunc may use the
+// values for pre-validation and for choosing the return type. For example,
+// a hypothetical JSON-unmarshalling function could return
+// cty.DynamicPseudoType if the given JSON string is unknown, but return
+// a concrete type based on the JSON structure if the JSON string is already
+// known.
+type TypeFunc func(args []cty.Value) (cty.Type, error)
+
+// ImplFunc is a callback type for the main implementation of a function.
+//
+// "args" are the values for the arguments, and this slice will always be at
+// least as long as the argument definition slice for the function.
+//
+// "retType" is the type returned from the Type callback, included as a
+// convenience to avoid the need to re-compute the return type for generic
+// functions whose return type is a function of the arguments.
+type ImplFunc func(args []cty.Value, retType cty.Type) (cty.Value, error)
+
+// StaticReturnType returns a TypeFunc that always returns the given type.
+//
+// This is provided as a convenience for defining a function whose return
+// type does not depend on the argument types.
+func StaticReturnType(ty cty.Type) TypeFunc {
+ return func([]cty.Value) (cty.Type, error) {
+ return ty, nil
+ }
+}
+
+// ReturnType returns the return type of a function given a set of candidate
+// argument types, or returns an error if the given types are unacceptable.
+//
+// If the caller already knows values for at least some of the arguments
+// it can be better to call ReturnTypeForValues, since certain functions may
+// determine their return types from their values and return DynamicVal if
+// the values are unknown.
+func (f Function) ReturnType(argTypes []cty.Type) (cty.Type, error) {
+ vals := make([]cty.Value, len(argTypes))
+ for i, ty := range argTypes {
+ vals[i] = cty.UnknownVal(ty)
+ }
+ return f.ReturnTypeForValues(vals)
+}
+
+func (f Function) returnTypeForValues(args []cty.Value) (ty cty.Type, dynTypedArgs bool, err error) {
+ var posArgs []cty.Value
+ var varArgs []cty.Value
+
+ if f.spec.VarParam == nil {
+ if len(args) != len(f.spec.Params) {
+ return cty.Type{}, false, fmt.Errorf(
+ "wrong number of arguments (%d required; %d given)",
+ len(f.spec.Params), len(args),
+ )
+ }
+
+ posArgs = args
+ varArgs = nil
+ } else {
+ if len(args) < len(f.spec.Params) {
+ return cty.Type{}, false, fmt.Errorf(
+ "wrong number of arguments (at least %d required; %d given)",
+ len(f.spec.Params), len(args),
+ )
+ }
+
+ posArgs = args[0:len(f.spec.Params)]
+ varArgs = args[len(f.spec.Params):]
+ }
+
+ for i, spec := range f.spec.Params {
+ val := posArgs[i]
+
+ if val.ContainsMarked() && !spec.AllowMarked {
+ // During type checking we just unmark values and discard their
+ // marks, under the assumption that during actual execution of
+ // the function we'll do similarly and then re-apply the marks
+ // afterwards. Note that this does mean that a function that
+ // inspects values (rather than just types) in its Type
+ // implementation can potentially fail to take into account marks,
+ // unless it specifically opts in to seeing them.
+ unmarked, _ := val.UnmarkDeep()
+ newArgs := make([]cty.Value, len(args))
+ copy(newArgs, args)
+ newArgs[i] = unmarked
+ args = newArgs
+ }
+
+ if val.IsNull() && !spec.AllowNull {
+ return cty.Type{}, false, NewArgErrorf(i, "argument must not be null")
+ }
+
+ // AllowUnknown is ignored for type-checking, since we expect to be
+ // able to type check with unknown values. We *do* still need to deal
+ // with DynamicPseudoType here though, since the Type function might
+ // not be ready to deal with that.
+
+ if val.Type() == cty.DynamicPseudoType {
+ if !spec.AllowDynamicType {
+ return cty.DynamicPseudoType, true, nil
+ }
+ } else if errs := val.Type().TestConformance(spec.Type); errs != nil {
+ // For now we'll just return the first error in the set, since
+ // we don't have a good way to return the whole list here.
+ // Would be good to do something better at some point...
+ return cty.Type{}, false, NewArgError(i, errs[0])
+ }
+ }
+
+ if varArgs != nil {
+ spec := f.spec.VarParam
+ for i, val := range varArgs {
+ realI := i + len(posArgs)
+
+ if val.ContainsMarked() && !spec.AllowMarked {
+ // See the similar block in the loop above for what's going on here.
+ unmarked, _ := val.UnmarkDeep()
+ newArgs := make([]cty.Value, len(args))
+ copy(newArgs, args)
+ newArgs[realI] = unmarked
+ args = newArgs
+ }
+
+ if val.IsNull() && !spec.AllowNull {
+ return cty.Type{}, false, NewArgErrorf(realI, "argument must not be null")
+ }
+
+ if val.Type() == cty.DynamicPseudoType {
+ if !spec.AllowDynamicType {
+ return cty.DynamicPseudoType, true, nil
+ }
+ } else if errs := val.Type().TestConformance(spec.Type); errs != nil {
+ // For now we'll just return the first error in the set, since
+ // we don't have a good way to return the whole list here.
+ // Would be good to do something better at some point...
+ return cty.Type{}, false, NewArgError(i, errs[0])
+ }
+ }
+ }
+
+ // Intercept any panics from the function and return them as normal errors,
+ // so a calling language runtime doesn't need to deal with panics.
+ defer func() {
+ if r := recover(); r != nil {
+ ty = cty.NilType
+ err = errorForPanic(r)
+ }
+ }()
+
+ ty, err = f.spec.Type(args)
+ return ty, false, err
+}
+
+// ReturnTypeForValues is similar to ReturnType but can be used if the caller
+// already knows the values of some or all of the arguments, in which case
+// the function may be able to determine a more definite result if its
+// return type depends on the argument *values*.
+//
+// For any arguments whose values are not known, pass an Unknown value of
+// the appropriate type.
+func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error) {
+ ty, _, err = f.returnTypeForValues(args)
+ return ty, err
+}
+
+// Call actually calls the function with the given arguments, which must
+// conform to the function's parameter specification or an error will be
+// returned.
+func (f Function) Call(args []cty.Value) (val cty.Value, err error) {
+ expectedType, dynTypeArgs, err := f.returnTypeForValues(args)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ var resultMarks []cty.ValueMarks
+ // If we are returning an unknown early due to some unknown in the
+ // arguments, we first need to complete the iteration over all the args
+ // to ensure we collect as many marks as possible for resultMarks.
+ returnUnknown := false
+
+ if dynTypeArgs {
+ // returnTypeForValues sets this if any argument was inexactly typed
+ // and the corresponding parameter did not indicate it could deal with
+ // that. In that case we also avoid calling the implementation function
+ // because it will also typically not be ready to deal with that case.
+ returnUnknown = true
+ }
+
+ // If returnUnknown is set already, it means we don't have a refinement
+ // because of dynTypeArgs, but we may still need to collect marks from the
+ // rest of the arguments.
+ if refineResult := f.spec.RefineResult; refineResult != nil && !returnUnknown {
+ // If this function has a refinement callback then we'll refine
+ // our result value in the same way regardless of how we return.
+ // It's the function author's responsibility to ensure that the
+ // refinements they specify are valid for the full range of possible
+ // return values from the function. If not, this will panic when
+ // detecting an inconsistency.
+ defer func() {
+ if val != cty.NilVal {
+ if val.IsKnown() || val.Type() != cty.DynamicPseudoType {
+ val = val.RefineWith(refineResult)
+ }
+ }
+ }()
+ }
+
+ // Type checking already dealt with most situations relating to our
+ // parameter specification, but we still need to deal with unknown
+ // values and marked values.
+ posArgs := args[:len(f.spec.Params)]
+ varArgs := args[len(f.spec.Params):]
+
+ for i, spec := range f.spec.Params {
+ val := posArgs[i]
+
+ if !spec.AllowMarked {
+ unwrappedVal, marks := val.UnmarkDeep()
+ if len(marks) > 0 {
+ // In order to avoid additional overhead on applications that
+ // are not using marked values, we copy the given args only
+ // if we encounter a marked value we need to unmark. However,
+ // as a consequence we end up doing redundant copying if multiple
+ // marked values need to be unwrapped. That seems okay because
+ // argument lists are generally small.
+ newArgs := make([]cty.Value, len(args))
+ copy(newArgs, args)
+ newArgs[i] = unwrappedVal
+ resultMarks = append(resultMarks, marks)
+ args = newArgs
+ }
+ }
+
+ if !val.IsKnown() && !spec.AllowUnknown {
+ returnUnknown = true
+ }
+ }
+
+ if f.spec.VarParam != nil {
+ spec := f.spec.VarParam
+ for i, val := range varArgs {
+ if !spec.AllowMarked {
+ unwrappedVal, marks := val.UnmarkDeep()
+ if len(marks) > 0 {
+ newArgs := make([]cty.Value, len(args))
+ copy(newArgs, args)
+ newArgs[len(posArgs)+i] = unwrappedVal
+ resultMarks = append(resultMarks, marks)
+ args = newArgs
+ }
+ }
+ if !val.IsKnown() && !spec.AllowUnknown {
+ returnUnknown = true
+ }
+ }
+ }
+
+ if returnUnknown {
+ return cty.UnknownVal(expectedType).WithMarks(resultMarks...), nil
+ }
+
+ var retVal cty.Value
+ {
+ // Intercept any panics from the function and return them as normal errors,
+ // so a calling language runtime doesn't need to deal with panics.
+ defer func() {
+ if r := recover(); r != nil {
+ val = cty.NilVal
+ err = errorForPanic(r)
+ }
+ }()
+
+ retVal, err = f.spec.Impl(args, expectedType)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ if len(resultMarks) > 0 {
+ retVal = retVal.WithMarks(resultMarks...)
+ }
+ }
+
+ // Returned value must conform to what the Type function expected, to
+ // protect callers from having to deal with inconsistencies.
+ if errs := retVal.Type().TestConformance(expectedType); errs != nil {
+ panic(fmt.Errorf(
+ "returned value %#v does not conform to expected return type %#v: %s",
+ retVal, expectedType, errs[0],
+ ))
+ }
+
+ return retVal, nil
+}
+
+// ProxyFunc the type returned by the method Function.Proxy.
+type ProxyFunc func(args ...cty.Value) (cty.Value, error)
+
+// Proxy returns a function that can be called with cty.Value arguments
+// to run the function. This is provided as a convenience for when using
+// a function directly within Go code.
+func (f Function) Proxy() ProxyFunc {
+ return func(args ...cty.Value) (cty.Value, error) {
+ return f.Call(args)
+ }
+}
+
+// Params returns information about the function's fixed positional parameters.
+// This does not include information about any variadic arguments accepted;
+// for that, call VarParam.
+func (f Function) Params() []Parameter {
+ new := make([]Parameter, len(f.spec.Params))
+ copy(new, f.spec.Params)
+ return new
+}
+
+// VarParam returns information about the variadic arguments the function
+// expects, or nil if the function is not variadic.
+func (f Function) VarParam() *Parameter {
+ if f.spec.VarParam == nil {
+ return nil
+ }
+
+ ret := *f.spec.VarParam
+ return &ret
+}
+
+// Description returns a human-readable description of the function.
+func (f Function) Description() string {
+ return f.spec.Description
+}
+
+// WithNewDescriptions returns a new function that has the same signature
+// and implementation as the receiver but has the function description and
+// the parameter descriptions replaced with those given in the arguments.
+//
+// All descriptions may be given as an empty string to specify that there
+// should be no description at all.
+//
+// The paramDescs argument must match the number of parameters
+// the reciever expects, or this function will panic. If the function has a
+// VarParam then that counts as one parameter for the sake of this rule. The
+// given descriptions will be assigned in order starting with the positional
+// arguments in their declared order, followed by the variadic parameter if
+// any.
+//
+// As a special case, WithNewDescriptions will accept a paramDescs which
+// does not cover the reciever's variadic parameter (if any), so that it's
+// possible to add a variadic parameter to a function which didn't previously
+// have one without that being a breaking change for an existing caller using
+// WithNewDescriptions against that function. In this case the base description
+// of the variadic parameter will be preserved.
+func (f Function) WithNewDescriptions(funcDesc string, paramDescs []string) Function {
+ retSpec := *f.spec // shallow copy of the reciever
+ retSpec.Description = funcDesc
+
+ retSpec.Params = make([]Parameter, len(f.spec.Params))
+ copy(retSpec.Params, f.spec.Params) // shallow copy of positional parameters
+ if f.spec.VarParam != nil {
+ retVarParam := *f.spec.VarParam // shallow copy of variadic parameter
+ retSpec.VarParam = &retVarParam
+ }
+
+ if retSpec.VarParam != nil {
+ if with, without := len(retSpec.Params)+1, len(retSpec.Params); len(paramDescs) != with && len(paramDescs) != without {
+ panic(fmt.Sprintf("paramDescs must have length of either %d or %d", with, without))
+ }
+ } else {
+ if want := len(retSpec.Params); len(paramDescs) != want {
+ panic(fmt.Sprintf("paramDescs must have length %d", want))
+ }
+ }
+
+ posParamDescs := paramDescs[:len(retSpec.Params)]
+ varParamDescs := paramDescs[len(retSpec.Params):] // guaranteed to be zero or one elements because of the rules above
+
+ for i, desc := range posParamDescs {
+ retSpec.Params[i].Description = desc
+ }
+ for _, desc := range varParamDescs {
+ retSpec.VarParam.Description = desc
+ }
+
+ return New(&retSpec)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go
new file mode 100644
index 00000000000..2826bf6eb02
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go
@@ -0,0 +1,84 @@
+package stdlib
+
+import (
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var NotFunc = function.New(&function.Spec{
+ Description: `Applies the logical NOT operation to the given boolean value.`,
+ Params: []function.Parameter{
+ {
+ Name: "val",
+ Type: cty.Bool,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return args[0].Not(), nil
+ },
+})
+
+var AndFunc = function.New(&function.Spec{
+ Description: `Applies the logical AND operation to the given boolean values.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Bool,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Bool,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return args[0].And(args[1]), nil
+ },
+})
+
+var OrFunc = function.New(&function.Spec{
+ Description: `Applies the logical OR operation to the given boolean values.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Bool,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Bool,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return args[0].Or(args[1]), nil
+ },
+})
+
+// Not returns the logical complement of the given boolean value.
+func Not(num cty.Value) (cty.Value, error) {
+ return NotFunc.Call([]cty.Value{num})
+}
+
+// And returns true if and only if both of the given boolean values are true.
+func And(a, b cty.Value) (cty.Value, error) {
+ return AndFunc.Call([]cty.Value{a, b})
+}
+
+// Or returns true if either of the given boolean values are true.
+func Or(a, b cty.Value) (cty.Value, error) {
+ return OrFunc.Call([]cty.Value{a, b})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go
new file mode 100644
index 00000000000..fe67e6f3fe9
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go
@@ -0,0 +1,116 @@
+package stdlib
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/gocty"
+)
+
+// Bytes is a capsule type that can be used with the binary functions to
+// support applications that need to support raw buffers in addition to
+// UTF-8 strings.
+var Bytes = cty.Capsule("bytes", reflect.TypeOf([]byte(nil)))
+
+// BytesVal creates a new Bytes value from the given buffer, which must be
+// non-nil or this function will panic.
+//
+// Once a byte slice has been wrapped in a Bytes capsule, its underlying array
+// must be considered immutable.
+func BytesVal(buf []byte) cty.Value {
+ if buf == nil {
+ panic("can't make Bytes value from nil slice")
+ }
+
+ return cty.CapsuleVal(Bytes, &buf)
+}
+
+// BytesLen is a Function that returns the length of the buffer encapsulated
+// in a Bytes value.
+var BytesLenFunc = function.New(&function.Spec{
+ Description: `Returns the total number of bytes in the given buffer.`,
+ Params: []function.Parameter{
+ {
+ Name: "buf",
+ Type: Bytes,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ bufPtr := args[0].EncapsulatedValue().(*[]byte)
+ return cty.NumberIntVal(int64(len(*bufPtr))), nil
+ },
+})
+
+// BytesSlice is a Function that returns a slice of the given Bytes value.
+var BytesSliceFunc = function.New(&function.Spec{
+ Description: `Extracts a subslice from the given buffer.`,
+ Params: []function.Parameter{
+ {
+ Name: "buf",
+ Type: Bytes,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "offset",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "length",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(Bytes),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ bufPtr := args[0].EncapsulatedValue().(*[]byte)
+
+ var offset, length int
+
+ var err error
+ err = gocty.FromCtyValue(args[1], &offset)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ err = gocty.FromCtyValue(args[2], &length)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ if offset < 0 || length < 0 {
+ return cty.NilVal, fmt.Errorf("offset and length must be non-negative")
+ }
+
+ if offset > len(*bufPtr) {
+ return cty.NilVal, fmt.Errorf(
+ "offset %d is greater than total buffer length %d",
+ offset, len(*bufPtr),
+ )
+ }
+
+ end := offset + length
+
+ if end > len(*bufPtr) {
+ return cty.NilVal, fmt.Errorf(
+ "offset %d + length %d is greater than total buffer length %d",
+ offset, length, len(*bufPtr),
+ )
+ }
+
+ return BytesVal((*bufPtr)[offset:end]), nil
+ },
+})
+
+func BytesLen(buf cty.Value) (cty.Value, error) {
+ return BytesLenFunc.Call([]cty.Value{buf})
+}
+
+func BytesSlice(buf cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
+ return BytesSliceFunc.Call([]cty.Value{buf, offset, length})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
new file mode 100644
index 00000000000..d3df0ea9601
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
@@ -0,0 +1,1545 @@
+package stdlib
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/gocty"
+)
+
+var HasIndexFunc = function.New(&function.Spec{
+ Description: `Returns true if if the given collection can be indexed with the given key without producing an error, or false otherwise.`,
+ Params: []function.Parameter{
+ {
+ Name: "collection",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "key",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ },
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ collTy := args[0].Type()
+ if !(collTy.IsTupleType() || collTy.IsListType() || collTy.IsMapType() || collTy == cty.DynamicPseudoType) {
+ return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
+ }
+ return cty.Bool, nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].HasIndex(args[1]), nil
+ },
+})
+
+var IndexFunc = function.New(&function.Spec{
+ Description: `Returns the element with the given key from the given collection, or raises an error if there is no such element.`,
+ Params: []function.Parameter{
+ {
+ Name: "collection",
+ Type: cty.DynamicPseudoType,
+ },
+ {
+ Name: "key",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ },
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ collTy := args[0].Type()
+ key := args[1]
+ keyTy := key.Type()
+ switch {
+ case collTy.IsTupleType():
+ if keyTy != cty.Number && keyTy != cty.DynamicPseudoType {
+ return cty.NilType, fmt.Errorf("key for tuple must be number")
+ }
+ if !key.IsKnown() {
+ return cty.DynamicPseudoType, nil
+ }
+ var idx int
+ err := gocty.FromCtyValue(key, &idx)
+ if err != nil {
+ return cty.NilType, fmt.Errorf("invalid key for tuple: %s", err)
+ }
+
+ etys := collTy.TupleElementTypes()
+
+ if idx >= len(etys) || idx < 0 {
+ return cty.NilType, fmt.Errorf("key must be between 0 and %d inclusive", len(etys))
+ }
+
+ return etys[idx], nil
+
+ case collTy.IsListType():
+ if keyTy != cty.Number && keyTy != cty.DynamicPseudoType {
+ return cty.NilType, fmt.Errorf("key for list must be number")
+ }
+
+ return collTy.ElementType(), nil
+
+ case collTy.IsMapType():
+ if keyTy != cty.String && keyTy != cty.DynamicPseudoType {
+ return cty.NilType, fmt.Errorf("key for map must be string")
+ }
+
+ return collTy.ElementType(), nil
+
+ default:
+ return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
+ }
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ has, err := HasIndex(args[0], args[1])
+ if err != nil {
+ return cty.NilVal, err
+ }
+ if has.False() { // safe because collection and key are guaranteed known here
+ return cty.NilVal, fmt.Errorf("invalid index")
+ }
+
+ return args[0].Index(args[1]), nil
+ },
+})
+
+var LengthFunc = function.New(&function.Spec{
+ Description: `Returns the number of elements in the given collection.`,
+ Params: []function.Parameter{
+ {
+ Name: "collection",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ AllowUnknown: true,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ collTy := args[0].Type()
+ if !(collTy.IsTupleType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType) {
+ return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
+ }
+ return cty.Number, nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].Length(), nil
+ },
+})
+
+var ElementFunc = function.New(&function.Spec{
+ Description: `Returns the element with the given index from the given list or tuple, applying the modulo operation to the given index if it's greater than the number of elements.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ {
+ Name: "index",
+ Type: cty.Number,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ list := args[0]
+
+ listTy := list.Type()
+ switch {
+ case listTy.IsListType():
+ return listTy.ElementType(), nil
+ case listTy.IsTupleType():
+ if !args[1].IsKnown() {
+ // If the index isn't known yet then we can't predict the
+ // result type since each tuple element can have its own type.
+ return cty.DynamicPseudoType, nil
+ }
+
+ etys := listTy.TupleElementTypes()
+ var index int
+ err := gocty.FromCtyValue(args[1], &index)
+ if err != nil {
+ // e.g. fractional number where whole number is required
+ return cty.DynamicPseudoType, fmt.Errorf("invalid index: %s", err)
+ }
+ if len(etys) == 0 {
+ return cty.DynamicPseudoType, errors.New("cannot use element function with an empty list")
+ }
+ index = index % len(etys)
+ if index < 0 {
+ index += len(etys)
+ }
+ return etys[index], nil
+ default:
+ return cty.DynamicPseudoType, fmt.Errorf("cannot read elements from %s", listTy.FriendlyName())
+ }
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ var index int
+ err := gocty.FromCtyValue(args[1], &index)
+ if err != nil {
+ // can't happen because we checked this in the Type function above
+ return cty.DynamicVal, fmt.Errorf("invalid index: %s", err)
+ }
+
+ input, marks := args[0].Unmark()
+ if !input.IsKnown() {
+ return cty.UnknownVal(retType), nil
+ }
+
+ l := input.LengthInt()
+ if l == 0 {
+ return cty.DynamicVal, errors.New("cannot use element function with an empty list")
+ }
+ index = index % l
+ if index < 0 {
+ index += l
+ }
+
+ // We did all the necessary type checks in the type function above,
+ // so this is guaranteed not to fail.
+ return input.Index(cty.NumberIntVal(int64(index))).WithMarks(marks), nil
+ },
+})
+
+// CoalesceListFunc is a function that takes any number of list arguments
+// and returns the first one that isn't empty.
+var CoalesceListFunc = function.New(&function.Spec{
+ Description: `Returns the first of the given sequences that has a length greater than zero.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "vals",
+ Description: `List or tuple values to test in the given order.`,
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ if len(args) == 0 {
+ return cty.NilType, errors.New("at least one argument is required")
+ }
+
+ argTypes := make([]cty.Type, len(args))
+
+ for i, arg := range args {
+ // if any argument is unknown, we can't be certain know which type we will return
+ if !arg.IsKnown() {
+ return cty.DynamicPseudoType, nil
+ }
+ ty := arg.Type()
+
+ if !ty.IsListType() && !ty.IsTupleType() {
+ return cty.NilType, errors.New("coalescelist arguments must be lists or tuples")
+ }
+
+ argTypes[i] = arg.Type()
+ }
+
+ last := argTypes[0]
+ // If there are mixed types, we have to return a dynamic type.
+ for _, next := range argTypes[1:] {
+ if !next.Equals(last) {
+ return cty.DynamicPseudoType, nil
+ }
+ }
+
+ return last, nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ for _, arg := range args {
+ if !arg.IsKnown() {
+ // If we run into an unknown list at some point, we can't
+ // predict the final result yet. (If there's a known, non-empty
+ // arg before this then we won't get here.)
+ return cty.UnknownVal(retType), nil
+ }
+
+ if arg.IsNull() {
+ continue
+ }
+
+ if arg.LengthInt() > 0 {
+ return arg, nil
+ }
+ }
+
+ return cty.NilVal, errors.New("no non-null arguments")
+ },
+})
+
+// CompactFunc is a function that takes a list of strings and returns a new list
+// with any empty string elements removed.
+var CompactFunc = function.New(&function.Spec{
+ Description: `Removes all empty string elements from the given list of strings.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.List(cty.String),
+ },
+ },
+ Type: function.StaticReturnType(cty.List(cty.String)),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ listVal := args[0]
+ if !listVal.IsWhollyKnown() {
+ // If some of the element values aren't known yet then we
+ // can't yet return a compacted list
+ return cty.UnknownVal(retType), nil
+ }
+
+ var outputList []cty.Value
+
+ for it := listVal.ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ if v.IsNull() || v.AsString() == "" {
+ continue
+ }
+ outputList = append(outputList, v)
+ }
+
+ if len(outputList) == 0 {
+ return cty.ListValEmpty(cty.String), nil
+ }
+
+ return cty.ListVal(outputList), nil
+ },
+})
+
+// ContainsFunc is a function that determines whether a given list or
+// set contains a given single value as one of its elements.
+var ContainsFunc = function.New(&function.Spec{
+ Description: `Returns true if the given value is a value in the given list, tuple, or set, or false otherwise.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.DynamicPseudoType,
+ },
+ {
+ Name: "value",
+ Type: cty.DynamicPseudoType,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ arg := args[0]
+ ty := arg.Type()
+
+ if !ty.IsListType() && !ty.IsTupleType() && !ty.IsSetType() {
+ return cty.NilVal, errors.New("argument must be list, tuple, or set")
+ }
+
+ if args[0].IsNull() {
+ return cty.NilVal, errors.New("cannot search a nil list or set")
+ }
+
+ if args[0].LengthInt() == 0 {
+ return cty.False, nil
+ }
+
+ if !args[0].IsKnown() || !args[1].IsKnown() {
+ return cty.UnknownVal(cty.Bool), nil
+ }
+
+ containsUnknown := false
+ for it := args[0].ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ eq := args[1].Equals(v)
+ if !eq.IsKnown() {
+ // We may have an unknown value which could match later, but we
+ // first need to continue checking all values for an exact
+ // match.
+ containsUnknown = true
+ continue
+ }
+ if eq.True() {
+ return cty.True, nil
+ }
+ }
+
+ if containsUnknown {
+ return cty.UnknownVal(cty.Bool), nil
+ }
+
+ return cty.False, nil
+ },
+})
+
+// DistinctFunc is a function that takes a list and returns a new list
+// with any duplicate elements removed.
+var DistinctFunc = function.New(&function.Spec{
+ Description: `Removes any duplicate values from the given list, preserving the order of remaining elements.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.List(cty.DynamicPseudoType),
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ return args[0].Type(), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ listVal := args[0]
+
+ if !listVal.IsWhollyKnown() {
+ return cty.UnknownVal(retType), nil
+ }
+ var list []cty.Value
+
+ for it := listVal.ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ list, err = appendIfMissing(list, v)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ if len(list) == 0 {
+ return cty.ListValEmpty(retType.ElementType()), nil
+ }
+ return cty.ListVal(list), nil
+ },
+})
+
+// ChunklistFunc is a function that splits a single list into fixed-size chunks,
+// returning a list of lists.
+var ChunklistFunc = function.New(&function.Spec{
+ Description: `Splits a single list into multiple lists where each has at most the given number of elements.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Description: `The list to split into chunks.`,
+ Type: cty.List(cty.DynamicPseudoType),
+ AllowMarked: true,
+ },
+ {
+ Name: "size",
+ Description: `The maximum length of each chunk. All but the last element of the result is guaranteed to be of exactly this size.`,
+ Type: cty.Number,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ return cty.List(args[0].Type()), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ listVal := args[0]
+ sizeVal := args[1]
+ listVal, listMarks := listVal.Unmark()
+ sizeVal, sizeMarks := sizeVal.Unmark()
+ // All return paths below must include .WithMarks(retMarks) to propagate
+ // the top-level marks into the return value. Deep marks inside the
+ // list will just propagate naturally because we treat those values
+ // as opaque here.
+ retMarks := cty.NewValueMarks(listMarks, sizeMarks)
+
+ var size int
+ err = gocty.FromCtyValue(sizeVal, &size)
+ if err != nil {
+ return cty.NilVal, fmt.Errorf("invalid size: %s", err)
+ }
+
+ if size < 0 {
+ return cty.NilVal, errors.New("the size argument must be positive")
+ }
+
+ if listVal.LengthInt() == 0 {
+ return cty.ListValEmpty(listVal.Type()).WithMarks(retMarks), nil
+ }
+
+ output := make([]cty.Value, 0)
+
+ // if size is 0, returns a list made of the initial list
+ if size == 0 {
+ output = append(output, listVal)
+ return cty.ListVal(output).WithMarks(retMarks), nil
+ }
+
+ chunk := make([]cty.Value, 0)
+
+ l := listVal.LengthInt()
+ i := 0
+
+ for it := listVal.ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ chunk = append(chunk, v)
+
+ // Chunk when index isn't 0, or when reaching the values's length
+ if (i+1)%size == 0 || (i+1) == l {
+ output = append(output, cty.ListVal(chunk))
+ chunk = make([]cty.Value, 0)
+ }
+ i++
+ }
+
+ return cty.ListVal(output).WithMarks(retMarks), nil
+ },
+})
+
+// FlattenFunc is a function that takes a list and replaces any elements
+// that are lists with a flattened sequence of the list contents.
+var FlattenFunc = function.New(&function.Spec{
+ Description: `Transforms a list, set, or tuple value into a tuple by replacing any given elements that are themselves sequences with a flattened tuple of all of the nested elements concatenated together.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ if !args[0].IsWhollyKnown() {
+ return cty.DynamicPseudoType, nil
+ }
+
+ argTy := args[0].Type()
+ if !argTy.IsListType() && !argTy.IsSetType() && !argTy.IsTupleType() {
+ return cty.NilType, errors.New("can only flatten lists, sets and tuples")
+ }
+
+ // marks are attached to values, so ignore while determining type
+ retVal, _, known := flattener(args[0])
+ if !known {
+ return cty.DynamicPseudoType, nil
+ }
+
+ tys := make([]cty.Type, len(retVal))
+ for i, ty := range retVal {
+ tys[i] = ty.Type()
+ }
+ return cty.Tuple(tys), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ inputList := args[0]
+
+ if unmarked, marks := inputList.Unmark(); unmarked.LengthInt() == 0 {
+ return cty.EmptyTupleVal.WithMarks(marks), nil
+ }
+
+ out, markses, known := flattener(inputList)
+ if !known {
+ return cty.UnknownVal(retType).WithMarks(markses...), nil
+ }
+
+ return cty.TupleVal(out).WithMarks(markses...), nil
+ },
+})
+
+// Flatten until it's not a cty.List, and return whether the value is known.
+// We can flatten lists with unknown values, as long as they are not
+// lists themselves.
+func flattener(flattenList cty.Value) ([]cty.Value, []cty.ValueMarks, bool) {
+ var markses []cty.ValueMarks
+ flattenList, flattenListMarks := flattenList.Unmark()
+ if len(flattenListMarks) > 0 {
+ markses = append(markses, flattenListMarks)
+ }
+
+ if !flattenList.Length().IsKnown() {
+ // If we don't know the length of what we're flattening then we can't
+ // predict the length of our result yet either.
+ return nil, markses, false
+ }
+
+ out := make([]cty.Value, 0)
+ isKnown := true
+ for it := flattenList.ElementIterator(); it.Next(); {
+ _, val := it.Element()
+
+ // Any dynamic types could result in more collections that need to be
+ // flattened, so the type cannot be known.
+ if val == cty.DynamicVal {
+ isKnown = false
+ }
+
+ if !val.IsNull() && (val.Type().IsListType() || val.Type().IsSetType() || val.Type().IsTupleType()) {
+ if !val.IsKnown() {
+ isKnown = false
+ _, unknownMarks := val.Unmark()
+ markses = append(markses, unknownMarks)
+ continue
+ }
+
+ res, resMarks, known := flattener(val)
+ markses = append(markses, resMarks...)
+ if known {
+ out = append(out, res...)
+ } else {
+ isKnown = false
+ }
+ } else {
+ out = append(out, val)
+ }
+ }
+ return out, markses, isKnown
+}
+
+// KeysFunc is a function that takes a map and returns a sorted list of the map keys.
+var KeysFunc = function.New(&function.Spec{
+ Description: `Returns a list of the keys of the given map in lexicographical order.`,
+ Params: []function.Parameter{
+ {
+ Name: "inputMap",
+ Description: `The map to extract keys from. May instead be an object-typed value, in which case the result is a tuple of the object attributes.`,
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ ty := args[0].Type()
+ switch {
+ case ty.IsMapType():
+ return cty.List(cty.String), nil
+ case ty.IsObjectType():
+ atys := ty.AttributeTypes()
+ if len(atys) == 0 {
+ return cty.EmptyTuple, nil
+ }
+ // All of our result elements will be strings, and atys just
+ // decides how many there are.
+ etys := make([]cty.Type, len(atys))
+ for i := range etys {
+ etys[i] = cty.String
+ }
+ return cty.Tuple(etys), nil
+ default:
+ return cty.DynamicPseudoType, function.NewArgErrorf(0, "must have map or object type")
+ }
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ // We must unmark the value before we can use ElementIterator on it, and
+ // then re-apply the same marks (possibly none) when we return. Since we
+ // don't mark map keys, we can throw away any nested marks, which would
+ // only apply to values.
+ m, marks := args[0].Unmark()
+ var keys []cty.Value
+
+ switch {
+ case m.Type().IsObjectType():
+ // In this case we allow unknown values so we must work only with
+ // the attribute _types_, not with the value itself.
+ var names []string
+ for name := range m.Type().AttributeTypes() {
+ names = append(names, name)
+ }
+ sort.Strings(names) // same ordering guaranteed by cty's ElementIterator
+ if len(names) == 0 {
+ return cty.EmptyTupleVal.WithMarks(marks), nil
+ }
+ keys = make([]cty.Value, len(names))
+ for i, name := range names {
+ keys[i] = cty.StringVal(name)
+ }
+ return cty.TupleVal(keys).WithMarks(marks), nil
+ default:
+ if !m.IsKnown() {
+ return cty.UnknownVal(retType).WithMarks(marks), nil
+ }
+
+ // cty guarantees that ElementIterator will iterate in lexicographical
+ // order by key.
+ for it := m.ElementIterator(); it.Next(); {
+ k, _ := it.Element()
+ keys = append(keys, k)
+ }
+ if len(keys) == 0 {
+ return cty.ListValEmpty(cty.String).WithMarks(marks), nil
+ }
+ return cty.ListVal(keys).WithMarks(marks), nil
+ }
+ },
+})
+
+// LookupFunc is a function that performs dynamic lookups of map types.
+var LookupFunc = function.New(&function.Spec{
+ Description: `Returns the value of the element with the given key from the given map, or returns the default value if there is no such element.`,
+ Params: []function.Parameter{
+ {
+ Name: "inputMap",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ {
+ Name: "key",
+ Type: cty.String,
+ AllowMarked: true,
+ },
+ {
+ Name: "default",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ ty := args[0].Type()
+
+ switch {
+ case ty.IsObjectType():
+ if !args[1].IsKnown() {
+ return cty.DynamicPseudoType, nil
+ }
+
+ keyVal, _ := args[1].Unmark()
+ key := keyVal.AsString()
+ if ty.HasAttribute(key) {
+ return args[0].GetAttr(key).Type(), nil
+ } else if len(args) == 3 {
+ // if the key isn't found but a default is provided,
+ // return the default type
+ return args[2].Type(), nil
+ }
+ return cty.DynamicPseudoType, function.NewArgErrorf(0, "the given object has no attribute %q", key)
+ case ty.IsMapType():
+ if len(args) == 3 {
+ _, err = convert.Convert(args[2], ty.ElementType())
+ if err != nil {
+ return cty.NilType, function.NewArgErrorf(2, "the default value must have the same type as the map elements")
+ }
+ }
+ return ty.ElementType(), nil
+ default:
+ return cty.NilType, function.NewArgErrorf(0, "lookup() requires a map as the first argument")
+ }
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ // leave default value marked
+ defaultVal := args[2]
+
+ var markses []cty.ValueMarks
+
+ // unmark collection, retain marks to reapply later
+ mapVar, mapMarks := args[0].Unmark()
+ markses = append(markses, mapMarks)
+
+ // include marks on the key in the result
+ keyVal, keyMarks := args[1].Unmark()
+ if len(keyMarks) > 0 {
+ markses = append(markses, keyMarks)
+ }
+ lookupKey := keyVal.AsString()
+
+ if !mapVar.IsWhollyKnown() {
+ return cty.UnknownVal(retType).WithMarks(markses...), nil
+ }
+
+ if mapVar.Type().IsObjectType() {
+ if mapVar.Type().HasAttribute(lookupKey) {
+ return mapVar.GetAttr(lookupKey).WithMarks(markses...), nil
+ }
+ } else if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True {
+ return mapVar.Index(cty.StringVal(lookupKey)).WithMarks(markses...), nil
+ }
+
+ defaultVal, err = convert.Convert(defaultVal, retType)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ return defaultVal.WithMarks(markses...), nil
+ },
+})
+
+// MergeFunc constructs a function that takes an arbitrary number of maps or
+// objects, and returns a single value that contains a merged set of keys and
+// values from all of the inputs.
+//
+// If more than one given map or object defines the same key then the one that
+// is later in the argument sequence takes precedence.
+var MergeFunc = function.New(&function.Spec{
+ Description: `Merges all of the elements from the given maps into a single map, or the attributes from given objects into a single object.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "maps",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ AllowNull: true,
+ AllowMarked: true,
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ // empty args is accepted, so assume an empty object since we have no
+ // key-value types.
+ if len(args) == 0 {
+ return cty.EmptyObject, nil
+ }
+
+ // collect the possible object attrs
+ attrs := map[string]cty.Type{}
+
+ first := cty.NilType
+ matching := true
+ attrsKnown := true
+ for i, arg := range args {
+ ty := arg.Type()
+ // any dynamic args mean we can't compute a type
+ if ty.Equals(cty.DynamicPseudoType) {
+ return cty.DynamicPseudoType, nil
+ }
+
+ // check for invalid arguments
+ if !ty.IsMapType() && !ty.IsObjectType() {
+ return cty.NilType, fmt.Errorf("arguments must be maps or objects, got %#v", ty.FriendlyName())
+ }
+ // marks are attached to values, so ignore while determining type
+ arg, _ = arg.Unmark()
+
+ switch {
+ case ty.IsObjectType() && !arg.IsNull():
+ for attr, aty := range ty.AttributeTypes() {
+ attrs[attr] = aty
+ }
+ case ty.IsMapType():
+ switch {
+ case arg.IsNull():
+ // pass, nothing to add
+ case arg.IsKnown():
+ ety := arg.Type().ElementType()
+ for it := arg.ElementIterator(); it.Next(); {
+ attr, _ := it.Element()
+ attrs[attr.AsString()] = ety
+ }
+ default:
+ // any unknown maps means we don't know all possible attrs
+ // for the return type
+ attrsKnown = false
+ }
+ }
+
+ // record the first argument type for comparison
+ if i == 0 {
+ first = arg.Type()
+ continue
+ }
+
+ if !ty.Equals(first) && matching {
+ matching = false
+ }
+ }
+
+ // the types all match, so use the first argument type
+ if matching {
+ return first, nil
+ }
+
+ // We had a mix of unknown maps and objects, so we can't predict the
+ // attributes
+ if !attrsKnown {
+ return cty.DynamicPseudoType, nil
+ }
+
+ return cty.Object(attrs), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ outputMap := make(map[string]cty.Value)
+ var markses []cty.ValueMarks // remember any marked maps/objects we find
+
+ for _, arg := range args {
+ if arg.IsNull() {
+ continue
+ }
+ arg, argMarks := arg.Unmark()
+ if len(argMarks) > 0 {
+ markses = append(markses, argMarks)
+ }
+ for it := arg.ElementIterator(); it.Next(); {
+ k, v := it.Element()
+ outputMap[k.AsString()] = v
+ }
+ }
+
+ switch {
+ case retType.IsMapType():
+ if len(outputMap) == 0 {
+ return cty.MapValEmpty(retType.ElementType()).WithMarks(markses...), nil
+ }
+ return cty.MapVal(outputMap).WithMarks(markses...), nil
+ case retType.IsObjectType(), retType.Equals(cty.DynamicPseudoType):
+ return cty.ObjectVal(outputMap).WithMarks(markses...), nil
+ default:
+ panic(fmt.Sprintf("unexpected return type: %#v", retType))
+ }
+ },
+})
+
+// ReverseListFunc takes a sequence and produces a new sequence of the same length
+// with all of the same elements as the given sequence but in reverse order.
+var ReverseListFunc = function.New(&function.Spec{
+ Description: `Returns the given list with its elements in reverse order.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ argTy := args[0].Type()
+ switch {
+ case argTy.IsTupleType():
+ argTys := argTy.TupleElementTypes()
+ retTys := make([]cty.Type, len(argTys))
+ for i, ty := range argTys {
+ retTys[len(retTys)-i-1] = ty
+ }
+ return cty.Tuple(retTys), nil
+ case argTy.IsListType(), argTy.IsSetType(): // We accept sets here to mimic the usual behavior of auto-converting to list
+ return cty.List(argTy.ElementType()), nil
+ default:
+ return cty.NilType, function.NewArgErrorf(0, "can only reverse list or tuple values, not %s", argTy.FriendlyName())
+ }
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ in, marks := args[0].Unmark()
+ inVals := in.AsValueSlice()
+ outVals := make([]cty.Value, len(inVals))
+
+ for i, v := range inVals {
+ outVals[len(outVals)-i-1] = v
+ }
+ switch {
+ case retType.IsTupleType():
+ return cty.TupleVal(outVals).WithMarks(marks), nil
+ default:
+ if len(outVals) == 0 {
+ return cty.ListValEmpty(retType.ElementType()).WithMarks(marks), nil
+ }
+ return cty.ListVal(outVals).WithMarks(marks), nil
+ }
+ },
+})
+
+// SetProductFunc calculates the Cartesian product of two or more sets or
+// sequences. If the arguments are all lists then the result is a list of tuples,
+// preserving the ordering of all of the input lists. Otherwise the result is a
+// set of tuples.
+var SetProductFunc = function.New(&function.Spec{
+ Description: `Calculates the cartesian product of two or more sets.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "sets",
+ Description: "The sets to consider. Also accepts lists and tuples, and if all arguments are of list or tuple type then the result will preserve the input ordering",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ AllowUnknown: true,
+ },
+ Type: func(args []cty.Value) (retType cty.Type, err error) {
+ if len(args) < 2 {
+ return cty.NilType, errors.New("at least two arguments are required")
+ }
+
+ listCount := 0
+ elemTys := make([]cty.Type, len(args))
+ for i, arg := range args {
+ aty := arg.Type()
+ switch {
+ case aty.IsSetType():
+ elemTys[i] = aty.ElementType()
+ case aty.IsListType():
+ elemTys[i] = aty.ElementType()
+ listCount++
+ case aty.IsTupleType():
+ // We can accept a tuple type only if there's some common type
+ // that all of its elements can be converted to.
+ allEtys := aty.TupleElementTypes()
+ if len(allEtys) == 0 {
+ elemTys[i] = cty.DynamicPseudoType
+ listCount++
+ break
+ }
+ ety, _ := convert.UnifyUnsafe(allEtys)
+ if ety == cty.NilType {
+ return cty.NilType, function.NewArgErrorf(i, "all elements must be of the same type")
+ }
+ elemTys[i] = ety
+ listCount++
+ default:
+ return cty.NilType, function.NewArgErrorf(i, "a set or a list is required")
+ }
+ }
+
+ if listCount == len(args) {
+ return cty.List(cty.Tuple(elemTys)), nil
+ }
+ return cty.Set(cty.Tuple(elemTys)), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ ety := retType.ElementType()
+ var retMarks cty.ValueMarks
+
+ total := 1
+ var hasUnknownLength bool
+ for _, arg := range args {
+ arg, marks := arg.Unmark()
+ retMarks = cty.NewValueMarks(retMarks, marks)
+
+ // Continue processing after we find an argument with unknown
+ // length to ensure that we cover all the marks
+ if !(arg.IsKnown() && arg.Length().IsKnown()) {
+ hasUnknownLength = true
+ continue
+ }
+
+ // Because of our type checking function, we are guaranteed that
+ // all of the arguments are known, non-null values of types that
+ // support LengthInt.
+ total *= arg.LengthInt()
+ }
+
+ if hasUnknownLength {
+ defer func() {
+ // We're definitely going to return from somewhere in this
+ // branch and however we do it we must reapply the marks
+ // on the way out.
+ ret = ret.WithMarks(retMarks)
+ }()
+ ret := cty.UnknownVal(retType)
+
+ // Even if we don't know the exact length we may be able to
+ // constrain the upper and lower bounds of the resulting length.
+ maxLength := 1
+ for _, arg := range args {
+ arg, _ := arg.Unmark() // safe to discard marks because "retMarks" already contains them all
+ argRng := arg.Range()
+ ty := argRng.TypeConstraint()
+ var argMaxLen int
+ if ty.IsCollectionType() {
+ argMaxLen = argRng.LengthUpperBound()
+ } else if ty.IsTupleType() {
+ argMaxLen = ty.Length()
+ } else {
+ // Should not get here but if we do then we'll just
+ // bail out with an unrefined unknown value.
+ return ret, nil
+ }
+ // The upper bound of a totally-unrefined collection is
+ // math.MaxInt, which will quickly get us to integer overflow
+ // here, and so out of pragmatism we'll just impose a reasonable
+ // upper limit on what is a useful bound to track and return
+ // unrefined for unusually-large input.
+ if argMaxLen > 1024 { // arbitrarily-decided threshold
+ return ret, nil
+ }
+ maxLength *= argMaxLen
+ if maxLength > 2048 { // arbitrarily-decided threshold
+ return ret, nil
+ }
+ if maxLength < 0 { // Seems like we already overflowed, then.
+ return ret, nil
+ }
+ }
+
+ if maxLength == 0 {
+ // This refinement will typically allow the unknown value to
+ // collapse into a known empty collection.
+ ret = ret.Refine().CollectionLength(0).NewValue()
+ } else {
+ // If we know there's a nonzero maximum number of elements then
+ // set element coalescing cannot reduce to fewer than one
+ // element.
+ ret = ret.Refine().
+ CollectionLengthLowerBound(1).
+ CollectionLengthUpperBound(maxLength).
+ NewValue()
+ }
+ return ret, nil
+ }
+
+ if total == 0 {
+ // If any of the arguments was an empty collection then our result
+ // is also an empty collection, which we'll short-circuit here.
+ if retType.IsListType() {
+ return cty.ListValEmpty(ety).WithMarks(retMarks), nil
+ }
+ return cty.SetValEmpty(ety).WithMarks(retMarks), nil
+ }
+
+ subEtys := ety.TupleElementTypes()
+ product := make([][]cty.Value, total)
+
+ b := make([]cty.Value, total*len(args))
+ n := make([]int, len(args))
+ s := 0
+ argVals := make([][]cty.Value, len(args))
+ for i, arg := range args {
+ // We've already stored the marks in retMarks
+ arg, _ := arg.Unmark()
+ argVals[i] = arg.AsValueSlice()
+ }
+
+ for i := range product {
+ e := s + len(args)
+ pi := b[s:e]
+ product[i] = pi
+ s = e
+
+ for j, n := range n {
+ val := argVals[j][n]
+ ty := subEtys[j]
+ if !val.Type().Equals(ty) {
+ var err error
+ val, err = convert.Convert(val, ty)
+ if err != nil {
+ // Should never happen since we checked this in our
+ // type-checking function.
+ return cty.NilVal, fmt.Errorf("failed to convert argVals[%d][%d] to %s; this is a bug in cty", j, n, ty.FriendlyName())
+ }
+ }
+ pi[j] = val
+ }
+
+ for j := len(n) - 1; j >= 0; j-- {
+ n[j]++
+ if n[j] < len(argVals[j]) {
+ break
+ }
+ n[j] = 0
+ }
+ }
+
+ productVals := make([]cty.Value, total)
+ for i, vals := range product {
+ productVals[i] = cty.TupleVal(vals)
+ }
+
+ if retType.IsListType() {
+ return cty.ListVal(productVals).WithMarks(retMarks), nil
+ }
+ return cty.SetVal(productVals).WithMarks(retMarks), nil
+ },
+})
+
+// SliceFunc is a function that extracts some consecutive elements
+// from within a list.
+var SliceFunc = function.New(&function.Spec{
+ Description: `Extracts a subslice of the given list or tuple value.`,
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ {
+ Name: "start_index",
+ Type: cty.Number,
+ },
+ {
+ Name: "end_index",
+ Type: cty.Number,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ arg := args[0]
+ argTy := arg.Type()
+
+ if argTy.IsSetType() {
+ return cty.NilType, function.NewArgErrorf(0, "cannot slice a set, because its elements do not have indices; explicitly convert to a list if the ordering of the result is not important")
+ }
+ if !argTy.IsListType() && !argTy.IsTupleType() {
+ return cty.NilType, function.NewArgErrorf(0, "must be a list or tuple value")
+ }
+
+ startIndex, endIndex, idxsKnown, err := sliceIndexes(args)
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ if argTy.IsListType() {
+ return argTy, nil
+ }
+
+ if !idxsKnown {
+ // If we don't know our start/end indices then we can't predict
+ // the result type if we're planning to return a tuple.
+ return cty.DynamicPseudoType, nil
+ }
+ return cty.Tuple(argTy.TupleElementTypes()[startIndex:endIndex]), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ inputList, marks := args[0].Unmark()
+
+ if retType == cty.DynamicPseudoType {
+ return cty.DynamicVal.WithMarks(marks), nil
+ }
+
+ // we ignore idxsKnown return value here because the indices are always
+ // known here, or else the call would've short-circuited.
+ startIndex, endIndex, _, err := sliceIndexes(args)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ if endIndex-startIndex == 0 {
+ if retType.IsTupleType() {
+ return cty.EmptyTupleVal.WithMarks(marks), nil
+ }
+ return cty.ListValEmpty(retType.ElementType()).WithMarks(marks), nil
+ }
+
+ outputList := inputList.AsValueSlice()[startIndex:endIndex]
+
+ if retType.IsTupleType() {
+ return cty.TupleVal(outputList).WithMarks(marks), nil
+ }
+
+ return cty.ListVal(outputList).WithMarks(marks), nil
+ },
+})
+
+func sliceIndexes(args []cty.Value) (int, int, bool, error) {
+ var startIndex, endIndex, length int
+ var startKnown, endKnown, lengthKnown bool
+
+ // remove marks from args[0]
+ list, _ := args[0].Unmark()
+
+ // If it's a tuple then we always know the length by the type, but collections might be unknown or have unknown length
+ if list.Type().IsTupleType() || list.Length().IsKnown() {
+ length = list.LengthInt()
+ lengthKnown = true
+ }
+
+ if args[1].IsKnown() {
+ if err := gocty.FromCtyValue(args[1], &startIndex); err != nil {
+ return 0, 0, false, function.NewArgErrorf(1, "invalid start index: %s", err)
+ }
+ if startIndex < 0 {
+ return 0, 0, false, function.NewArgErrorf(1, "start index must not be less than zero")
+ }
+ if lengthKnown && startIndex > length {
+ return 0, 0, false, function.NewArgErrorf(1, "start index must not be greater than the length of the list")
+ }
+ startKnown = true
+ }
+ if args[2].IsKnown() {
+ if err := gocty.FromCtyValue(args[2], &endIndex); err != nil {
+ return 0, 0, false, function.NewArgErrorf(2, "invalid end index: %s", err)
+ }
+ if endIndex < 0 {
+ return 0, 0, false, function.NewArgErrorf(2, "end index must not be less than zero")
+ }
+ if lengthKnown && endIndex > length {
+ return 0, 0, false, function.NewArgErrorf(2, "end index must not be greater than the length of the list")
+ }
+ endKnown = true
+ }
+ if startKnown && endKnown {
+ if startIndex > endIndex {
+ return 0, 0, false, function.NewArgErrorf(1, "start index must not be greater than end index")
+ }
+ }
+ return startIndex, endIndex, startKnown && endKnown, nil
+}
+
+// ValuesFunc is a function that returns a list of the map values,
+// in the order of the sorted keys.
+var ValuesFunc = function.New(&function.Spec{
+ Description: `Returns the values of elements of a given map, or the values of attributes of a given object, in lexicographic order by key or attribute name.`,
+ Params: []function.Parameter{
+ {
+ Name: "mapping",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ ty := args[0].Type()
+ if ty.IsMapType() {
+ return cty.List(ty.ElementType()), nil
+ } else if ty.IsObjectType() {
+ // The result is a tuple type with all of the same types as our
+ // object type's attributes, sorted in lexicographical order by the
+ // keys. (This matches the sort order guaranteed by ElementIterator
+ // on a cty object value.)
+ atys := ty.AttributeTypes()
+ if len(atys) == 0 {
+ return cty.EmptyTuple, nil
+ }
+ attrNames := make([]string, 0, len(atys))
+ for name := range atys {
+ attrNames = append(attrNames, name)
+ }
+ sort.Strings(attrNames)
+
+ tys := make([]cty.Type, len(attrNames))
+ for i, name := range attrNames {
+ tys[i] = atys[name]
+ }
+ return cty.Tuple(tys), nil
+ }
+ return cty.NilType, errors.New("values() requires a map as the first argument")
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ mapVar := args[0]
+
+ // We must unmark the value before we can use ElementIterator on it,
+ // and then re-apply the same marks (possibly none) when we return.
+ // (We leave the inner values just as they are, because we won't be
+ // doing anything with them aside from copying them verbatim into the
+ // result, marks and all.)
+ mapVar, marks := mapVar.Unmark()
+
+ // We can just iterate the map/object value here because cty guarantees
+ // that these types always iterate in key lexicographical order.
+ var values []cty.Value
+ for it := mapVar.ElementIterator(); it.Next(); {
+ _, val := it.Element()
+ values = append(values, val)
+ }
+
+ // All of the return paths must include .WithMarks(marks) so that we
+ // will preserve the markings of the overall map/object we were given.
+ if retType.IsTupleType() {
+ return cty.TupleVal(values).WithMarks(marks), nil
+ }
+ if len(values) == 0 {
+ return cty.ListValEmpty(retType.ElementType()).WithMarks(marks), nil
+ }
+ return cty.ListVal(values).WithMarks(marks), nil
+ },
+})
+
+// ZipmapFunc is a function that constructs a map from a list of keys
+// and a corresponding list of values.
+var ZipmapFunc = function.New(&function.Spec{
+ Description: `Constructs a map from a list of keys and a corresponding list of values, which must both be of the same length.`,
+ Params: []function.Parameter{
+ {
+ Name: "keys",
+ Type: cty.List(cty.String),
+ AllowMarked: true,
+ },
+ {
+ Name: "values",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ keys := args[0]
+ values := args[1]
+ valuesTy := values.Type()
+
+ switch {
+ case valuesTy.IsListType():
+ return cty.Map(values.Type().ElementType()), nil
+ case valuesTy.IsTupleType():
+ if !keys.IsWhollyKnown() {
+ // Since zipmap with a tuple produces an object, we need to know
+ // all of the key names before we can predict our result type.
+ return cty.DynamicPseudoType, nil
+ }
+
+ // NOTE: Marking of the keys list can't be represented in the
+ // result type, so the tuple type here will disclose the keys.
+ // This is unfortunate but is a common compromise with dynamic
+ // return types; the result from Impl will still reflect the marks
+ // from the keys list, so a mark-using caller should look out for
+ // that if it's important for their use-case.
+ keys, _ := keys.Unmark()
+ keysRaw := keys.AsValueSlice()
+ valueTypesRaw := valuesTy.TupleElementTypes()
+ if len(keysRaw) != len(valueTypesRaw) {
+ return cty.NilType, fmt.Errorf("number of keys (%d) does not match number of values (%d)", len(keysRaw), len(valueTypesRaw))
+ }
+ atys := make(map[string]cty.Type, len(valueTypesRaw))
+ for i, keyVal := range keysRaw {
+ keyVal, _ = keyVal.Unmark()
+ if keyVal.IsNull() {
+ return cty.NilType, fmt.Errorf("keys list has null value at index %d", i)
+ }
+ key := keyVal.AsString()
+ atys[key] = valueTypesRaw[i]
+ }
+ return cty.Object(atys), nil
+
+ default:
+ return cty.NilType, errors.New("values argument must be a list or tuple value")
+ }
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ keys := args[0]
+ values := args[1]
+ keys, keysMarks := keys.Unmark()
+ values, valuesMarks := values.Unmark()
+
+ // All of our return paths must pass through the merged marks from
+ // both the keys and the values, if any, using .WithMarks(retMarks)
+ retMarks := cty.NewValueMarks(keysMarks, valuesMarks)
+
+ if !keys.IsWhollyKnown() {
+ // Unknown map keys and object attributes are not supported, so
+ // our entire result must be unknown in this case.
+ return cty.UnknownVal(retType).WithMarks(retMarks), nil
+ }
+
+ // both keys and values are guaranteed to be shallowly-known here,
+ // because our declared params above don't allow unknown or null values.
+ if keys.LengthInt() != values.LengthInt() {
+ return cty.NilVal, fmt.Errorf("number of keys (%d) does not match number of values (%d)", keys.LengthInt(), values.LengthInt())
+ }
+
+ output := make(map[string]cty.Value)
+
+ i := 0
+ for it := keys.ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ v, vMarks := v.Unmark()
+ val := values.Index(cty.NumberIntVal(int64(i)))
+ output[v.AsString()] = val
+
+ // We also need to accumulate the individual key marks on the
+ // returned map, because keys can't carry marks on their own.
+ retMarks = cty.NewValueMarks(retMarks, vMarks)
+
+ i++
+ }
+
+ switch {
+ case retType.IsMapType():
+ if len(output) == 0 {
+ return cty.MapValEmpty(retType.ElementType()).WithMarks(retMarks), nil
+ }
+ return cty.MapVal(output).WithMarks(retMarks), nil
+ case retType.IsObjectType():
+ return cty.ObjectVal(output).WithMarks(retMarks), nil
+ default:
+ // Should never happen because the type-check function should've
+ // caught any other case.
+ return cty.NilVal, fmt.Errorf("internally selected incorrect result type %s (this is a bug)", retType.FriendlyName())
+ }
+ },
+})
+
+// helper function to add an element to a list, if it does not already exist
+func appendIfMissing(slice []cty.Value, element cty.Value) ([]cty.Value, error) {
+ for _, ele := range slice {
+ eq, err := Equal(ele, element)
+ if err != nil {
+ return slice, err
+ }
+ if eq.True() {
+ return slice, nil
+ }
+ }
+ return append(slice, element), nil
+}
+
+// HasIndex determines whether the given collection can be indexed with the
+// given key.
+func HasIndex(collection cty.Value, key cty.Value) (cty.Value, error) {
+ return HasIndexFunc.Call([]cty.Value{collection, key})
+}
+
+// Index returns an element from the given collection using the given key,
+// or returns an error if there is no element for the given key.
+func Index(collection cty.Value, key cty.Value) (cty.Value, error) {
+ return IndexFunc.Call([]cty.Value{collection, key})
+}
+
+// Length returns the number of elements in the given collection.
+func Length(collection cty.Value) (cty.Value, error) {
+ return LengthFunc.Call([]cty.Value{collection})
+}
+
+// Element returns a single element from a given list at the given index. If
+// index is greater than the length of the list then it is wrapped modulo
+// the list length.
+func Element(list, index cty.Value) (cty.Value, error) {
+ return ElementFunc.Call([]cty.Value{list, index})
+}
+
+// CoalesceList takes any number of list arguments and returns the first one that isn't empty.
+func CoalesceList(args ...cty.Value) (cty.Value, error) {
+ return CoalesceListFunc.Call(args)
+}
+
+// Compact takes a list of strings and returns a new list
+// with any empty string elements removed.
+func Compact(list cty.Value) (cty.Value, error) {
+ return CompactFunc.Call([]cty.Value{list})
+}
+
+// Contains determines whether a given list contains a given single value
+// as one of its elements.
+func Contains(list, value cty.Value) (cty.Value, error) {
+ return ContainsFunc.Call([]cty.Value{list, value})
+}
+
+// Distinct takes a list and returns a new list with any duplicate elements removed.
+func Distinct(list cty.Value) (cty.Value, error) {
+ return DistinctFunc.Call([]cty.Value{list})
+}
+
+// Chunklist splits a single list into fixed-size chunks, returning a list of lists.
+func Chunklist(list, size cty.Value) (cty.Value, error) {
+ return ChunklistFunc.Call([]cty.Value{list, size})
+}
+
+// Flatten takes a list and replaces any elements that are lists with a flattened
+// sequence of the list contents.
+func Flatten(list cty.Value) (cty.Value, error) {
+ return FlattenFunc.Call([]cty.Value{list})
+}
+
+// Keys takes a map and returns a sorted list of the map keys.
+func Keys(inputMap cty.Value) (cty.Value, error) {
+ return KeysFunc.Call([]cty.Value{inputMap})
+}
+
+// Lookup performs a dynamic lookup into a map.
+// There are three required arguments, inputMap and key, plus a defaultValue,
+// which is a value to return if the given key is not found in the inputMap.
+func Lookup(inputMap, key, defaultValue cty.Value) (cty.Value, error) {
+ return LookupFunc.Call([]cty.Value{inputMap, key, defaultValue})
+}
+
+// Merge takes an arbitrary number of maps and returns a single map that contains
+// a merged set of elements from all of the maps.
+//
+// If more than one given map defines the same key then the one that is later in
+// the argument sequence takes precedence.
+func Merge(maps ...cty.Value) (cty.Value, error) {
+ return MergeFunc.Call(maps)
+}
+
+// ReverseList takes a sequence and produces a new sequence of the same length
+// with all of the same elements as the given sequence but in reverse order.
+func ReverseList(list cty.Value) (cty.Value, error) {
+ return ReverseListFunc.Call([]cty.Value{list})
+}
+
+// SetProduct computes the Cartesian product of sets or sequences.
+func SetProduct(sets ...cty.Value) (cty.Value, error) {
+ return SetProductFunc.Call(sets)
+}
+
+// Slice extracts some consecutive elements from within a list.
+func Slice(list, start, end cty.Value) (cty.Value, error) {
+ return SliceFunc.Call([]cty.Value{list, start, end})
+}
+
+// Values returns a list of the map values, in the order of the sorted keys.
+// This function only works on flat maps.
+func Values(values cty.Value) (cty.Value, error) {
+ return ValuesFunc.Call([]cty.Value{values})
+}
+
+// Zipmap constructs a map from a list of keys and a corresponding list of values.
+func Zipmap(keys, values cty.Value) (cty.Value, error) {
+ return ZipmapFunc.Call([]cty.Value{keys, values})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go
new file mode 100644
index 00000000000..406dea23325
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go
@@ -0,0 +1,123 @@
+package stdlib
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// MakeToFunc constructs a "to..." function, like "tostring", which converts
+// its argument to a specific type or type kind.
+//
+// The given type wantTy can be any type constraint that cty's "convert" package
+// would accept. In particular, this means that you can pass
+// cty.List(cty.DynamicPseudoType) to mean "list of any single type", which
+// will then cause cty to attempt to unify all of the element types when given
+// a tuple.
+func MakeToFunc(wantTy cty.Type) function.Function {
+ return function.New(&function.Spec{
+ Description: fmt.Sprintf("Converts the given value to %s, or raises an error if that conversion is impossible.", wantTy.FriendlyName()),
+ Params: []function.Parameter{
+ {
+ Name: "v",
+ // We use DynamicPseudoType rather than wantTy here so that
+ // all values will pass through the function API verbatim and
+ // we can handle the conversion logic within the Type and
+ // Impl functions. This allows us to customize the error
+ // messages to be more appropriate for an explicit type
+ // conversion, whereas the cty function system produces
+ // messages aimed at _implicit_ type conversions.
+ Type: cty.DynamicPseudoType,
+ AllowNull: true,
+ AllowDynamicType: true,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ gotTy := args[0].Type()
+ if gotTy.Equals(wantTy) {
+ return wantTy, nil
+ }
+ conv := convert.GetConversionUnsafe(args[0].Type(), wantTy)
+ if conv == nil {
+ // We'll use some specialized errors for some trickier cases,
+ // but most we can handle in a simple way.
+ switch {
+ case gotTy.IsTupleType() && wantTy.IsTupleType():
+ return cty.NilType, function.NewArgErrorf(0, "incompatible tuple type for conversion: %s", convert.MismatchMessage(gotTy, wantTy))
+ case gotTy.IsObjectType() && wantTy.IsObjectType():
+ return cty.NilType, function.NewArgErrorf(0, "incompatible object type for conversion: %s", convert.MismatchMessage(gotTy, wantTy))
+ default:
+ return cty.NilType, function.NewArgErrorf(0, "cannot convert %s to %s", gotTy.FriendlyName(), wantTy.FriendlyNameForConstraint())
+ }
+ }
+ // If a conversion is available then everything is fine.
+ return wantTy, nil
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ // We didn't set "AllowUnknown" on our argument, so it is guaranteed
+ // to be known here but may still be null.
+ ret, err := convert.Convert(args[0], retType)
+ if err != nil {
+ // Because we used GetConversionUnsafe above, conversion can
+ // still potentially fail in here. For example, if the user
+ // asks to convert the string "a" to bool then we'll
+ // optimistically permit it during type checking but fail here
+ // once we note that the value isn't either "true" or "false".
+ gotTy := args[0].Type()
+ switch {
+ case gotTy == cty.String && wantTy == cty.Bool:
+ what := "string"
+ if !args[0].IsNull() {
+ what = strconv.Quote(args[0].AsString())
+ }
+ return cty.NilVal, function.NewArgErrorf(0, `cannot convert %s to bool; only the strings "true" or "false" are allowed`, what)
+ case gotTy == cty.String && wantTy == cty.Number:
+ what := "string"
+ if !args[0].IsNull() {
+ what = strconv.Quote(args[0].AsString())
+ }
+ return cty.NilVal, function.NewArgErrorf(0, `cannot convert %s to number; given string must be a decimal representation of a number`, what)
+ default:
+ return cty.NilVal, function.NewArgErrorf(0, "cannot convert %s to %s", gotTy.FriendlyName(), wantTy.FriendlyNameForConstraint())
+ }
+ }
+ return ret, nil
+ },
+ })
+}
+
+// AssertNotNullFunc is a function which does nothing except return an error
+// if the argument given to it is null.
+//
+// This could be useful in some cases where the automatic refinment of
+// nullability isn't precise enough, because the result is guaranteed to not
+// be null and can therefore allow downstream comparisons to null to return
+// a known value even if the value is otherwise unknown.
+var AssertNotNullFunc = function.New(&function.Spec{
+ Description: "Returns the given value varbatim if it is non-null, or raises an error if it's null.",
+ Params: []function.Parameter{
+ {
+ Name: "v",
+ Type: cty.DynamicPseudoType,
+ // NOTE: We intentionally don't set AllowNull here, and so
+ // the function system will automatically reject a null argument
+ // for us before calling Impl.
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ return args[0].Type(), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ // Our argument doesn't set AllowNull: true, so we're guaranteed to
+ // have a non-null value in args[0].
+ return args[0], nil
+ },
+})
+
+func AssertNotNull(v cty.Value) (cty.Value, error) {
+ return AssertNotNullFunc.Call([]cty.Value{v})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
new file mode 100644
index 00000000000..e854e817b2e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
@@ -0,0 +1,104 @@
+package stdlib
+
+import (
+ "encoding/csv"
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var CSVDecodeFunc = function.New(&function.Spec{
+ Description: `Parses the given string as Comma Separated Values (as defined by RFC 4180) and returns a map of objects representing the table of data, using the first row as a header row to define the object attributes.`,
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ str := args[0]
+ if !str.IsKnown() {
+ return cty.DynamicPseudoType, nil
+ }
+
+ r := strings.NewReader(str.AsString())
+ cr := csv.NewReader(r)
+ headers, err := cr.Read()
+ if err == io.EOF {
+ return cty.DynamicPseudoType, fmt.Errorf("missing header line")
+ }
+ if err != nil {
+ return cty.DynamicPseudoType, csvError(err)
+ }
+
+ atys := make(map[string]cty.Type, len(headers))
+ for _, name := range headers {
+ if _, exists := atys[name]; exists {
+ return cty.DynamicPseudoType, fmt.Errorf("duplicate column name %q", name)
+ }
+ atys[name] = cty.String
+ }
+ return cty.List(cty.Object(atys)), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ ety := retType.ElementType()
+ atys := ety.AttributeTypes()
+ str := args[0]
+ r := strings.NewReader(str.AsString())
+ cr := csv.NewReader(r)
+ cr.FieldsPerRecord = len(atys)
+
+ // Read the header row first, since that'll tell us which indices
+ // map to which attribute names.
+ headers, err := cr.Read()
+ if err != nil {
+ return cty.DynamicVal, err
+ }
+
+ var rows []cty.Value
+ for {
+ cols, err := cr.Read()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return cty.DynamicVal, csvError(err)
+ }
+
+ vals := make(map[string]cty.Value, len(cols))
+ for i, str := range cols {
+ name := headers[i]
+ vals[name] = cty.StringVal(str)
+ }
+ rows = append(rows, cty.ObjectVal(vals))
+ }
+
+ if len(rows) == 0 {
+ return cty.ListValEmpty(ety), nil
+ }
+ return cty.ListVal(rows), nil
+ },
+})
+
+// CSVDecode parses the given CSV (RFC 4180) string and, if it is valid,
+// returns a list of objects representing the rows.
+//
+// The result is always a list of some object type. The first row of the
+// input is used to determine the object attributes, and subsequent rows
+// determine the values of those attributes.
+func CSVDecode(str cty.Value) (cty.Value, error) {
+ return CSVDecodeFunc.Call([]cty.Value{str})
+}
+
+func csvError(err error) error {
+ switch err := err.(type) {
+ case *csv.ParseError:
+ return fmt.Errorf("CSV parse error on line %d: %w", err.Line, err.Err)
+ default:
+ return err
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go
new file mode 100644
index 00000000000..85f58d4cc7c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go
@@ -0,0 +1,445 @@
+package stdlib
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var FormatDateFunc = function.New(&function.Spec{
+ Description: `Formats a timestamp given in RFC 3339 syntax into another timestamp in some other machine-oriented time syntax, as described in the format string.`,
+ Params: []function.Parameter{
+ {
+ Name: "format",
+ Type: cty.String,
+ },
+ {
+ Name: "time",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ formatStr := args[0].AsString()
+ timeStr := args[1].AsString()
+ t, err := parseTimestamp(timeStr)
+ if err != nil {
+ return cty.DynamicVal, function.NewArgError(1, err)
+ }
+
+ var buf bytes.Buffer
+ sc := bufio.NewScanner(strings.NewReader(formatStr))
+ sc.Split(splitDateFormat)
+ const esc = '\''
+ for sc.Scan() {
+ tok := sc.Bytes()
+
+ // The leading byte signals the token type
+ switch {
+ case tok[0] == esc:
+ if tok[len(tok)-1] != esc || len(tok) == 1 {
+ return cty.DynamicVal, function.NewArgErrorf(0, "unterminated literal '")
+ }
+ if len(tok) == 2 {
+ // Must be a single escaped quote, ''
+ buf.WriteByte(esc)
+ } else {
+ // The content (until a closing esc) is printed out verbatim
+ // except that we must un-double any double-esc escapes in
+ // the middle of the string.
+ raw := tok[1 : len(tok)-1]
+ for i := 0; i < len(raw); i++ {
+ buf.WriteByte(raw[i])
+ if raw[i] == esc {
+ i++ // skip the escaped quote
+ }
+ }
+ }
+
+ case startsDateFormatVerb(tok[0]):
+ switch tok[0] {
+ case 'Y':
+ y := t.Year()
+ switch len(tok) {
+ case 2:
+ fmt.Fprintf(&buf, "%02d", y%100)
+ case 4:
+ fmt.Fprintf(&buf, "%04d", y)
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: year must either be \"YY\" or \"YYYY\"", tok)
+ }
+ case 'M':
+ m := t.Month()
+ switch len(tok) {
+ case 1:
+ fmt.Fprintf(&buf, "%d", m)
+ case 2:
+ fmt.Fprintf(&buf, "%02d", m)
+ case 3:
+ buf.WriteString(m.String()[:3])
+ case 4:
+ buf.WriteString(m.String())
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: month must be \"M\", \"MM\", \"MMM\", or \"MMMM\"", tok)
+ }
+ case 'D':
+ d := t.Day()
+ switch len(tok) {
+ case 1:
+ fmt.Fprintf(&buf, "%d", d)
+ case 2:
+ fmt.Fprintf(&buf, "%02d", d)
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: day of month must either be \"D\" or \"DD\"", tok)
+ }
+ case 'E':
+ d := t.Weekday()
+ switch len(tok) {
+ case 3:
+ buf.WriteString(d.String()[:3])
+ case 4:
+ buf.WriteString(d.String())
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: day of week must either be \"EEE\" or \"EEEE\"", tok)
+ }
+ case 'h':
+ h := t.Hour()
+ switch len(tok) {
+ case 1:
+ fmt.Fprintf(&buf, "%d", h)
+ case 2:
+ fmt.Fprintf(&buf, "%02d", h)
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: 24-hour must either be \"h\" or \"hh\"", tok)
+ }
+ case 'H':
+ h := t.Hour() % 12
+ if h == 0 {
+ h = 12
+ }
+ switch len(tok) {
+ case 1:
+ fmt.Fprintf(&buf, "%d", h)
+ case 2:
+ fmt.Fprintf(&buf, "%02d", h)
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: 12-hour must either be \"H\" or \"HH\"", tok)
+ }
+ case 'A', 'a':
+ if len(tok) != 2 {
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: must be \"%s%s\"", tok, tok[0:1], tok[0:1])
+ }
+ upper := tok[0] == 'A'
+ switch t.Hour() / 12 {
+ case 0:
+ if upper {
+ buf.WriteString("AM")
+ } else {
+ buf.WriteString("am")
+ }
+ case 1:
+ if upper {
+ buf.WriteString("PM")
+ } else {
+ buf.WriteString("pm")
+ }
+ }
+ case 'm':
+ m := t.Minute()
+ switch len(tok) {
+ case 1:
+ fmt.Fprintf(&buf, "%d", m)
+ case 2:
+ fmt.Fprintf(&buf, "%02d", m)
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: minute must either be \"m\" or \"mm\"", tok)
+ }
+ case 's':
+ s := t.Second()
+ switch len(tok) {
+ case 1:
+ fmt.Fprintf(&buf, "%d", s)
+ case 2:
+ fmt.Fprintf(&buf, "%02d", s)
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: second must either be \"s\" or \"ss\"", tok)
+ }
+ case 'Z':
+ // We'll just lean on Go's own formatter for this one, since
+ // the necessary information is unexported.
+ switch len(tok) {
+ case 1:
+ buf.WriteString(t.Format("Z07:00"))
+ case 3:
+ str := t.Format("-0700")
+ switch str {
+ case "+0000":
+ buf.WriteString("UTC")
+ default:
+ buf.WriteString(str)
+ }
+ case 4:
+ buf.WriteString(t.Format("-0700"))
+ case 5:
+ buf.WriteString(t.Format("-07:00"))
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q: timezone must be Z, ZZZZ, or ZZZZZ", tok)
+ }
+ default:
+ return cty.DynamicVal, function.NewArgErrorf(0, "invalid date format verb %q", tok)
+ }
+
+ default:
+ // Any other starting character indicates a literal sequence
+ buf.Write(tok)
+ }
+ }
+
+ return cty.StringVal(buf.String()), nil
+ },
+})
+
+// TimeAddFunc is a function that adds a duration to a timestamp, returning a new timestamp.
+var TimeAddFunc = function.New(&function.Spec{
+ Description: `Adds the duration represented by the given duration string to the given RFC 3339 timestamp string, returning another RFC 3339 timestamp.`,
+ Params: []function.Parameter{
+ {
+ Name: "timestamp",
+ Type: cty.String,
+ },
+ {
+ Name: "duration",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ ts, err := parseTimestamp(args[0].AsString())
+ if err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+ duration, err := time.ParseDuration(args[1].AsString())
+ if err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+
+ return cty.StringVal(ts.Add(duration).Format(time.RFC3339)), nil
+ },
+})
+
+// FormatDate reformats a timestamp given in RFC3339 syntax into another time
+// syntax defined by a given format string.
+//
+// The format string uses letter mnemonics to represent portions of the
+// timestamp, with repetition signifying length variants of each portion.
+// Single quote characters ' can be used to quote sequences of literal letters
+// that should not be interpreted as formatting mnemonics.
+//
+// The full set of supported mnemonic sequences is listed below:
+//
+// YY Year modulo 100 zero-padded to two digits, like "06".
+// YYYY Four (or more) digit year, like "2006".
+// M Month number, like "1" for January.
+// MM Month number zero-padded to two digits, like "01".
+// MMM English month name abbreviated to three letters, like "Jan".
+// MMMM English month name unabbreviated, like "January".
+// D Day of month number, like "2".
+// DD Day of month number zero-padded to two digits, like "02".
+// EEE English day of week name abbreviated to three letters, like "Mon".
+// EEEE English day of week name unabbreviated, like "Monday".
+// h 24-hour number, like "2".
+// hh 24-hour number zero-padded to two digits, like "02".
+// H 12-hour number, like "2".
+// HH 12-hour number zero-padded to two digits, like "02".
+// AA Hour AM/PM marker in uppercase, like "AM".
+// aa Hour AM/PM marker in lowercase, like "am".
+// m Minute within hour, like "5".
+// mm Minute within hour zero-padded to two digits, like "05".
+// s Second within minute, like "9".
+// ss Second within minute zero-padded to two digits, like "09".
+// ZZZZ Timezone offset with just sign and digit, like "-0800".
+// ZZZZZ Timezone offset with colon separating hours and minutes, like "-08:00".
+// Z Like ZZZZZ but with a special case "Z" for UTC.
+// ZZZ Like ZZZZ but with a special case "UTC" for UTC.
+//
+// The format syntax is optimized mainly for generating machine-oriented
+// timestamps rather than human-oriented timestamps; the English language
+// portions of the output reflect the use of English names in a number of
+// machine-readable date formatting standards. For presentation to humans,
+// a locale-aware time formatter (not included in this package) is a better
+// choice.
+//
+// The format syntax is not compatible with that of any other language, but
+// is optimized so that patterns for common standard date formats can be
+// recognized quickly even by a reader unfamiliar with the format syntax.
+func FormatDate(format cty.Value, timestamp cty.Value) (cty.Value, error) {
+ return FormatDateFunc.Call([]cty.Value{format, timestamp})
+}
+
+// splitDataFormat is a bufio.SplitFunc used to tokenize a date format.
+func splitDateFormat(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if len(data) == 0 {
+ return 0, nil, nil
+ }
+
+ const esc = '\''
+
+ switch {
+
+ case data[0] == esc:
+ // If we have another quote immediately after then this is a single
+ // escaped escape.
+ if len(data) > 1 && data[1] == esc {
+ return 2, data[:2], nil
+ }
+
+ // Beginning of quoted sequence, so we will seek forward until we find
+ // the closing quote, ignoring escaped quotes along the way.
+ for i := 1; i < len(data); i++ {
+ if data[i] == esc {
+ if (i + 1) == len(data) {
+ if atEOF {
+ // We have a closing quote and are at the end of our input
+ return len(data), data, nil
+ } else {
+ // We need at least one more byte to decide if this is an
+ // escape or a terminator.
+ return 0, nil, nil
+ }
+ }
+ if data[i+1] == esc {
+ i++ // doubled-up quotes are an escape sequence
+ continue
+ }
+ // We've found the closing quote
+ return i + 1, data[:i+1], nil
+ }
+ }
+ // If we fall out here then we need more bytes to find the end,
+ // unless we're already at the end with an unclosed quote.
+ if atEOF {
+ return len(data), data, nil
+ }
+ return 0, nil, nil
+
+ case startsDateFormatVerb(data[0]):
+ rep := data[0]
+ for i := 1; i < len(data); i++ {
+ if data[i] != rep {
+ return i, data[:i], nil
+ }
+ }
+ if atEOF {
+ return len(data), data, nil
+ }
+ // We need more data to decide if we've found the end
+ return 0, nil, nil
+
+ default:
+ for i := 1; i < len(data); i++ {
+ if data[i] == esc || startsDateFormatVerb(data[i]) {
+ return i, data[:i], nil
+ }
+ }
+ // We might not actually be at the end of a literal sequence,
+ // but that doesn't matter since we'll concat them back together
+ // anyway.
+ return len(data), data, nil
+ }
+}
+
+func startsDateFormatVerb(b byte) bool {
+ return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')
+}
+
+func parseTimestamp(ts string) (time.Time, error) {
+ t, err := parseStrictRFC3339(ts)
+ if err != nil {
+ switch err := err.(type) {
+ case *time.ParseError:
+ // If err is s time.ParseError then its string representation is not
+ // appropriate since it relies on details of Go's strange date format
+ // representation, which a caller of our functions is not expected
+ // to be familiar with.
+ //
+ // Therefore we do some light transformation to get a more suitable
+ // error that should make more sense to our callers. These are
+ // still not awesome error messages, but at least they refer to
+ // the timestamp portions by name rather than by Go's example
+ // values.
+ if err.LayoutElem == "" && err.ValueElem == "" && err.Message != "" {
+ // For some reason err.Message is populated with a ": " prefix
+ // by the time package.
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp%s", err.Message)
+ }
+ var what string
+ switch err.LayoutElem {
+ case "2006":
+ what = "year"
+ case "01":
+ what = "month"
+ case "02":
+ what = "day of month"
+ case "15":
+ what = "hour"
+ case "04":
+ what = "minute"
+ case "05":
+ what = "second"
+ case "Z07:00":
+ what = "UTC offset"
+ case "T":
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: missing required time introducer 'T'")
+ case ":", "-":
+ if err.ValueElem == "" {
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: end of string where %q is expected", err.LayoutElem)
+ } else {
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: found %q where %q is expected", err.ValueElem, err.LayoutElem)
+ }
+ default:
+ // Should never get here, because RFC3339 includes only the
+ // above portions.
+ what = "timestamp segment"
+ }
+ if err.ValueElem == "" {
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: end of string before %s", what)
+ } else {
+ switch {
+ case what == "hour" && strings.Contains(err.ValueElem, ":"):
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: hour must be between 0 and 23 inclusive")
+ case what == "hour" && len(err.ValueElem) != 2:
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: hour must have exactly two digits")
+ case what == "minute" && len(err.ValueElem) != 2:
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: minute must have exactly two digits")
+ default:
+ return time.Time{}, fmt.Errorf("not a valid RFC3339 timestamp: cannot use %q as %s", err.ValueElem, what)
+ }
+ }
+ }
+ return time.Time{}, err
+ }
+ return t, nil
+}
+
+// TimeAdd adds a duration to a timestamp, returning a new timestamp.
+//
+// In the HCL language, timestamps are conventionally represented as
+// strings using RFC 3339 "Date and Time format" syntax. Timeadd requires
+// the timestamp argument to be a string conforming to this syntax.
+//
+// `duration` is a string representation of a time difference, consisting of
+// sequences of number and unit pairs, like `"1.5h"` or `1h30m`. The accepted
+// units are `ns`, `us` (or `µs`), `"ms"`, `"s"`, `"m"`, and `"h"`. The first
+// number may be negative to indicate a negative duration, like `"-2h5m"`.
+//
+// The result is a string, also in RFC 3339 format, representing the result
+// of adding the given direction to the given timestamp.
+func TimeAdd(timestamp cty.Value, duration cty.Value) (cty.Value, error) {
+ return TimeAddFunc.Call([]cty.Value{timestamp, duration})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime_rfc3339.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime_rfc3339.go
new file mode 100644
index 00000000000..687854f3784
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime_rfc3339.go
@@ -0,0 +1,219 @@
+package stdlib
+
+import (
+ "errors"
+ "strconv"
+ "time"
+)
+
+// This file inlines some RFC3339 parsing code that was added to the Go standard
+// library's "time" package during the Go 1.20 development period but then
+// reverted prior to release to follow the Go proposals process first.
+//
+// Our goal is to support only valid RFC3339 strings regardless of what version
+// of Go is being used, because the Go stdlib is just an implementation detail
+// of the cty stdlib and so these functions should not very their behavior
+// significantly due to being compiled against a different Go version.
+//
+// These inline copies of the code from upstream should likely stay here
+// indefinitely even if functionality like this _is_ accepted in a later version
+// of Go, because this now defines cty's definition of RFC3339 parsing as
+// intentionally independent of Go's.
+
+func parseStrictRFC3339(str string) (time.Time, error) {
+ t, ok := parseRFC3339(str)
+ if !ok {
+ // If parsing failed then we'll try to use time.Parse to gather up a
+ // helpful error object.
+ _, err := time.Parse(time.RFC3339, str)
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ // The parse template syntax cannot correctly validate RFC 3339.
+ // Explicitly check for cases that Parse is unable to validate for.
+ // See https://go.dev/issue/54580.
+ num2 := func(str string) byte { return 10*(str[0]-'0') + (str[1] - '0') }
+ switch {
+ case str[len("2006-01-02T")+1] == ':': // hour must be two digits
+ return time.Time{}, &time.ParseError{
+ Layout: time.RFC3339,
+ Value: str,
+ LayoutElem: "15",
+ ValueElem: str[len("2006-01-02T"):][:1],
+ Message: ": hour must have two digits",
+ }
+ case str[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period
+ return time.Time{}, &time.ParseError{
+ Layout: time.RFC3339,
+ Value: str,
+ LayoutElem: ".",
+ ValueElem: ",",
+ Message: ": sub-second separator must be a period",
+ }
+ case str[len(str)-1] != 'Z':
+ switch {
+ case num2(str[len(str)-len("07:00"):]) >= 24: // timezone hour must be in range
+ return time.Time{}, &time.ParseError{
+ Layout: time.RFC3339,
+ Value: str,
+ LayoutElem: "Z07:00",
+ ValueElem: str[len(str)-len("Z07:00"):],
+ Message: ": timezone hour out of range",
+ }
+ case num2(str[len(str)-len("00"):]) >= 60: // timezone minute must be in range
+ return time.Time{}, &time.ParseError{
+ Layout: time.RFC3339,
+ Value: str,
+ LayoutElem: "Z07:00",
+ ValueElem: str[len(str)-len("Z07:00"):],
+ Message: ": timezone minute out of range",
+ }
+ }
+ default: // unknown error; should not occur
+ return time.Time{}, &time.ParseError{
+ Layout: time.RFC3339,
+ Value: str,
+ LayoutElem: time.RFC3339,
+ ValueElem: str,
+ Message: "",
+ }
+ }
+ }
+ return t, nil
+}
+
+func parseRFC3339(s string) (time.Time, bool) {
+ // parseUint parses s as an unsigned decimal integer and
+ // verifies that it is within some range.
+ // If it is invalid or out-of-range,
+ // it sets ok to false and returns the min value.
+ ok := true
+ parseUint := func(s string, min, max int) (x int) {
+ for _, c := range []byte(s) {
+ if c < '0' || '9' < c {
+ ok = false
+ return min
+ }
+ x = x*10 + int(c) - '0'
+ }
+ if x < min || max < x {
+ ok = false
+ return min
+ }
+ return x
+ }
+
+ // Parse the date and time.
+ if len(s) < len("2006-01-02T15:04:05") {
+ return time.Time{}, false
+ }
+ year := parseUint(s[0:4], 0, 9999) // e.g., 2006
+ month := parseUint(s[5:7], 1, 12) // e.g., 01
+ day := parseUint(s[8:10], 1, daysIn(time.Month(month), year)) // e.g., 02
+ hour := parseUint(s[11:13], 0, 23) // e.g., 15
+ min := parseUint(s[14:16], 0, 59) // e.g., 04
+ sec := parseUint(s[17:19], 0, 59) // e.g., 05
+ if !ok || !(s[4] == '-' && s[7] == '-' && s[10] == 'T' && s[13] == ':' && s[16] == ':') {
+ return time.Time{}, false
+ }
+ s = s[19:]
+
+ // Parse the fractional second.
+ var nsec int
+ if len(s) >= 2 && s[0] == '.' && isDigit(s, 1) {
+ n := 2
+ for ; n < len(s) && isDigit(s, n); n++ {
+ }
+ nsec, _, _ = parseNanoseconds(s, n)
+ s = s[n:]
+ }
+
+ // Parse the time zone.
+ loc := time.UTC
+ if len(s) != 1 || s[0] != 'Z' {
+ if len(s) != len("-07:00") {
+ return time.Time{}, false
+ }
+ hr := parseUint(s[1:3], 0, 23) // e.g., 07
+ mm := parseUint(s[4:6], 0, 59) // e.g., 00
+ if !ok || !((s[0] == '-' || s[0] == '+') && s[3] == ':') {
+ return time.Time{}, false
+ }
+ zoneOffsetSecs := (hr*60 + mm) * 60
+ if s[0] == '-' {
+ zoneOffsetSecs = -zoneOffsetSecs
+ }
+ loc = time.FixedZone("", zoneOffsetSecs)
+ }
+ t := time.Date(year, time.Month(month), day, hour, min, sec, nsec, loc)
+
+ return t, true
+}
+
+func isDigit(s string, i int) bool {
+ if len(s) <= i {
+ return false
+ }
+ c := s[i]
+ return '0' <= c && c <= '9'
+}
+
+func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
+ if value[0] != '.' && value[0] != ',' {
+ err = errBadTimestamp
+ return
+ }
+ if nbytes > 10 {
+ value = value[:10]
+ nbytes = 10
+ }
+ if ns, err = strconv.Atoi(value[1:nbytes]); err != nil {
+ return
+ }
+ if ns < 0 {
+ rangeErrString = "fractional second"
+ return
+ }
+ // We need nanoseconds, which means scaling by the number
+ // of missing digits in the format, maximum length 10.
+ scaleDigits := 10 - nbytes
+ for i := 0; i < scaleDigits; i++ {
+ ns *= 10
+ }
+ return
+}
+
+// These are internal errors used by the date parsing code and are not ever
+// returned by public functions.
+var errBadTimestamp = errors.New("bad value for field")
+
+// daysBefore[m] counts the number of days in a non-leap year
+// before month m begins. There is an entry for m=12, counting
+// the number of days before January of next year (365).
+var daysBefore = [...]int32{
+ 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
+}
+
+func daysIn(m time.Month, year int) int {
+ if m == time.February && isLeap(year) {
+ return 29
+ }
+ return int(daysBefore[m] - daysBefore[m-1])
+}
+
+func isLeap(year int) bool {
+ return year%4 == 0 && (year%100 != 0 || year%400 == 0)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go
new file mode 100644
index 00000000000..cfb613e5a5d
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go
@@ -0,0 +1,13 @@
+// Package stdlib is a collection of cty functions that are expected to be
+// generally useful, and are thus factored out into this shared library in
+// the hope that cty-using applications will have consistent behavior when
+// using these functions.
+//
+// See the parent package "function" for more information on the purpose
+// and usage of cty functions.
+//
+// This package contains both Go functions, which provide convenient access
+// to call the functions from Go code, and the Function objects themselves.
+// The latter follow the naming scheme of appending "Func" to the end of
+// the function name.
+package stdlib
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
new file mode 100644
index 00000000000..9da529b187c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
@@ -0,0 +1,534 @@
+package stdlib
+
+import (
+ "bytes"
+ "fmt"
+ "math/big"
+ "strings"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/json"
+)
+
+//go:generate ragel -Z format_fsm.rl
+//go:generate gofmt -w format_fsm.go
+
+var FormatFunc = function.New(&function.Spec{
+ Description: `Constructs a string by applying formatting verbs to a series of arguments, using a similar syntax to the C function \"printf\".`,
+ Params: []function.Parameter{
+ {
+ Name: "format",
+ Type: cty.String,
+ },
+ },
+ VarParam: &function.Parameter{
+ Name: "args",
+ Type: cty.DynamicPseudoType,
+ AllowNull: true,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ for _, arg := range args[1:] {
+ if !arg.IsWhollyKnown() {
+ // We require all nested values to be known because the only
+ // thing we can do for a collection/structural type is print
+ // it as JSON and that requires it to be wholly known.
+ // However, we might be able to refine the result with a
+ // known prefix, if there are literal characters before the
+ // first formatting verb.
+ f := args[0].AsString()
+ if idx := strings.IndexByte(f, '%'); idx > 0 {
+ prefix := f[:idx]
+ return cty.UnknownVal(cty.String).Refine().StringPrefix(prefix).NewValue(), nil
+ }
+ return cty.UnknownVal(cty.String), nil
+ }
+ }
+ str, err := formatFSM(args[0].AsString(), args[1:])
+ return cty.StringVal(str), err
+ },
+})
+
+var FormatListFunc = function.New(&function.Spec{
+ Description: `Constructs a list of strings by applying formatting verbs to a series of arguments, using a similar syntax to the C function \"printf\".`,
+ Params: []function.Parameter{
+ {
+ Name: "format",
+ Type: cty.String,
+ },
+ },
+ VarParam: &function.Parameter{
+ Name: "args",
+ Type: cty.DynamicPseudoType,
+ AllowNull: true,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ },
+ Type: function.StaticReturnType(cty.List(cty.String)),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ fmtVal := args[0]
+ args = args[1:]
+
+ if len(args) == 0 {
+ // With no arguments, this function is equivalent to Format, but
+ // returning a single-element list result.
+ result, err := Format(fmtVal, args...)
+ return cty.ListVal([]cty.Value{result}), err
+ }
+
+ fmtStr := fmtVal.AsString()
+
+ // Each of our arguments will be dealt with either as an iterator
+ // or as a single value. Iterators are used for sequence-type values
+ // (lists, sets, tuples) while everything else is treated as a
+ // single value. The sequences we iterate over are required to be
+ // all the same length.
+ iterLen := -1
+ lenChooser := -1
+ iterators := make([]cty.ElementIterator, len(args))
+ singleVals := make([]cty.Value, len(args))
+ unknowns := make([]bool, len(args))
+ for i, arg := range args {
+ argTy := arg.Type()
+ switch {
+ case (argTy.IsListType() || argTy.IsSetType() || argTy.IsTupleType()) && !arg.IsNull():
+ if !argTy.IsTupleType() && !(arg.IsKnown() && arg.Length().IsKnown()) {
+ // We can't iterate this one at all yet then, so we can't
+ // yet produce a result.
+ unknowns[i] = true
+ continue
+ }
+ thisLen := arg.LengthInt()
+ if iterLen == -1 {
+ iterLen = thisLen
+ lenChooser = i
+ } else {
+ if thisLen != iterLen {
+ return cty.NullVal(cty.List(cty.String)), function.NewArgErrorf(
+ i+1,
+ "argument %d has length %d, which is inconsistent with argument %d of length %d",
+ i+1, thisLen,
+ lenChooser+1, iterLen,
+ )
+ }
+ }
+ if !arg.IsKnown() {
+ // We allowed an unknown tuple value to fall through in
+ // our initial check above so that we'd be able to run
+ // the above error checks against it, but we still can't
+ // iterate it if the checks pass.
+ unknowns[i] = true
+ continue
+ }
+ iterators[i] = arg.ElementIterator()
+ case arg == cty.DynamicVal:
+ unknowns[i] = true
+ default:
+ singleVals[i] = arg
+ }
+ }
+
+ for _, isUnk := range unknowns {
+ if isUnk {
+ return cty.UnknownVal(retType), nil
+ }
+ }
+
+ if iterLen == 0 {
+ // If our sequences are all empty then our result must be empty.
+ return cty.ListValEmpty(cty.String), nil
+ }
+
+ if iterLen == -1 {
+ // If we didn't encounter any iterables at all then we're going
+ // to just do one iteration with items from singleVals.
+ iterLen = 1
+ }
+
+ ret := make([]cty.Value, 0, iterLen)
+ fmtArgs := make([]cty.Value, len(iterators))
+ Results:
+ for iterIdx := 0; iterIdx < iterLen; iterIdx++ {
+
+ // Construct our arguments for a single format call
+ for i := range fmtArgs {
+ switch {
+ case iterators[i] != nil:
+ iterator := iterators[i]
+ iterator.Next()
+ _, val := iterator.Element()
+ fmtArgs[i] = val
+ default:
+ fmtArgs[i] = singleVals[i]
+ }
+
+ // If any of the arguments to this call would be unknown then
+ // this particular result is unknown, but we'll keep going
+ // to see if any other iterations can produce known values.
+ if !fmtArgs[i].IsWhollyKnown() {
+ // We require all nested values to be known because the only
+ // thing we can do for a collection/structural type is print
+ // it as JSON and that requires it to be wholly known.
+ ret = append(ret, cty.UnknownVal(cty.String).RefineNotNull())
+ continue Results
+ }
+ }
+
+ str, err := formatFSM(fmtStr, fmtArgs)
+ if err != nil {
+ return cty.NullVal(cty.List(cty.String)), fmt.Errorf(
+ "error on format iteration %d: %s", iterIdx, err,
+ )
+ }
+
+ ret = append(ret, cty.StringVal(str))
+ }
+
+ return cty.ListVal(ret), nil
+ },
+})
+
+// Format produces a string representation of zero or more values using a
+// format string similar to the "printf" function in C.
+//
+// It supports the following "verbs":
+//
+// %% Literal percent sign, consuming no value
+// %v A default formatting of the value based on type, as described below.
+// %#v JSON serialization of the value
+// %t Converts to boolean and then produces "true" or "false"
+// %b Converts to number, requires integer, produces binary representation
+// %d Converts to number, requires integer, produces decimal representation
+// %o Converts to number, requires integer, produces octal representation
+// %x Converts to number, requires integer, produces hexadecimal representation
+// with lowercase letters
+// %X Like %x but with uppercase letters
+// %e Converts to number, produces scientific notation like -1.234456e+78
+// %E Like %e but with an uppercase "E" representing the exponent
+// %f Converts to number, produces decimal representation with fractional
+// part but no exponent, like 123.456
+// %g %e for large exponents or %f otherwise
+// %G %E for large exponents or %f otherwise
+// %s Converts to string and produces the string's characters
+// %q Converts to string and produces JSON-quoted string representation,
+// like %v.
+//
+// The default format selections made by %v are:
+//
+// string %s
+// number %g
+// bool %t
+// other %#v
+//
+// Null values produce the literal keyword "null" for %v and %#v, and produce
+// an error otherwise.
+//
+// Width is specified by an optional decimal number immediately preceding the
+// verb letter. If absent, the width is whatever is necessary to represent the
+// value. Precision is specified after the (optional) width by a period
+// followed by a decimal number. If no period is present, a default precision
+// is used. A period with no following number is invalid.
+// For examples:
+//
+// %f default width, default precision
+// %9f width 9, default precision
+// %.2f default width, precision 2
+// %9.2f width 9, precision 2
+//
+// Width and precision are measured in unicode characters (grapheme clusters).
+//
+// For most values, width is the minimum number of characters to output,
+// padding the formatted form with spaces if necessary.
+//
+// For strings, precision limits the length of the input to be formatted (not
+// the size of the output), truncating if necessary.
+//
+// For numbers, width sets the minimum width of the field and precision sets
+// the number of places after the decimal, if appropriate, except that for
+// %g/%G precision sets the total number of significant digits.
+//
+// The following additional symbols can be used immediately after the percent
+// introducer as flags:
+//
+// (a space) leave a space where the sign would be if number is positive
+// + Include a sign for a number even if it is positive (numeric only)
+// - Pad with spaces on the left rather than the right
+// 0 Pad with zeros rather than spaces.
+//
+// Flag characters are ignored for verbs that do not support them.
+//
+// By default, % sequences consume successive arguments starting with the first.
+// Introducing a [n] sequence immediately before the verb letter, where n is a
+// decimal integer, explicitly chooses a particular value argument by its
+// one-based index. Subsequent calls without an explicit index will then
+// proceed with n+1, n+2, etc.
+//
+// An error is produced if the format string calls for an impossible conversion
+// or accesses more values than are given. An error is produced also for
+// an unsupported format verb.
+func Format(format cty.Value, vals ...cty.Value) (cty.Value, error) {
+ args := make([]cty.Value, 0, len(vals)+1)
+ args = append(args, format)
+ args = append(args, vals...)
+ return FormatFunc.Call(args)
+}
+
+// FormatList applies the same formatting behavior as Format, but accepts
+// a mixture of list and non-list values as arguments. Any list arguments
+// passed must have the same length, which dictates the length of the
+// resulting list.
+//
+// Any non-list arguments are used repeatedly for each iteration over the
+// list arguments. The list arguments are iterated in order by key, so
+// corresponding items are formatted together.
+func FormatList(format cty.Value, vals ...cty.Value) (cty.Value, error) {
+ args := make([]cty.Value, 0, len(vals)+1)
+ args = append(args, format)
+ args = append(args, vals...)
+ return FormatListFunc.Call(args)
+}
+
+type formatVerb struct {
+ Raw string
+ Offset int
+
+ ArgNum int
+ Mode rune
+
+ Zero bool
+ Sharp bool
+ Plus bool
+ Minus bool
+ Space bool
+
+ HasPrec bool
+ Prec int
+
+ HasWidth bool
+ Width int
+}
+
+// formatAppend is called by formatFSM (generated by format_fsm.rl) for each
+// formatting sequence that is encountered.
+func formatAppend(verb *formatVerb, buf *bytes.Buffer, args []cty.Value) error {
+ argIdx := verb.ArgNum - 1
+ if argIdx >= len(args) {
+ return fmt.Errorf(
+ "not enough arguments for %q at %d: need index %d but have %d total",
+ verb.Raw, verb.Offset,
+ verb.ArgNum, len(args),
+ )
+ }
+ arg := args[argIdx]
+
+ if verb.Mode != 'v' && arg.IsNull() {
+ return fmt.Errorf("unsupported value for %q at %d: null value cannot be formatted", verb.Raw, verb.Offset)
+ }
+
+ // Normalize to make some things easier for downstream formatters
+ if !verb.HasWidth {
+ verb.Width = -1
+ }
+ if !verb.HasPrec {
+ verb.Prec = -1
+ }
+
+ // For our first pass we'll ensure the verb is supported and then fan
+ // out to other functions based on what conversion is needed.
+ switch verb.Mode {
+
+ case 'v':
+ return formatAppendAsIs(verb, buf, arg)
+
+ case 't':
+ return formatAppendBool(verb, buf, arg)
+
+ case 'b', 'd', 'o', 'x', 'X', 'e', 'E', 'f', 'g', 'G':
+ return formatAppendNumber(verb, buf, arg)
+
+ case 's', 'q':
+ return formatAppendString(verb, buf, arg)
+
+ default:
+ return fmt.Errorf("unsupported format verb %q in %q at offset %d", verb.Mode, verb.Raw, verb.Offset)
+ }
+}
+
+func formatAppendAsIs(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
+
+ if !verb.Sharp && !arg.IsNull() {
+ // Unless the caller overrode it with the sharp flag, we'll try some
+ // specialized formats before we fall back on JSON.
+ switch arg.Type() {
+ case cty.String:
+ fmted := arg.AsString()
+ fmted = formatPadWidth(verb, fmted)
+ buf.WriteString(fmted)
+ return nil
+ case cty.Number:
+ bf := arg.AsBigFloat()
+ fmted := bf.Text('g', -1)
+ fmted = formatPadWidth(verb, fmted)
+ buf.WriteString(fmted)
+ return nil
+ }
+ }
+
+ jb, err := json.Marshal(arg, arg.Type())
+ if err != nil {
+ return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
+ }
+ fmted := formatPadWidth(verb, string(jb))
+ buf.WriteString(fmted)
+
+ return nil
+}
+
+func formatAppendBool(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
+ var err error
+ arg, err = convert.Convert(arg, cty.Bool)
+ if err != nil {
+ return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
+ }
+
+ if arg.True() {
+ buf.WriteString("true")
+ } else {
+ buf.WriteString("false")
+ }
+ return nil
+}
+
+func formatAppendNumber(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
+ var err error
+ arg, err = convert.Convert(arg, cty.Number)
+ if err != nil {
+ return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
+ }
+
+ switch verb.Mode {
+ case 'b', 'd', 'o', 'x', 'X':
+ return formatAppendInteger(verb, buf, arg)
+ default:
+ bf := arg.AsBigFloat()
+
+ // For floats our format syntax is a subset of Go's, so it's
+ // safe for us to just lean on the existing Go implementation.
+ fmtstr := formatStripIndexSegment(verb.Raw)
+ fmted := fmt.Sprintf(fmtstr, bf)
+ buf.WriteString(fmted)
+ return nil
+ }
+}
+
+func formatAppendInteger(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
+ bf := arg.AsBigFloat()
+ bi, acc := bf.Int(nil)
+ if acc != big.Exact {
+ return fmt.Errorf("unsupported value for %q at %d: an integer is required", verb.Raw, verb.Offset)
+ }
+
+ // For integers our format syntax is a subset of Go's, so it's
+ // safe for us to just lean on the existing Go implementation.
+ fmtstr := formatStripIndexSegment(verb.Raw)
+ fmted := fmt.Sprintf(fmtstr, bi)
+ buf.WriteString(fmted)
+ return nil
+}
+
+func formatAppendString(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
+ var err error
+ arg, err = convert.Convert(arg, cty.String)
+ if err != nil {
+ return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
+ }
+
+ // We _cannot_ directly use the Go fmt.Sprintf implementation for strings
+ // because it measures widths and precisions in runes rather than grapheme
+ // clusters.
+
+ str := arg.AsString()
+ if verb.Prec > 0 {
+ strB := []byte(str)
+ pos := 0
+ wanted := verb.Prec
+ for i := 0; i < wanted; i++ {
+ next := strB[pos:]
+ if len(next) == 0 {
+ // ran out of characters before we hit our max width
+ break
+ }
+ d, _, _ := textseg.ScanGraphemeClusters(strB[pos:], true)
+ pos += d
+ }
+ str = str[:pos]
+ }
+
+ switch verb.Mode {
+ case 's':
+ fmted := formatPadWidth(verb, str)
+ buf.WriteString(fmted)
+ case 'q':
+ jb, err := json.Marshal(cty.StringVal(str), cty.String)
+ if err != nil {
+ // Should never happen, since we know this is a known, non-null string
+ panic(fmt.Errorf("failed to marshal %#v as JSON: %s", arg, err))
+ }
+ fmted := formatPadWidth(verb, string(jb))
+ buf.WriteString(fmted)
+ default:
+ // Should never happen because formatAppend should've already validated
+ panic(fmt.Errorf("invalid string formatting mode %q", verb.Mode))
+ }
+ return nil
+}
+
+func formatPadWidth(verb *formatVerb, fmted string) string {
+ if verb.Width < 0 {
+ return fmted
+ }
+
+ // Safe to ignore errors because ScanGraphemeClusters cannot produce errors
+ givenLen, _ := textseg.TokenCount([]byte(fmted), textseg.ScanGraphemeClusters)
+ wantLen := verb.Width
+ if givenLen >= wantLen {
+ return fmted
+ }
+
+ padLen := wantLen - givenLen
+ padChar := " "
+ if verb.Zero {
+ padChar = "0"
+ }
+ pads := strings.Repeat(padChar, padLen)
+
+ if verb.Minus {
+ return fmted + pads
+ }
+ return pads + fmted
+}
+
+// formatStripIndexSegment strips out any [nnn] segment present in a verb
+// string so that we can pass it through to Go's fmt.Sprintf with a single
+// argument. This is used in cases where we're just leaning on Go's formatter
+// because it's a superset of ours.
+func formatStripIndexSegment(rawVerb string) string {
+ // We assume the string has already been validated here, since we should
+ // only be using this function with strings that were accepted by our
+ // scanner in formatFSM.
+ start := strings.Index(rawVerb, "[")
+ end := strings.Index(rawVerb, "]")
+ if start == -1 || end == -1 {
+ return rawVerb
+ }
+
+ return rawVerb[:start] + rawVerb[end+1:]
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
new file mode 100644
index 00000000000..32b1ac9712f
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
@@ -0,0 +1,374 @@
+// line 1 "format_fsm.rl"
+// This file is generated from format_fsm.rl. DO NOT EDIT.
+
+// line 5 "format_fsm.rl"
+
+package stdlib
+
+import (
+ "bytes"
+ "fmt"
+ "unicode/utf8"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// line 21 "format_fsm.go"
+var _formatfsm_actions []byte = []byte{
+ 0, 1, 0, 1, 1, 1, 2, 1, 4,
+ 1, 5, 1, 6, 1, 7, 1, 8,
+ 1, 9, 1, 10, 1, 11, 1, 14,
+ 1, 16, 1, 17, 1, 18, 2, 3,
+ 4, 2, 12, 10, 2, 12, 16, 2,
+ 12, 18, 2, 13, 14, 2, 15, 10,
+ 2, 15, 18,
+}
+
+var _formatfsm_key_offsets []byte = []byte{
+ 0, 0, 14, 27, 34, 36, 39, 43,
+ 51,
+}
+
+var _formatfsm_trans_keys []byte = []byte{
+ 32, 35, 37, 43, 45, 46, 48, 91,
+ 49, 57, 65, 90, 97, 122, 32, 35,
+ 43, 45, 46, 48, 91, 49, 57, 65,
+ 90, 97, 122, 91, 48, 57, 65, 90,
+ 97, 122, 49, 57, 93, 48, 57, 65,
+ 90, 97, 122, 46, 91, 48, 57, 65,
+ 90, 97, 122, 37,
+}
+
+var _formatfsm_single_lengths []byte = []byte{
+ 0, 8, 7, 1, 0, 1, 0, 2,
+ 1,
+}
+
+var _formatfsm_range_lengths []byte = []byte{
+ 0, 3, 3, 3, 1, 1, 2, 3,
+ 0,
+}
+
+var _formatfsm_index_offsets []byte = []byte{
+ 0, 0, 12, 23, 28, 30, 33, 36,
+ 42,
+}
+
+var _formatfsm_indicies []byte = []byte{
+ 1, 2, 3, 4, 5, 6, 7, 10,
+ 8, 9, 9, 0, 1, 2, 4, 5,
+ 6, 7, 10, 8, 9, 9, 0, 13,
+ 11, 12, 12, 0, 14, 0, 15, 14,
+ 0, 9, 9, 0, 16, 19, 17, 18,
+ 18, 0, 20, 3,
+}
+
+var _formatfsm_trans_targs []byte = []byte{
+ 0, 2, 2, 8, 2, 2, 3, 2,
+ 7, 8, 4, 3, 8, 4, 5, 6,
+ 3, 7, 8, 4, 1,
+}
+
+var _formatfsm_trans_actions []byte = []byte{
+ 7, 17, 9, 3, 15, 13, 25, 11,
+ 43, 29, 19, 27, 49, 46, 21, 0,
+ 37, 23, 40, 34, 1,
+}
+
+var _formatfsm_eof_actions []byte = []byte{
+ 0, 31, 31, 31, 31, 31, 31, 31,
+ 5,
+}
+
+const formatfsm_start int = 8
+const formatfsm_first_final int = 8
+const formatfsm_error int = 0
+
+const formatfsm_en_main int = 8
+
+// line 20 "format_fsm.rl"
+
+func formatFSM(format string, a []cty.Value) (string, error) {
+ var buf bytes.Buffer
+ data := format
+ nextArg := 1 // arg numbers are 1-based
+ var verb formatVerb
+ highestArgIdx := 0 // zero means "none", since arg numbers are 1-based
+
+ // line 159 "format_fsm.rl"
+
+ // Ragel state
+ p := 0 // "Pointer" into data
+ pe := len(data) // End-of-data "pointer"
+ cs := 0 // current state (will be initialized by ragel-generated code)
+ ts := 0
+ te := 0
+ eof := pe
+
+ // Keep Go compiler happy even if generated code doesn't use these
+ _ = ts
+ _ = te
+ _ = eof
+
+ // line 123 "format_fsm.go"
+ {
+ cs = formatfsm_start
+ }
+
+ // line 128 "format_fsm.go"
+ {
+ var _klen int
+ var _trans int
+ var _acts int
+ var _nacts uint
+ var _keys int
+ if p == pe {
+ goto _test_eof
+ }
+ if cs == 0 {
+ goto _out
+ }
+ _resume:
+ _keys = int(_formatfsm_key_offsets[cs])
+ _trans = int(_formatfsm_index_offsets[cs])
+
+ _klen = int(_formatfsm_single_lengths[cs])
+ if _klen > 0 {
+ _lower := int(_keys)
+ var _mid int
+ _upper := int(_keys + _klen - 1)
+ for {
+ if _upper < _lower {
+ break
+ }
+
+ _mid = _lower + ((_upper - _lower) >> 1)
+ switch {
+ case data[p] < _formatfsm_trans_keys[_mid]:
+ _upper = _mid - 1
+ case data[p] > _formatfsm_trans_keys[_mid]:
+ _lower = _mid + 1
+ default:
+ _trans += int(_mid - int(_keys))
+ goto _match
+ }
+ }
+ _keys += _klen
+ _trans += _klen
+ }
+
+ _klen = int(_formatfsm_range_lengths[cs])
+ if _klen > 0 {
+ _lower := int(_keys)
+ var _mid int
+ _upper := int(_keys + (_klen << 1) - 2)
+ for {
+ if _upper < _lower {
+ break
+ }
+
+ _mid = _lower + (((_upper - _lower) >> 1) & ^1)
+ switch {
+ case data[p] < _formatfsm_trans_keys[_mid]:
+ _upper = _mid - 2
+ case data[p] > _formatfsm_trans_keys[_mid+1]:
+ _lower = _mid + 2
+ default:
+ _trans += int((_mid - int(_keys)) >> 1)
+ goto _match
+ }
+ }
+ _trans += _klen
+ }
+
+ _match:
+ _trans = int(_formatfsm_indicies[_trans])
+ cs = int(_formatfsm_trans_targs[_trans])
+
+ if _formatfsm_trans_actions[_trans] == 0 {
+ goto _again
+ }
+
+ _acts = int(_formatfsm_trans_actions[_trans])
+ _nacts = uint(_formatfsm_actions[_acts])
+ _acts++
+ for ; _nacts > 0; _nacts-- {
+ _acts++
+ switch _formatfsm_actions[_acts-1] {
+ case 0:
+ // line 31 "format_fsm.rl"
+
+ verb = formatVerb{
+ ArgNum: nextArg,
+ Prec: -1,
+ Width: -1,
+ }
+ ts = p
+
+ case 1:
+ // line 40 "format_fsm.rl"
+
+ buf.WriteByte(data[p])
+
+ case 4:
+ // line 51 "format_fsm.rl"
+
+ // We'll try to slurp a whole UTF-8 sequence here, to give the user
+ // better feedback.
+ r, _ := utf8.DecodeRuneInString(data[p:])
+ return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
+
+ case 5:
+ // line 58 "format_fsm.rl"
+
+ verb.Sharp = true
+
+ case 6:
+ // line 61 "format_fsm.rl"
+
+ verb.Zero = true
+
+ case 7:
+ // line 64 "format_fsm.rl"
+
+ verb.Minus = true
+
+ case 8:
+ // line 67 "format_fsm.rl"
+
+ verb.Plus = true
+
+ case 9:
+ // line 70 "format_fsm.rl"
+
+ verb.Space = true
+
+ case 10:
+ // line 74 "format_fsm.rl"
+
+ verb.ArgNum = 0
+
+ case 11:
+ // line 77 "format_fsm.rl"
+
+ verb.ArgNum = (10 * verb.ArgNum) + (int(data[p]) - '0')
+
+ case 12:
+ // line 81 "format_fsm.rl"
+
+ verb.HasWidth = true
+
+ case 13:
+ // line 84 "format_fsm.rl"
+
+ verb.Width = 0
+
+ case 14:
+ // line 87 "format_fsm.rl"
+
+ verb.Width = (10 * verb.Width) + (int(data[p]) - '0')
+
+ case 15:
+ // line 91 "format_fsm.rl"
+
+ verb.HasPrec = true
+
+ case 16:
+ // line 94 "format_fsm.rl"
+
+ verb.Prec = 0
+
+ case 17:
+ // line 97 "format_fsm.rl"
+
+ verb.Prec = (10 * verb.Prec) + (int(data[p]) - '0')
+
+ case 18:
+ // line 101 "format_fsm.rl"
+
+ verb.Mode = rune(data[p])
+ te = p + 1
+ verb.Raw = data[ts:te]
+ verb.Offset = ts
+
+ if verb.ArgNum > highestArgIdx {
+ highestArgIdx = verb.ArgNum
+ }
+
+ err := formatAppend(&verb, &buf, a)
+ if err != nil {
+ return buf.String(), err
+ }
+ nextArg = verb.ArgNum + 1
+
+ // line 330 "format_fsm.go"
+ }
+ }
+
+ _again:
+ if cs == 0 {
+ goto _out
+ }
+ p++
+ if p != pe {
+ goto _resume
+ }
+ _test_eof:
+ {
+ }
+ if p == eof {
+ __acts := _formatfsm_eof_actions[cs]
+ __nacts := uint(_formatfsm_actions[__acts])
+ __acts++
+ for ; __nacts > 0; __nacts-- {
+ __acts++
+ switch _formatfsm_actions[__acts-1] {
+ case 2:
+ // line 44 "format_fsm.rl"
+
+ case 3:
+ // line 47 "format_fsm.rl"
+
+ return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
+
+ case 4:
+ // line 51 "format_fsm.rl"
+
+ // We'll try to slurp a whole UTF-8 sequence here, to give the user
+ // better feedback.
+ r, _ := utf8.DecodeRuneInString(data[p:])
+ return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
+
+ // line 369 "format_fsm.go"
+ }
+ }
+ }
+
+ _out:
+ {
+ }
+ }
+
+ // line 177 "format_fsm.rl"
+
+ // If we fall out here without being in a final state then we've
+ // encountered something that the scanner can't match, which should
+ // be impossible (the scanner matches all bytes _somehow_) but we'll
+ // flag it anyway rather than just losing data from the end.
+ if cs < formatfsm_first_final {
+ return buf.String(), fmt.Errorf("extraneous characters beginning at offset %d", p)
+ }
+
+ if highestArgIdx < len(a) {
+ // Extraneous args are an error, to more easily detect mistakes
+ firstBad := highestArgIdx + 1
+ if highestArgIdx == 0 {
+ // Custom error message for this case
+ return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; no verbs in format string")
+ }
+ return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; only %d used by format string", highestArgIdx)
+ }
+
+ return buf.String(), nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
new file mode 100644
index 00000000000..3c642d9e14e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
@@ -0,0 +1,198 @@
+// This file is generated from format_fsm.rl. DO NOT EDIT.
+%%{
+ # (except you are actually in scan_tokens.rl here, so edit away!)
+ machine formatfsm;
+}%%
+
+package stdlib
+
+import (
+ "bytes"
+ "fmt"
+ "unicode/utf8"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+%%{
+ write data;
+}%%
+
+func formatFSM(format string, a []cty.Value) (string, error) {
+ var buf bytes.Buffer
+ data := format
+ nextArg := 1 // arg numbers are 1-based
+ var verb formatVerb
+ highestArgIdx := 0 // zero means "none", since arg numbers are 1-based
+
+ %%{
+
+ action begin {
+ verb = formatVerb{
+ ArgNum: nextArg,
+ Prec: -1,
+ Width: -1,
+ }
+ ts = p
+ }
+
+ action emit {
+ buf.WriteByte(fc);
+ }
+
+ action finish_ok {
+ }
+
+ action finish_err {
+ return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
+ }
+
+ action err_char {
+ // We'll try to slurp a whole UTF-8 sequence here, to give the user
+ // better feedback.
+ r, _ := utf8.DecodeRuneInString(data[p:])
+ return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
+ }
+
+ action flag_sharp {
+ verb.Sharp = true
+ }
+ action flag_zero {
+ verb.Zero = true
+ }
+ action flag_minus {
+ verb.Minus = true
+ }
+ action flag_plus {
+ verb.Plus = true
+ }
+ action flag_space {
+ verb.Space = true
+ }
+
+ action argidx_reset {
+ verb.ArgNum = 0
+ }
+ action argidx_num {
+ verb.ArgNum = (10 * verb.ArgNum) + (int(fc) - '0')
+ }
+
+ action has_width {
+ verb.HasWidth = true
+ }
+ action width_reset {
+ verb.Width = 0
+ }
+ action width_num {
+ verb.Width = (10 * verb.Width) + (int(fc) - '0')
+ }
+
+ action has_prec {
+ verb.HasPrec = true
+ }
+ action prec_reset {
+ verb.Prec = 0
+ }
+ action prec_num {
+ verb.Prec = (10 * verb.Prec) + (int(fc) - '0')
+ }
+
+ action mode {
+ verb.Mode = rune(fc)
+ te = p+1
+ verb.Raw = data[ts:te]
+ verb.Offset = ts
+
+ if verb.ArgNum > highestArgIdx {
+ highestArgIdx = verb.ArgNum
+ }
+
+ err := formatAppend(&verb, &buf, a)
+ if err != nil {
+ return buf.String(), err
+ }
+ nextArg = verb.ArgNum + 1
+ }
+
+ # a number that isn't zero and doesn't have a leading zero
+ num = [1-9] [0-9]*;
+
+ flags = (
+ '0' @flag_zero |
+ '#' @flag_sharp |
+ '-' @flag_minus |
+ '+' @flag_plus |
+ ' ' @flag_space
+ )*;
+
+ argidx = ((
+ '[' (num $argidx_num) ']'
+ ) >argidx_reset)?;
+
+ width = (
+ ( num $width_num ) >width_reset %has_width
+ )?;
+
+ precision = (
+ ('.' ( digit* $prec_num )) >prec_reset %has_prec
+ )?;
+
+ # We accept any letter here, but will be more picky in formatAppend
+ mode = ('a'..'z' | 'A'..'Z') @mode;
+
+ fmt_verb = (
+ '%' @begin
+ flags
+ width
+ precision
+ argidx
+ mode
+ );
+
+ main := (
+ [^%] @emit |
+ '%%' @emit |
+ fmt_verb
+ )* @/finish_err %/finish_ok $!err_char;
+
+ }%%
+
+ // Ragel state
+ p := 0 // "Pointer" into data
+ pe := len(data) // End-of-data "pointer"
+ cs := 0 // current state (will be initialized by ragel-generated code)
+ ts := 0
+ te := 0
+ eof := pe
+
+ // Keep Go compiler happy even if generated code doesn't use these
+ _ = ts
+ _ = te
+ _ = eof
+
+ %%{
+ write init;
+ write exec;
+ }%%
+
+ // If we fall out here without being in a final state then we've
+ // encountered something that the scanner can't match, which should
+ // be impossible (the scanner matches all bytes _somehow_) but we'll
+ // flag it anyway rather than just losing data from the end.
+ if cs < formatfsm_first_final {
+ return buf.String(), fmt.Errorf("extraneous characters beginning at offset %d", p)
+ }
+
+ if highestArgIdx < len(a) {
+ // Extraneous args are an error, to more easily detect mistakes
+ firstBad := highestArgIdx+1
+ if highestArgIdx == 0 {
+ // Custom error message for this case
+ return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; no verbs in format string")
+ }
+ return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; only %d used by format string", highestArgIdx)
+ }
+
+ return buf.String(), nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go
new file mode 100644
index 00000000000..627b55a5ccc
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go
@@ -0,0 +1,117 @@
+package stdlib
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var EqualFunc = function.New(&function.Spec{
+ Description: `Returns true if the two given values are equal, or false otherwise.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ {
+ Name: "b",
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].Equals(args[1]), nil
+ },
+})
+
+var NotEqualFunc = function.New(&function.Spec{
+ Description: `Returns false if the two given values are equal, or true otherwise.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ {
+ Name: "b",
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].Equals(args[1]).Not(), nil
+ },
+})
+
+var CoalesceFunc = function.New(&function.Spec{
+ Description: `Returns the first of the given arguments that isn't null, or raises an error if there are no non-null arguments.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "vals",
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ argTypes := make([]cty.Type, len(args))
+ for i, val := range args {
+ argTypes[i] = val.Type()
+ }
+ retType, _ := convert.UnifyUnsafe(argTypes)
+ if retType == cty.NilType {
+ return cty.NilType, fmt.Errorf("all arguments must have the same type")
+ }
+ return retType, nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ for _, argVal := range args {
+ if !argVal.IsKnown() {
+ return cty.UnknownVal(retType), nil
+ }
+ if argVal.IsNull() {
+ continue
+ }
+
+ return convert.Convert(argVal, retType)
+ }
+ return cty.NilVal, fmt.Errorf("no non-null arguments")
+ },
+})
+
+func refineNonNull(b *cty.RefinementBuilder) *cty.RefinementBuilder {
+ return b.NotNull()
+}
+
+// Equal determines whether the two given values are equal, returning a
+// bool value.
+func Equal(a cty.Value, b cty.Value) (cty.Value, error) {
+ return EqualFunc.Call([]cty.Value{a, b})
+}
+
+// NotEqual is the opposite of Equal.
+func NotEqual(a cty.Value, b cty.Value) (cty.Value, error) {
+ return NotEqualFunc.Call([]cty.Value{a, b})
+}
+
+// Coalesce returns the first of the given arguments that is not null. If
+// all arguments are null, an error is produced.
+func Coalesce(vals ...cty.Value) (cty.Value, error) {
+ return CoalesceFunc.Call(vals)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go
new file mode 100644
index 00000000000..655977656fd
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go
@@ -0,0 +1,146 @@
+package stdlib
+
+import (
+ "bytes"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/json"
+)
+
+var JSONEncodeFunc = function.New(&function.Spec{
+ Description: `Returns a string containing a JSON representation of the given value.`,
+ Params: []function.Parameter{
+ {
+ Name: "val",
+ Type: cty.DynamicPseudoType,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowNull: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ val := args[0]
+ if !val.IsWhollyKnown() {
+ // We can't serialize unknowns, so if the value is unknown or
+ // contains any _nested_ unknowns then our result must be
+ // unknown. However, we might still be able to at least constrain
+ // the prefix of our string so that downstreams can sniff for
+ // whether it's valid JSON and what result types it could have.
+
+ valRng := val.Range()
+ if valRng.CouldBeNull() {
+ // If null is possible then we can't constrain the result
+ // beyond the type constraint, because the very first character
+ // of the string is what distinguishes a null.
+ return cty.UnknownVal(retType), nil
+ }
+ b := cty.UnknownVal(retType).Refine()
+ ty := valRng.TypeConstraint()
+ switch {
+ case ty == cty.String:
+ b = b.StringPrefixFull(`"`)
+ case ty.IsObjectType() || ty.IsMapType():
+ b = b.StringPrefixFull("{")
+ case ty.IsTupleType() || ty.IsListType() || ty.IsSetType():
+ b = b.StringPrefixFull("[")
+ }
+ return b.NewValue(), nil
+ }
+
+ if val.IsNull() {
+ return cty.StringVal("null"), nil
+ }
+
+ buf, err := json.Marshal(val, val.Type())
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ // json.Marshal should already produce a trimmed string, but we'll
+ // make sure it always is because our unknown value refinements above
+ // assume there will be no leading whitespace before the value.
+ buf = bytes.TrimSpace(buf)
+
+ return cty.StringVal(string(buf)), nil
+ },
+})
+
+var JSONDecodeFunc = function.New(&function.Spec{
+ Description: `Parses the given string as JSON and returns a value corresponding to what the JSON document describes.`,
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ str := args[0]
+ if !str.IsKnown() {
+ // If the string isn't known then we can't fully parse it, but
+ // if the value has been refined with a prefix then we may at
+ // least be able to reject obviously-invalid syntax and maybe
+ // even predict the result type. It's safe to return a specific
+ // result type only if parsing a full document with this prefix
+ // would return exactly that type or fail with a syntax error.
+ rng := str.Range()
+ if prefix := strings.TrimSpace(rng.StringPrefix()); prefix != "" {
+ // If we know at least one character then it should be one
+ // of the few characters that can introduce a JSON value.
+ switch r, _ := utf8.DecodeRuneInString(prefix); r {
+ case '{', '[':
+ // These can start object values and array values
+ // respectively, but we can't actually form a full
+ // object type constraint or tuple type constraint
+ // without knowing all of the attributes, so we
+ // will still return DynamicPseudoType in this case.
+ case '"':
+ // This means that the result will either be a string
+ // or parsing will fail.
+ return cty.String, nil
+ case 't', 'f':
+ // Must either be a boolean value or a syntax error.
+ return cty.Bool, nil
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
+ // These characters would all start the "number" production.
+ return cty.Number, nil
+ case 'n':
+ // n is valid to begin the keyword "null" but that doesn't
+ // give us any extra type information.
+ default:
+ // No other characters are valid as the beginning of a
+ // JSON value, so we can safely return an early error.
+ return cty.NilType, function.NewArgErrorf(0, "a JSON document cannot begin with the character %q", r)
+ }
+ }
+ return cty.DynamicPseudoType, nil
+ }
+
+ buf := []byte(str.AsString())
+ return json.ImpliedType(buf)
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ buf := []byte(args[0].AsString())
+ return json.Unmarshal(buf, retType)
+ },
+})
+
+// JSONEncode returns a JSON serialization of the given value.
+func JSONEncode(val cty.Value) (cty.Value, error) {
+ return JSONEncodeFunc.Call([]cty.Value{val})
+}
+
+// JSONDecode parses the given JSON string and, if it is valid, returns the
+// value it represents.
+//
+// Note that applying JSONDecode to the result of JSONEncode may not produce
+// an identically-typed result, since JSON encoding is lossy for cty Types.
+// The resulting value will consist only of primitive types, object types, and
+// tuple types.
+func JSONDecode(str cty.Value) (cty.Value, error) {
+ return JSONDecodeFunc.Call([]cty.Value{str})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
new file mode 100644
index 00000000000..73ef32f14dd
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
@@ -0,0 +1,715 @@
+package stdlib
+
+import (
+ "fmt"
+ "math"
+ "math/big"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/gocty"
+)
+
+var AbsoluteFunc = function.New(&function.Spec{
+ Description: `If the given number is negative then returns its positive equivalent, or otherwise returns the given number unchanged.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return args[0].Absolute(), nil
+ },
+})
+
+var AddFunc = function.New(&function.Spec{
+ Description: `Returns the sum of the two given numbers.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ // big.Float.Add can panic if the input values are opposing infinities,
+ // so we must catch that here in order to remain within
+ // the cty Function abstraction.
+ defer func() {
+ if r := recover(); r != nil {
+ if _, ok := r.(big.ErrNaN); ok {
+ ret = cty.NilVal
+ err = fmt.Errorf("can't compute sum of opposing infinities")
+ } else {
+ // not a panic we recognize
+ panic(r)
+ }
+ }
+ }()
+ return args[0].Add(args[1]), nil
+ },
+})
+
+var SubtractFunc = function.New(&function.Spec{
+ Description: `Returns the difference between the two given numbers.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ // big.Float.Sub can panic if the input values are infinities,
+ // so we must catch that here in order to remain within
+ // the cty Function abstraction.
+ defer func() {
+ if r := recover(); r != nil {
+ if _, ok := r.(big.ErrNaN); ok {
+ ret = cty.NilVal
+ err = fmt.Errorf("can't subtract infinity from itself")
+ } else {
+ // not a panic we recognize
+ panic(r)
+ }
+ }
+ }()
+ return args[0].Subtract(args[1]), nil
+ },
+})
+
+var MultiplyFunc = function.New(&function.Spec{
+ Description: `Returns the product of the two given numbers.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ // big.Float.Mul can panic if the input values are both zero or both
+ // infinity, so we must catch that here in order to remain within
+ // the cty Function abstraction.
+ defer func() {
+ if r := recover(); r != nil {
+ if _, ok := r.(big.ErrNaN); ok {
+ ret = cty.NilVal
+ err = fmt.Errorf("can't multiply zero by infinity")
+ } else {
+ // not a panic we recognize
+ panic(r)
+ }
+ }
+ }()
+
+ return args[0].Multiply(args[1]), nil
+ },
+})
+
+var DivideFunc = function.New(&function.Spec{
+ Description: `Divides the first given number by the second.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ // big.Float.Quo can panic if the input values are both zero or both
+ // infinity, so we must catch that here in order to remain within
+ // the cty Function abstraction.
+ defer func() {
+ if r := recover(); r != nil {
+ if _, ok := r.(big.ErrNaN); ok {
+ ret = cty.NilVal
+ err = fmt.Errorf("can't divide zero by zero or infinity by infinity")
+ } else {
+ // not a panic we recognize
+ panic(r)
+ }
+ }
+ }()
+
+ return args[0].Divide(args[1]), nil
+ },
+})
+
+var ModuloFunc = function.New(&function.Spec{
+ Description: `Divides the first given number by the second and then returns the remainder.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ // big.Float.Mul can panic if the input values are both zero or both
+ // infinity, so we must catch that here in order to remain within
+ // the cty Function abstraction.
+ defer func() {
+ if r := recover(); r != nil {
+ if _, ok := r.(big.ErrNaN); ok {
+ ret = cty.NilVal
+ err = fmt.Errorf("can't use modulo with zero and infinity")
+ } else {
+ // not a panic we recognize
+ panic(r)
+ }
+ }
+ }()
+
+ return args[0].Modulo(args[1]), nil
+ },
+})
+
+var GreaterThanFunc = function.New(&function.Spec{
+ Description: `Returns true if and only if the second number is greater than the first.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].GreaterThan(args[1]), nil
+ },
+})
+
+var GreaterThanOrEqualToFunc = function.New(&function.Spec{
+ Description: `Returns true if and only if the second number is greater than or equal to the first.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].GreaterThanOrEqualTo(args[1]), nil
+ },
+})
+
+var LessThanFunc = function.New(&function.Spec{
+ Description: `Returns true if and only if the second number is less than the first.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].LessThan(args[1]), nil
+ },
+})
+
+var LessThanOrEqualToFunc = function.New(&function.Spec{
+ Description: `Returns true if and only if the second number is less than or equal to the first.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Number,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].LessThanOrEqualTo(args[1]), nil
+ },
+})
+
+var NegateFunc = function.New(&function.Spec{
+ Description: `Multiplies the given number by -1.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ AllowMarked: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return args[0].Negate(), nil
+ },
+})
+
+var MinFunc = function.New(&function.Spec{
+ Description: `Returns the numerically smallest of all of the given numbers.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "numbers",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ if len(args) == 0 {
+ return cty.NilVal, fmt.Errorf("must pass at least one number")
+ }
+
+ min := cty.PositiveInfinity
+ for _, num := range args {
+ if num.LessThan(min).True() {
+ min = num
+ }
+ }
+
+ return min, nil
+ },
+})
+
+var MaxFunc = function.New(&function.Spec{
+ Description: `Returns the numerically greatest of all of the given numbers.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "numbers",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ if len(args) == 0 {
+ return cty.NilVal, fmt.Errorf("must pass at least one number")
+ }
+
+ max := cty.NegativeInfinity
+ for _, num := range args {
+ if num.GreaterThan(max).True() {
+ max = num
+ }
+ }
+
+ return max, nil
+ },
+})
+
+var IntFunc = function.New(&function.Spec{
+ Description: `Discards any fractional portion of the given number.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ bf := args[0].AsBigFloat()
+ if bf.IsInt() {
+ return args[0], nil
+ }
+ bi, _ := bf.Int(nil)
+ bf = (&big.Float{}).SetInt(bi)
+ return cty.NumberVal(bf), nil
+ },
+})
+
+// CeilFunc is a function that returns the closest whole number greater
+// than or equal to the given value.
+var CeilFunc = function.New(&function.Spec{
+ Description: `Returns the smallest whole number that is greater than or equal to the given value.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ f := args[0].AsBigFloat()
+
+ if f.IsInf() {
+ return cty.NumberVal(f), nil
+ }
+
+ i, acc := f.Int(nil)
+ switch acc {
+ case big.Exact, big.Above:
+ // Done.
+ case big.Below:
+ i.Add(i, big.NewInt(1))
+ }
+
+ return cty.NumberVal(f.SetInt(i)), nil
+ },
+})
+
+// FloorFunc is a function that returns the closest whole number lesser
+// than or equal to the given value.
+var FloorFunc = function.New(&function.Spec{
+ Description: `Returns the greatest whole number that is less than or equal to the given value.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ f := args[0].AsBigFloat()
+
+ if f.IsInf() {
+ return cty.NumberVal(f), nil
+ }
+
+ i, acc := f.Int(nil)
+ switch acc {
+ case big.Exact, big.Below:
+ // Done.
+ case big.Above:
+ i.Sub(i, big.NewInt(1))
+ }
+
+ return cty.NumberVal(f.SetInt(i)), nil
+ },
+})
+
+// LogFunc is a function that returns the logarithm of a given number in a given base.
+var LogFunc = function.New(&function.Spec{
+ Description: `Returns the logarithm of the given number in the given base.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ },
+ {
+ Name: "base",
+ Type: cty.Number,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ var num float64
+ if err := gocty.FromCtyValue(args[0], &num); err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+
+ var base float64
+ if err := gocty.FromCtyValue(args[1], &base); err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+
+ return cty.NumberFloatVal(math.Log(num) / math.Log(base)), nil
+ },
+})
+
+// PowFunc is a function that returns the logarithm of a given number in a given base.
+var PowFunc = function.New(&function.Spec{
+ Description: `Returns the given number raised to the given power (exponentiation).`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ },
+ {
+ Name: "power",
+ Type: cty.Number,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ var num float64
+ if err := gocty.FromCtyValue(args[0], &num); err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+
+ var power float64
+ if err := gocty.FromCtyValue(args[1], &power); err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+
+ return cty.NumberFloatVal(math.Pow(num, power)), nil
+ },
+})
+
+// SignumFunc is a function that determines the sign of a number, returning a
+// number between -1 and 1 to represent the sign..
+var SignumFunc = function.New(&function.Spec{
+ Description: `Returns 0 if the given number is zero, 1 if the given number is positive, or -1 if the given number is negative.`,
+ Params: []function.Parameter{
+ {
+ Name: "num",
+ Type: cty.Number,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ var num int
+ if err := gocty.FromCtyValue(args[0], &num); err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+ switch {
+ case num < 0:
+ return cty.NumberIntVal(-1), nil
+ case num > 0:
+ return cty.NumberIntVal(+1), nil
+ default:
+ return cty.NumberIntVal(0), nil
+ }
+ },
+})
+
+// ParseIntFunc is a function that parses a string argument and returns an integer of the specified base.
+var ParseIntFunc = function.New(&function.Spec{
+ Description: `Parses the given string as a number of the given base, or raises an error if the string contains invalid characters.`,
+ Params: []function.Parameter{
+ {
+ Name: "number",
+ Type: cty.DynamicPseudoType,
+ },
+ {
+ Name: "base",
+ Type: cty.Number,
+ },
+ },
+
+ Type: func(args []cty.Value) (cty.Type, error) {
+ if !args[0].Type().Equals(cty.String) {
+ return cty.Number, function.NewArgErrorf(0, "first argument must be a string, not %s", args[0].Type().FriendlyName())
+ }
+ return cty.Number, nil
+ },
+ RefineResult: refineNonNull,
+
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ var numstr string
+ var base int
+ var err error
+
+ if err = gocty.FromCtyValue(args[0], &numstr); err != nil {
+ return cty.UnknownVal(cty.String), function.NewArgError(0, err)
+ }
+
+ if err = gocty.FromCtyValue(args[1], &base); err != nil {
+ return cty.UnknownVal(cty.Number), function.NewArgError(1, err)
+ }
+
+ if base < 2 || base > 62 {
+ return cty.UnknownVal(cty.Number), function.NewArgErrorf(
+ 1,
+ "base must be a whole number between 2 and 62 inclusive",
+ )
+ }
+
+ num, ok := (&big.Int{}).SetString(numstr, base)
+ if !ok {
+ return cty.UnknownVal(cty.Number), function.NewArgErrorf(
+ 0,
+ "cannot parse %q as a base %d integer",
+ numstr,
+ base,
+ )
+ }
+
+ parsedNum := cty.NumberVal((&big.Float{}).SetInt(num))
+
+ return parsedNum, nil
+ },
+})
+
+// Absolute returns the magnitude of the given number, without its sign.
+// That is, it turns negative values into positive values.
+func Absolute(num cty.Value) (cty.Value, error) {
+ return AbsoluteFunc.Call([]cty.Value{num})
+}
+
+// Add returns the sum of the two given numbers.
+func Add(a cty.Value, b cty.Value) (cty.Value, error) {
+ return AddFunc.Call([]cty.Value{a, b})
+}
+
+// Subtract returns the difference between the two given numbers.
+func Subtract(a cty.Value, b cty.Value) (cty.Value, error) {
+ return SubtractFunc.Call([]cty.Value{a, b})
+}
+
+// Multiply returns the product of the two given numbers.
+func Multiply(a cty.Value, b cty.Value) (cty.Value, error) {
+ return MultiplyFunc.Call([]cty.Value{a, b})
+}
+
+// Divide returns a divided by b, where both a and b are numbers.
+func Divide(a cty.Value, b cty.Value) (cty.Value, error) {
+ return DivideFunc.Call([]cty.Value{a, b})
+}
+
+// Negate returns the given number multipled by -1.
+func Negate(num cty.Value) (cty.Value, error) {
+ return NegateFunc.Call([]cty.Value{num})
+}
+
+// LessThan returns true if a is less than b.
+func LessThan(a cty.Value, b cty.Value) (cty.Value, error) {
+ return LessThanFunc.Call([]cty.Value{a, b})
+}
+
+// LessThanOrEqualTo returns true if a is less than b.
+func LessThanOrEqualTo(a cty.Value, b cty.Value) (cty.Value, error) {
+ return LessThanOrEqualToFunc.Call([]cty.Value{a, b})
+}
+
+// GreaterThan returns true if a is less than b.
+func GreaterThan(a cty.Value, b cty.Value) (cty.Value, error) {
+ return GreaterThanFunc.Call([]cty.Value{a, b})
+}
+
+// GreaterThanOrEqualTo returns true if a is less than b.
+func GreaterThanOrEqualTo(a cty.Value, b cty.Value) (cty.Value, error) {
+ return GreaterThanOrEqualToFunc.Call([]cty.Value{a, b})
+}
+
+// Modulo returns the remainder of a divided by b under integer division,
+// where both a and b are numbers.
+func Modulo(a cty.Value, b cty.Value) (cty.Value, error) {
+ return ModuloFunc.Call([]cty.Value{a, b})
+}
+
+// Min returns the minimum number from the given numbers.
+func Min(numbers ...cty.Value) (cty.Value, error) {
+ return MinFunc.Call(numbers)
+}
+
+// Max returns the maximum number from the given numbers.
+func Max(numbers ...cty.Value) (cty.Value, error) {
+ return MaxFunc.Call(numbers)
+}
+
+// Int removes the fractional component of the given number returning an
+// integer representing the whole number component, rounding towards zero.
+// For example, -1.5 becomes -1.
+//
+// If an infinity is passed to Int, an error is returned.
+func Int(num cty.Value) (cty.Value, error) {
+ if num == cty.PositiveInfinity || num == cty.NegativeInfinity {
+ return cty.NilVal, fmt.Errorf("can't truncate infinity to an integer")
+ }
+ return IntFunc.Call([]cty.Value{num})
+}
+
+// Ceil returns the closest whole number greater than or equal to the given value.
+func Ceil(num cty.Value) (cty.Value, error) {
+ return CeilFunc.Call([]cty.Value{num})
+}
+
+// Floor returns the closest whole number lesser than or equal to the given value.
+func Floor(num cty.Value) (cty.Value, error) {
+ return FloorFunc.Call([]cty.Value{num})
+}
+
+// Log returns returns the logarithm of a given number in a given base.
+func Log(num, base cty.Value) (cty.Value, error) {
+ return LogFunc.Call([]cty.Value{num, base})
+}
+
+// Pow returns the logarithm of a given number in a given base.
+func Pow(num, power cty.Value) (cty.Value, error) {
+ return PowFunc.Call([]cty.Value{num, power})
+}
+
+// Signum determines the sign of a number, returning a number between -1 and
+// 1 to represent the sign.
+func Signum(num cty.Value) (cty.Value, error) {
+ return SignumFunc.Call([]cty.Value{num})
+}
+
+// ParseInt parses a string argument and returns an integer of the specified base.
+func ParseInt(num cty.Value, base cty.Value) (cty.Value, error) {
+ return ParseIntFunc.Call([]cty.Value{num, base})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go
new file mode 100644
index 00000000000..246544421c8
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go
@@ -0,0 +1,237 @@
+package stdlib
+
+import (
+ "fmt"
+ "regexp"
+ resyntax "regexp/syntax"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var RegexFunc = function.New(&function.Spec{
+ Description: `Applies the given regular expression pattern to the given string and returns information about a single match, or raises an error if there is no match.`,
+ Params: []function.Parameter{
+ {
+ Name: "pattern",
+ Type: cty.String,
+ },
+ {
+ Name: "string",
+ Type: cty.String,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ if !args[0].IsKnown() {
+ // We can't predict our type without seeing our pattern
+ return cty.DynamicPseudoType, nil
+ }
+
+ retTy, err := regexPatternResultType(args[0].AsString())
+ if err != nil {
+ err = function.NewArgError(0, err)
+ }
+ return retTy, err
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ if retType == cty.DynamicPseudoType {
+ return cty.DynamicVal, nil
+ }
+
+ re, err := regexp.Compile(args[0].AsString())
+ if err != nil {
+ // Should never happen, since we checked this in the Type function above.
+ return cty.NilVal, function.NewArgErrorf(0, "error parsing pattern: %s", err)
+ }
+ str := args[1].AsString()
+
+ captureIdxs := re.FindStringSubmatchIndex(str)
+ if captureIdxs == nil {
+ return cty.NilVal, fmt.Errorf("pattern did not match any part of the given string")
+ }
+
+ return regexPatternResult(re, str, captureIdxs, retType), nil
+ },
+})
+
+var RegexAllFunc = function.New(&function.Spec{
+ Description: `Applies the given regular expression pattern to the given string and returns a list of information about all non-overlapping matches, or an empty list if there are no matches.`,
+ Params: []function.Parameter{
+ {
+ Name: "pattern",
+ Type: cty.String,
+ },
+ {
+ Name: "string",
+ Type: cty.String,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ if !args[0].IsKnown() {
+ // We can't predict our type without seeing our pattern,
+ // but we do know it'll always be a list of something.
+ return cty.List(cty.DynamicPseudoType), nil
+ }
+
+ retTy, err := regexPatternResultType(args[0].AsString())
+ if err != nil {
+ err = function.NewArgError(0, err)
+ }
+ return cty.List(retTy), err
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ ety := retType.ElementType()
+ if ety == cty.DynamicPseudoType {
+ return cty.DynamicVal, nil
+ }
+
+ re, err := regexp.Compile(args[0].AsString())
+ if err != nil {
+ // Should never happen, since we checked this in the Type function above.
+ return cty.NilVal, function.NewArgErrorf(0, "error parsing pattern: %s", err)
+ }
+ str := args[1].AsString()
+
+ captureIdxsEach := re.FindAllStringSubmatchIndex(str, -1)
+ if len(captureIdxsEach) == 0 {
+ return cty.ListValEmpty(ety), nil
+ }
+
+ elems := make([]cty.Value, len(captureIdxsEach))
+ for i, captureIdxs := range captureIdxsEach {
+ elems[i] = regexPatternResult(re, str, captureIdxs, ety)
+ }
+ return cty.ListVal(elems), nil
+ },
+})
+
+// Regex is a function that extracts one or more substrings from a given
+// string by applying a regular expression pattern, describing the first
+// match.
+//
+// The return type depends on the composition of the capture groups (if any)
+// in the pattern:
+//
+// - If there are no capture groups at all, the result is a single string
+// representing the entire matched pattern.
+// - If all of the capture groups are named, the result is an object whose
+// keys are the named groups and whose values are their sub-matches, or
+// null if a particular sub-group was inside another group that didn't
+// match.
+// - If none of the capture groups are named, the result is a tuple whose
+// elements are the sub-groups in order and whose values are their
+// sub-matches, or null if a particular sub-group was inside another group
+// that didn't match.
+// - It is invalid to use both named and un-named capture groups together in
+// the same pattern.
+//
+// If the pattern doesn't match, this function returns an error. To test for
+// a match, call RegexAll and check if the length of the result is greater
+// than zero.
+func Regex(pattern, str cty.Value) (cty.Value, error) {
+ return RegexFunc.Call([]cty.Value{pattern, str})
+}
+
+// RegexAll is similar to Regex but it finds all of the non-overlapping matches
+// in the given string and returns a list of them.
+//
+// The result type is always a list, whose element type is deduced from the
+// pattern in the same way as the return type for Regex is decided.
+//
+// If the pattern doesn't match at all, this function returns an empty list.
+func RegexAll(pattern, str cty.Value) (cty.Value, error) {
+ return RegexAllFunc.Call([]cty.Value{pattern, str})
+}
+
+// regexPatternResultType parses the given regular expression pattern and
+// returns the structural type that would be returned to represent its
+// capture groups.
+//
+// Returns an error if parsing fails or if the pattern uses a mixture of
+// named and unnamed capture groups, which is not permitted.
+func regexPatternResultType(pattern string) (cty.Type, error) {
+ re, rawErr := regexp.Compile(pattern)
+ switch err := rawErr.(type) {
+ case *resyntax.Error:
+ return cty.NilType, fmt.Errorf("invalid regexp pattern: %s in %s", err.Code, err.Expr)
+ case error:
+ // Should never happen, since all regexp compile errors should
+ // be resyntax.Error, but just in case...
+ return cty.NilType, fmt.Errorf("error parsing pattern: %s", err)
+ }
+
+ allNames := re.SubexpNames()[1:]
+ var names []string
+ unnamed := 0
+ for _, name := range allNames {
+ if name == "" {
+ unnamed++
+ } else {
+ if names == nil {
+ names = make([]string, 0, len(allNames))
+ }
+ names = append(names, name)
+ }
+ }
+ switch {
+ case unnamed == 0 && len(names) == 0:
+ // If there are no capture groups at all then we'll return just a
+ // single string for the whole match.
+ return cty.String, nil
+ case unnamed > 0 && len(names) > 0:
+ return cty.NilType, fmt.Errorf("invalid regexp pattern: cannot mix both named and unnamed capture groups")
+ case unnamed > 0:
+ // For unnamed captures, we return a tuple of them all in order.
+ etys := make([]cty.Type, unnamed)
+ for i := range etys {
+ etys[i] = cty.String
+ }
+ return cty.Tuple(etys), nil
+ default:
+ // For named captures, we return an object using the capture names
+ // as keys.
+ atys := make(map[string]cty.Type, len(names))
+ for _, name := range names {
+ atys[name] = cty.String
+ }
+ return cty.Object(atys), nil
+ }
+}
+
+func regexPatternResult(re *regexp.Regexp, str string, captureIdxs []int, retType cty.Type) cty.Value {
+ switch {
+ case retType == cty.String:
+ start, end := captureIdxs[0], captureIdxs[1]
+ return cty.StringVal(str[start:end])
+ case retType.IsTupleType():
+ captureIdxs = captureIdxs[2:] // index 0 is the whole pattern span, which we ignore by skipping one pair
+ vals := make([]cty.Value, len(captureIdxs)/2)
+ for i := range vals {
+ start, end := captureIdxs[i*2], captureIdxs[i*2+1]
+ if start < 0 || end < 0 {
+ vals[i] = cty.NullVal(cty.String) // Did not match anything because containing group didn't match
+ continue
+ }
+ vals[i] = cty.StringVal(str[start:end])
+ }
+ return cty.TupleVal(vals)
+ case retType.IsObjectType():
+ captureIdxs = captureIdxs[2:] // index 0 is the whole pattern span, which we ignore by skipping one pair
+ vals := make(map[string]cty.Value, len(captureIdxs)/2)
+ names := re.SubexpNames()[1:]
+ for i, name := range names {
+ start, end := captureIdxs[i*2], captureIdxs[i*2+1]
+ if start < 0 || end < 0 {
+ vals[name] = cty.NullVal(cty.String) // Did not match anything because containing group didn't match
+ continue
+ }
+ vals[name] = cty.StringVal(str[start:end])
+ }
+ return cty.ObjectVal(vals)
+ default:
+ // Should never happen
+ panic(fmt.Sprintf("invalid return type %#v", retType))
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
new file mode 100644
index 00000000000..009949d472d
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
@@ -0,0 +1,239 @@
+package stdlib
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var ConcatFunc = function.New(&function.Spec{
+ Description: `Concatenates together all of the given lists or tuples into a single sequence, preserving the input order.`,
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "seqs",
+ Type: cty.DynamicPseudoType,
+ AllowMarked: true,
+ },
+ Type: func(args []cty.Value) (ret cty.Type, err error) {
+ if len(args) == 0 {
+ return cty.NilType, fmt.Errorf("at least one argument is required")
+ }
+
+ if args[0].Type().IsListType() {
+ // Possibly we're going to return a list, if all of our other
+ // args are also lists and we can find a common element type.
+ tys := make([]cty.Type, len(args))
+ for i, val := range args {
+ ty := val.Type()
+ if !ty.IsListType() {
+ tys = nil
+ break
+ }
+ tys[i] = ty
+ }
+
+ if tys != nil {
+ commonType, _ := convert.UnifyUnsafe(tys)
+ if commonType != cty.NilType {
+ return commonType, nil
+ }
+ }
+ }
+
+ etys := make([]cty.Type, 0, len(args))
+ for i, val := range args {
+ // Discard marks for nested values, as we only need to handle types
+ // and lengths.
+ val, _ := val.UnmarkDeep()
+
+ ety := val.Type()
+ switch {
+ case ety.IsTupleType():
+ etys = append(etys, ety.TupleElementTypes()...)
+ case ety.IsListType():
+ if !val.IsKnown() {
+ // We need to know the list to count its elements to
+ // build our tuple type, so any concat of an unknown
+ // list can't be typed yet.
+ return cty.DynamicPseudoType, nil
+ }
+
+ l := val.LengthInt()
+ subEty := ety.ElementType()
+ for j := 0; j < l; j++ {
+ etys = append(etys, subEty)
+ }
+ default:
+ return cty.NilType, function.NewArgErrorf(
+ i, "all arguments must be lists or tuples; got %s",
+ ety.FriendlyName(),
+ )
+ }
+ }
+ return cty.Tuple(etys), nil
+ },
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ switch {
+ case retType.IsListType():
+ // If retType is a list type then we know that all of the
+ // given values will be lists and that they will either be of
+ // retType or of something we can convert to retType.
+ vals := make([]cty.Value, 0, len(args))
+ var markses []cty.ValueMarks // remember any marked lists we find
+ for i, list := range args {
+ list, err = convert.Convert(list, retType)
+ if err != nil {
+ // Conversion might fail because we used UnifyUnsafe
+ // to choose our return type.
+ return cty.NilVal, function.NewArgError(i, err)
+ }
+
+ list, listMarks := list.Unmark()
+ if len(listMarks) > 0 {
+ markses = append(markses, listMarks)
+ }
+
+ it := list.ElementIterator()
+ for it.Next() {
+ _, v := it.Element()
+ vals = append(vals, v)
+ }
+ }
+ if len(vals) == 0 {
+ return cty.ListValEmpty(retType.ElementType()).WithMarks(markses...), nil
+ }
+
+ return cty.ListVal(vals).WithMarks(markses...), nil
+ case retType.IsTupleType():
+ // If retType is a tuple type then we could have a mixture of
+ // lists and tuples but we know they all have known values
+ // (because our params don't AllowUnknown) and we know that
+ // concatenating them all together will produce a tuple of
+ // retType because of the work we did in the Type function above.
+ vals := make([]cty.Value, 0, len(args))
+ var markses []cty.ValueMarks // remember any marked seqs we find
+
+ for _, seq := range args {
+ seq, seqMarks := seq.Unmark()
+ if len(seqMarks) > 0 {
+ markses = append(markses, seqMarks)
+ }
+
+ // Both lists and tuples support ElementIterator, so this is easy.
+ it := seq.ElementIterator()
+ for it.Next() {
+ _, v := it.Element()
+ vals = append(vals, v)
+ }
+ }
+
+ return cty.TupleVal(vals).WithMarks(markses...), nil
+ default:
+ // should never happen if Type is working correctly above
+ panic("unsupported return type")
+ }
+ },
+})
+
+var RangeFunc = function.New(&function.Spec{
+ Description: `Returns a list of numbers spread evenly over a particular range.`,
+ VarParam: &function.Parameter{
+ Name: "params",
+ Type: cty.Number,
+ },
+ Type: function.StaticReturnType(cty.List(cty.Number)),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ var start, end, step cty.Value
+ switch len(args) {
+ case 1:
+ if args[0].LessThan(cty.Zero).True() {
+ start, end, step = cty.Zero, args[0], cty.NumberIntVal(-1)
+ } else {
+ start, end, step = cty.Zero, args[0], cty.NumberIntVal(1)
+ }
+ case 2:
+ if args[1].LessThan(args[0]).True() {
+ start, end, step = args[0], args[1], cty.NumberIntVal(-1)
+ } else {
+ start, end, step = args[0], args[1], cty.NumberIntVal(1)
+ }
+ case 3:
+ start, end, step = args[0], args[1], args[2]
+ default:
+ return cty.NilVal, fmt.Errorf("must have one, two, or three arguments")
+ }
+
+ var vals []cty.Value
+
+ if step == cty.Zero {
+ return cty.NilVal, function.NewArgErrorf(2, "step must not be zero")
+ }
+ down := step.LessThan(cty.Zero).True()
+
+ if down {
+ if end.GreaterThan(start).True() {
+ return cty.NilVal, function.NewArgErrorf(1, "end must be less than start when step is negative")
+ }
+ } else {
+ if end.LessThan(start).True() {
+ return cty.NilVal, function.NewArgErrorf(1, "end must be greater than start when step is positive")
+ }
+ }
+
+ num := start
+ for {
+ if down {
+ if num.LessThanOrEqualTo(end).True() {
+ break
+ }
+ } else {
+ if num.GreaterThanOrEqualTo(end).True() {
+ break
+ }
+ }
+ if len(vals) >= 1024 {
+ // Artificial limit to prevent bad arguments from consuming huge amounts of memory
+ return cty.NilVal, fmt.Errorf("more than 1024 values were generated; either decrease the difference between start and end or use a smaller step")
+ }
+ vals = append(vals, num)
+ num = num.Add(step)
+ }
+ if len(vals) == 0 {
+ return cty.ListValEmpty(cty.Number), nil
+ }
+ return cty.ListVal(vals), nil
+ },
+})
+
+// Concat takes one or more sequences (lists or tuples) and returns the single
+// sequence that results from concatenating them together in order.
+//
+// If all of the given sequences are lists of the same element type then the
+// result is a list of that type. Otherwise, the result is a of a tuple type
+// constructed from the given sequence types.
+func Concat(seqs ...cty.Value) (cty.Value, error) {
+ return ConcatFunc.Call(seqs)
+}
+
+// Range creates a list of numbers by starting from the given starting value,
+// then adding the given step value until the result is greater than or
+// equal to the given stopping value. Each intermediate result becomes an
+// element in the resulting list.
+//
+// When all three parameters are set, the order is (start, end, step). If
+// only two parameters are set, they are the start and end respectively and
+// step defaults to 1. If only one argument is set, it gives the end value
+// with start defaulting to 0 and step defaulting to 1.
+//
+// Because the resulting list must be fully buffered in memory, there is an
+// artificial cap of 1024 elements, after which this function will return
+// an error to avoid consuming unbounded amounts of memory. The Range function
+// is primarily intended for creating small lists of indices to iterate over,
+// so there should be no reason to generate huge lists with it.
+func Range(params ...cty.Value) (cty.Value, error) {
+ return RangeFunc.Call(params)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go
new file mode 100644
index 00000000000..6da22919169
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go
@@ -0,0 +1,232 @@
+package stdlib
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty/convert"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+var SetHasElementFunc = function.New(&function.Spec{
+ Description: `Returns true if the given set contains the given element, or false otherwise.`,
+ Params: []function.Parameter{
+ {
+ Name: "set",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ {
+ Name: "elem",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Bool),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return args[0].HasElement(args[1]), nil
+ },
+})
+
+var SetUnionFunc = function.New(&function.Spec{
+ Description: `Returns the union of all given sets.`,
+ Params: []function.Parameter{
+ {
+ Name: "first_set",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ },
+ VarParam: &function.Parameter{
+ Name: "other_sets",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ Type: setOperationReturnType,
+ RefineResult: refineNonNull,
+ Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
+ return s1.Union(s2)
+ }, true),
+})
+
+var SetIntersectionFunc = function.New(&function.Spec{
+ Description: `Returns the intersection of all given sets.`,
+ Params: []function.Parameter{
+ {
+ Name: "first_set",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ },
+ VarParam: &function.Parameter{
+ Name: "other_sets",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ Type: setOperationReturnType,
+ RefineResult: refineNonNull,
+ Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
+ return s1.Intersection(s2)
+ }, false),
+})
+
+var SetSubtractFunc = function.New(&function.Spec{
+ Description: `Returns the relative complement of the two given sets.`,
+ Params: []function.Parameter{
+ {
+ Name: "a",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ {
+ Name: "b",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ },
+ Type: setOperationReturnType,
+ RefineResult: refineNonNull,
+ Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
+ return s1.Subtract(s2)
+ }, false),
+})
+
+var SetSymmetricDifferenceFunc = function.New(&function.Spec{
+ Description: `Returns the symmetric difference of the two given sets.`,
+ Params: []function.Parameter{
+ {
+ Name: "first_set",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ },
+ VarParam: &function.Parameter{
+ Name: "other_sets",
+ Type: cty.Set(cty.DynamicPseudoType),
+ AllowDynamicType: true,
+ },
+ Type: setOperationReturnType,
+ RefineResult: refineNonNull,
+ Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
+ return s1.SymmetricDifference(s2)
+ }, false),
+})
+
+// SetHasElement determines whether the given set contains the given value as an
+// element.
+func SetHasElement(set cty.Value, elem cty.Value) (cty.Value, error) {
+ return SetHasElementFunc.Call([]cty.Value{set, elem})
+}
+
+// SetUnion returns a new set containing all of the elements from the given
+// sets, which must have element types that can all be converted to some
+// common type using the standard type unification rules. If conversion
+// is not possible, an error is returned.
+//
+// The union operation is performed after type conversion, which may result
+// in some previously-distinct values being conflated.
+//
+// At least one set must be provided.
+func SetUnion(sets ...cty.Value) (cty.Value, error) {
+ return SetUnionFunc.Call(sets)
+}
+
+// Intersection returns a new set containing the elements that exist
+// in all of the given sets, which must have element types that can all be
+// converted to some common type using the standard type unification rules.
+// If conversion is not possible, an error is returned.
+//
+// The intersection operation is performed after type conversion, which may
+// result in some previously-distinct values being conflated.
+//
+// At least one set must be provided.
+func SetIntersection(sets ...cty.Value) (cty.Value, error) {
+ return SetIntersectionFunc.Call(sets)
+}
+
+// SetSubtract returns a new set containing the elements from the
+// first set that are not present in the second set. The sets must have
+// element types that can both be converted to some common type using the
+// standard type unification rules. If conversion is not possible, an error
+// is returned.
+//
+// The subtract operation is performed after type conversion, which may
+// result in some previously-distinct values being conflated.
+func SetSubtract(a, b cty.Value) (cty.Value, error) {
+ return SetSubtractFunc.Call([]cty.Value{a, b})
+}
+
+// SetSymmetricDifference returns a new set containing elements that appear
+// in any of the given sets but not multiple. The sets must have
+// element types that can all be converted to some common type using the
+// standard type unification rules. If conversion is not possible, an error
+// is returned.
+//
+// The difference operation is performed after type conversion, which may
+// result in some previously-distinct values being conflated.
+func SetSymmetricDifference(sets ...cty.Value) (cty.Value, error) {
+ return SetSymmetricDifferenceFunc.Call(sets)
+}
+
+func setOperationReturnType(args []cty.Value) (ret cty.Type, err error) {
+ var etys []cty.Type
+ for _, arg := range args {
+ ty := arg.Type().ElementType()
+
+ // Do not unify types for empty dynamic pseudo typed collections. These
+ // will always convert to any other concrete type.
+ if arg.IsKnown() && arg.LengthInt() == 0 && ty.Equals(cty.DynamicPseudoType) {
+ continue
+ }
+
+ etys = append(etys, ty)
+ }
+
+ // If all element types were skipped (due to being empty dynamic collections),
+ // the return type should also be a set of dynamic pseudo type.
+ if len(etys) == 0 {
+ return cty.Set(cty.DynamicPseudoType), nil
+ }
+
+ newEty, _ := convert.UnifyUnsafe(etys)
+ if newEty == cty.NilType {
+ return cty.NilType, fmt.Errorf("given sets must all have compatible element types")
+ }
+ return cty.Set(newEty), nil
+}
+
+func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet, allowUnknowns bool) function.ImplFunc {
+ return func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ first := args[0]
+ first, err = convert.Convert(first, retType)
+ if err != nil {
+ return cty.NilVal, function.NewArgError(0, err)
+ }
+ if !allowUnknowns && !first.IsWhollyKnown() {
+ // This set function can produce a correct result only when all
+ // elements are known, because eventually knowing the unknown
+ // values may cause the result to have fewer known elements, or
+ // might cause a result with no unknown elements at all to become
+ // one with a different length.
+ return cty.UnknownVal(retType), nil
+ }
+
+ set := first.AsValueSet()
+ for i, arg := range args[1:] {
+ arg, err := convert.Convert(arg, retType)
+ if err != nil {
+ return cty.NilVal, function.NewArgError(i+1, err)
+ }
+ if !allowUnknowns && !arg.IsWhollyKnown() {
+ // (For the same reason as we did this check for "first" above.)
+ return cty.UnknownVal(retType), nil
+ }
+
+ argSet := arg.AsValueSet()
+ set = f(set, argSet)
+ }
+ return cty.SetValFromValueSet(set), nil
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
new file mode 100644
index 00000000000..f79bf98df2e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
@@ -0,0 +1,624 @@
+package stdlib
+
+import (
+ "fmt"
+ "regexp"
+ "sort"
+ "strings"
+
+ "github.com/apparentlymart/go-textseg/v15/textseg"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/gocty"
+)
+
+var UpperFunc = function.New(&function.Spec{
+ Description: "Returns the given string with all Unicode letters translated to their uppercase equivalents.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ in := args[0].AsString()
+ out := strings.ToUpper(in)
+ return cty.StringVal(out), nil
+ },
+})
+
+var LowerFunc = function.New(&function.Spec{
+ Description: "Returns the given string with all Unicode letters translated to their lowercase equivalents.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ in := args[0].AsString()
+ out := strings.ToLower(in)
+ return cty.StringVal(out), nil
+ },
+})
+
+var ReverseFunc = function.New(&function.Spec{
+ Description: "Returns the given string with all of its Unicode characters in reverse order.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ in := []byte(args[0].AsString())
+ out := make([]byte, len(in))
+ pos := len(out)
+
+ inB := []byte(in)
+ for i := 0; i < len(in); {
+ d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
+ cluster := in[i : i+d]
+ pos -= len(cluster)
+ copy(out[pos:], cluster)
+ i += d
+ }
+
+ return cty.StringVal(string(out)), nil
+ },
+})
+
+var StrlenFunc = function.New(&function.Spec{
+ Description: "Returns the number of Unicode characters (technically: grapheme clusters) in the given string.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ AllowUnknown: true,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ RefineResult: func(b *cty.RefinementBuilder) *cty.RefinementBuilder {
+ // String length is never null and never negative.
+ // (We might refine the lower bound even more inside Impl.)
+ return b.NotNull().NumberRangeLowerBound(cty.NumberIntVal(0), true)
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ if !args[0].IsKnown() {
+ ret := cty.UnknownVal(cty.Number)
+ // We may be able to still return a constrained result based on the
+ // refined range of the unknown value.
+ inRng := args[0].Range()
+ if inRng.TypeConstraint() == cty.String {
+ prefixLen := int64(graphemeClusterCount(inRng.StringPrefix()))
+ ret = ret.Refine().NumberRangeLowerBound(cty.NumberIntVal(prefixLen), true).NewValue()
+ }
+ return ret, nil
+ }
+
+ in := args[0].AsString()
+ l := graphemeClusterCount(in)
+ return cty.NumberIntVal(int64(l)), nil
+ },
+})
+
+func graphemeClusterCount(in string) int {
+ l := 0
+ inB := []byte(in)
+ for i := 0; i < len(in); {
+ d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
+ l++
+ i += d
+ }
+ return l
+}
+
+var SubstrFunc = function.New(&function.Spec{
+ Description: "Extracts a substring from the given string.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Description: "The input string.",
+ Type: cty.String,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "offset",
+ Description: "The starting offset in Unicode characters.",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ {
+ Name: "length",
+ Description: "The maximum length of the result in Unicode characters.",
+ Type: cty.Number,
+ AllowDynamicType: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ in := []byte(args[0].AsString())
+ var offset, length int
+
+ var err error
+ err = gocty.FromCtyValue(args[1], &offset)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ err = gocty.FromCtyValue(args[2], &length)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ if offset < 0 {
+ totalLenNum, err := Strlen(args[0])
+ if err != nil {
+ // should never happen
+ panic("Stdlen returned an error")
+ }
+
+ var totalLen int
+ err = gocty.FromCtyValue(totalLenNum, &totalLen)
+ if err != nil {
+ // should never happen
+ panic("Stdlen returned a non-int number")
+ }
+
+ offset += totalLen
+ } else if length == 0 {
+ // Short circuit here, after error checks, because if a
+ // string of length 0 has been requested it will always
+ // be the empty string
+ return cty.StringVal(""), nil
+ }
+
+ sub := in
+ pos := 0
+ var i int
+
+ // First we'll seek forward to our offset
+ if offset > 0 {
+ for i = 0; i < len(sub); {
+ d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
+ i += d
+ pos++
+ if pos == offset {
+ break
+ }
+ if i >= len(in) {
+ return cty.StringVal(""), nil
+ }
+ }
+
+ sub = sub[i:]
+ }
+
+ if length < 0 {
+ // Taking the remainder of the string is a fast path since
+ // we can just return the rest of the buffer verbatim.
+ return cty.StringVal(string(sub)), nil
+ }
+
+ // Otherwise we need to start seeking forward again until we
+ // reach the length we want.
+ pos = 0
+ for i = 0; i < len(sub); {
+ d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
+ i += d
+ pos++
+ if pos == length {
+ break
+ }
+ }
+
+ sub = sub[:i]
+
+ return cty.StringVal(string(sub)), nil
+ },
+})
+
+var JoinFunc = function.New(&function.Spec{
+ Description: "Concatenates together the elements of all given lists with a delimiter, producing a single string.",
+ Params: []function.Parameter{
+ {
+ Name: "separator",
+ Description: "Delimiter to insert between the given strings.",
+ Type: cty.String,
+ },
+ },
+ VarParam: &function.Parameter{
+ Name: "lists",
+ Description: "One or more lists of strings to join.",
+ Type: cty.List(cty.String),
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ sep := args[0].AsString()
+ listVals := args[1:]
+ if len(listVals) < 1 {
+ return cty.UnknownVal(cty.String), fmt.Errorf("at least one list is required")
+ }
+
+ l := 0
+ for _, list := range listVals {
+ if !list.IsWhollyKnown() {
+ return cty.UnknownVal(cty.String), nil
+ }
+ l += list.LengthInt()
+ }
+
+ items := make([]string, 0, l)
+ for ai, list := range listVals {
+ ei := 0
+ for it := list.ElementIterator(); it.Next(); {
+ _, val := it.Element()
+ if val.IsNull() {
+ if len(listVals) > 1 {
+ return cty.UnknownVal(cty.String), function.NewArgErrorf(ai+1, "element %d of list %d is null; cannot concatenate null values", ei, ai+1)
+ }
+ return cty.UnknownVal(cty.String), function.NewArgErrorf(ai+1, "element %d is null; cannot concatenate null values", ei)
+ }
+ items = append(items, val.AsString())
+ ei++
+ }
+ }
+
+ return cty.StringVal(strings.Join(items, sep)), nil
+ },
+})
+
+var SortFunc = function.New(&function.Spec{
+ Description: "Applies a lexicographic sort to the elements of the given list.",
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.List(cty.String),
+ AllowUnknown: true,
+ },
+ },
+ Type: function.StaticReturnType(cty.List(cty.String)),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ listVal := args[0]
+
+ if !listVal.IsWhollyKnown() {
+ // If some of the element values aren't known yet then we
+ // can't yet predict the order of the result, but we can be
+ // sure that the length won't change.
+ ret := cty.UnknownVal(retType)
+ if listVal.Type().IsListType() {
+ rng := listVal.Range()
+ ret = ret.Refine().
+ CollectionLengthLowerBound(rng.LengthLowerBound()).
+ CollectionLengthUpperBound(rng.LengthUpperBound()).
+ NewValue()
+ }
+ return ret, nil
+ }
+ if listVal.LengthInt() == 0 { // Easy path
+ return listVal, nil
+ }
+
+ list := make([]string, 0, listVal.LengthInt())
+ for it := listVal.ElementIterator(); it.Next(); {
+ iv, v := it.Element()
+ if v.IsNull() {
+ return cty.UnknownVal(retType), fmt.Errorf("given list element %s is null; a null string cannot be sorted", iv.AsBigFloat().String())
+ }
+ list = append(list, v.AsString())
+ }
+
+ sort.Strings(list)
+ retVals := make([]cty.Value, len(list))
+ for i, s := range list {
+ retVals[i] = cty.StringVal(s)
+ }
+ return cty.ListVal(retVals), nil
+ },
+})
+
+var SplitFunc = function.New(&function.Spec{
+ Description: "Produces a list of one or more strings by splitting the given string at all instances of a given separator substring.",
+ Params: []function.Parameter{
+ {
+ Name: "separator",
+ Description: "The substring that delimits the result strings.",
+ Type: cty.String,
+ },
+ {
+ Name: "str",
+ Description: "The string to split.",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.List(cty.String)),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ sep := args[0].AsString()
+ str := args[1].AsString()
+ elems := strings.Split(str, sep)
+ elemVals := make([]cty.Value, len(elems))
+ for i, s := range elems {
+ elemVals[i] = cty.StringVal(s)
+ }
+ if len(elemVals) == 0 {
+ return cty.ListValEmpty(cty.String), nil
+ }
+ return cty.ListVal(elemVals), nil
+ },
+})
+
+// ChompFunc is a function that removes newline characters at the end of a
+// string.
+var ChompFunc = function.New(&function.Spec{
+ Description: "Removes one or more newline characters from the end of the given string.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ newlines := regexp.MustCompile(`(?:\r\n?|\n)*\z`)
+ return cty.StringVal(newlines.ReplaceAllString(args[0].AsString(), "")), nil
+ },
+})
+
+// IndentFunc is a function that adds a given number of spaces to the
+// beginnings of all but the first line in a given multi-line string.
+var IndentFunc = function.New(&function.Spec{
+ Description: "Adds a given number of spaces after each newline character in the given string.",
+ Params: []function.Parameter{
+ {
+ Name: "spaces",
+ Description: "Number of spaces to add after each newline character.",
+ Type: cty.Number,
+ },
+ {
+ Name: "str",
+ Description: "The string to transform.",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ var spaces int
+ if err := gocty.FromCtyValue(args[0], &spaces); err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+ data := args[1].AsString()
+ pad := strings.Repeat(" ", spaces)
+ return cty.StringVal(strings.Replace(data, "\n", "\n"+pad, -1)), nil
+ },
+})
+
+// TitleFunc is a function that converts the first letter of each word in the
+// given string to uppercase.
+var TitleFunc = function.New(&function.Spec{
+ Description: "Replaces one letter after each non-letter and non-digit character with its uppercase equivalent.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return cty.StringVal(strings.Title(args[0].AsString())), nil
+ },
+})
+
+// TrimSpaceFunc is a function that removes any space characters from the start
+// and end of the given string.
+var TrimSpaceFunc = function.New(&function.Spec{
+ Description: "Removes any consecutive space characters (as defined by Unicode) from the start and end of the given string.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ return cty.StringVal(strings.TrimSpace(args[0].AsString())), nil
+ },
+})
+
+// TrimFunc is a function that removes the specified characters from the start
+// and end of the given string.
+var TrimFunc = function.New(&function.Spec{
+ Description: "Removes consecutive sequences of characters in \"cutset\" from the start and end of the given string.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Description: "The string to trim.",
+ Type: cty.String,
+ },
+ {
+ Name: "cutset",
+ Description: "A string containing all of the characters to trim. Each character is taken separately, so the order of characters is insignificant.",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ str := args[0].AsString()
+ cutset := args[1].AsString()
+ // NOTE: This doesn't properly handle any character that is encoded
+ // with multiple sequential code units, such as letters with
+ // combining diacritics and emoji modifier sequences.
+ return cty.StringVal(strings.Trim(str, cutset)), nil
+ },
+})
+
+// TrimPrefixFunc is a function that removes the specified characters from the
+// start the given string.
+var TrimPrefixFunc = function.New(&function.Spec{
+ Description: "Removes the given prefix from the start of the given string, if present.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Description: "The string to trim.",
+ Type: cty.String,
+ },
+ {
+ Name: "prefix",
+ Description: "The prefix to remove, if present.",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ str := args[0].AsString()
+ prefix := args[1].AsString()
+ return cty.StringVal(strings.TrimPrefix(str, prefix)), nil
+ },
+})
+
+// TrimSuffixFunc is a function that removes the specified characters from the
+// end of the given string.
+var TrimSuffixFunc = function.New(&function.Spec{
+ Description: "Removes the given suffix from the start of the given string, if present.",
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Description: "The string to trim.",
+ Type: cty.String,
+ },
+ {
+ Name: "suffix",
+ Description: "The suffix to remove, if present.",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ str := args[0].AsString()
+ cutset := args[1].AsString()
+ return cty.StringVal(strings.TrimSuffix(str, cutset)), nil
+ },
+})
+
+// Upper is a Function that converts a given string to uppercase.
+func Upper(str cty.Value) (cty.Value, error) {
+ return UpperFunc.Call([]cty.Value{str})
+}
+
+// Lower is a Function that converts a given string to lowercase.
+func Lower(str cty.Value) (cty.Value, error) {
+ return LowerFunc.Call([]cty.Value{str})
+}
+
+// Reverse is a Function that reverses the order of the characters in the
+// given string.
+//
+// As usual, "character" for the sake of this function is a grapheme cluster,
+// so combining diacritics (for example) will be considered together as a
+// single character.
+func Reverse(str cty.Value) (cty.Value, error) {
+ return ReverseFunc.Call([]cty.Value{str})
+}
+
+// Strlen is a Function that returns the length of the given string in
+// characters.
+//
+// As usual, "character" for the sake of this function is a grapheme cluster,
+// so combining diacritics (for example) will be considered together as a
+// single character.
+func Strlen(str cty.Value) (cty.Value, error) {
+ return StrlenFunc.Call([]cty.Value{str})
+}
+
+// Substr is a Function that extracts a sequence of characters from another
+// string and creates a new string.
+//
+// As usual, "character" for the sake of this function is a grapheme cluster,
+// so combining diacritics (for example) will be considered together as a
+// single character.
+//
+// The "offset" index may be negative, in which case it is relative to the
+// end of the given string.
+//
+// The "length" may be -1, in which case the remainder of the string after
+// the given offset will be returned.
+func Substr(str cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
+ return SubstrFunc.Call([]cty.Value{str, offset, length})
+}
+
+// Join concatenates together the string elements of one or more lists with a
+// given separator.
+func Join(sep cty.Value, lists ...cty.Value) (cty.Value, error) {
+ args := make([]cty.Value, len(lists)+1)
+ args[0] = sep
+ copy(args[1:], lists)
+ return JoinFunc.Call(args)
+}
+
+// Sort re-orders the elements of a given list of strings so that they are
+// in ascending lexicographical order.
+func Sort(list cty.Value) (cty.Value, error) {
+ return SortFunc.Call([]cty.Value{list})
+}
+
+// Split divides a given string by a given separator, returning a list of
+// strings containing the characters between the separator sequences.
+func Split(sep, str cty.Value) (cty.Value, error) {
+ return SplitFunc.Call([]cty.Value{sep, str})
+}
+
+// Chomp removes newline characters at the end of a string.
+func Chomp(str cty.Value) (cty.Value, error) {
+ return ChompFunc.Call([]cty.Value{str})
+}
+
+// Indent adds a given number of spaces to the beginnings of all but the first
+// line in a given multi-line string.
+func Indent(spaces, str cty.Value) (cty.Value, error) {
+ return IndentFunc.Call([]cty.Value{spaces, str})
+}
+
+// Title converts the first letter of each word in the given string to uppercase.
+func Title(str cty.Value) (cty.Value, error) {
+ return TitleFunc.Call([]cty.Value{str})
+}
+
+// TrimSpace removes any space characters from the start and end of the given string.
+func TrimSpace(str cty.Value) (cty.Value, error) {
+ return TrimSpaceFunc.Call([]cty.Value{str})
+}
+
+// Trim removes the specified characters from the start and end of the given string.
+func Trim(str, cutset cty.Value) (cty.Value, error) {
+ return TrimFunc.Call([]cty.Value{str, cutset})
+}
+
+// TrimPrefix removes the specified prefix from the start of the given string.
+func TrimPrefix(str, prefix cty.Value) (cty.Value, error) {
+ return TrimPrefixFunc.Call([]cty.Value{str, prefix})
+}
+
+// TrimSuffix removes the specified suffix from the end of the given string.
+func TrimSuffix(str, suffix cty.Value) (cty.Value, error) {
+ return TrimSuffixFunc.Call([]cty.Value{str, suffix})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go
new file mode 100644
index 00000000000..25a821bbf0c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go
@@ -0,0 +1,87 @@
+package stdlib
+
+import (
+ "regexp"
+ "strings"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// ReplaceFunc is a function that searches a given string for another given
+// substring, and replaces each occurence with a given replacement string.
+// The substr argument is a simple string.
+var ReplaceFunc = function.New(&function.Spec{
+ Description: `Replaces all instances of the given substring in the given string with the given replacement string.`,
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Description: `The string to search within.`,
+ Type: cty.String,
+ },
+ {
+ Name: "substr",
+ Description: `The substring to search for.`,
+ Type: cty.String,
+ },
+ {
+ Name: "replace",
+ Description: `The new substring to replace substr with.`,
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ str := args[0].AsString()
+ substr := args[1].AsString()
+ replace := args[2].AsString()
+
+ return cty.StringVal(strings.Replace(str, substr, replace, -1)), nil
+ },
+})
+
+// RegexReplaceFunc is a function that searches a given string for another
+// given substring, and replaces each occurence with a given replacement
+// string. The substr argument must be a valid regular expression.
+var RegexReplaceFunc = function.New(&function.Spec{
+ Description: `Applies the given regular expression pattern to the given string and replaces all matches with the given replacement string.`,
+ Params: []function.Parameter{
+ {
+ Name: "str",
+ Type: cty.String,
+ },
+ {
+ Name: "pattern",
+ Type: cty.String,
+ },
+ {
+ Name: "replace",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ RefineResult: refineNonNull,
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ str := args[0].AsString()
+ substr := args[1].AsString()
+ replace := args[2].AsString()
+
+ re, err := regexp.Compile(substr)
+ if err != nil {
+ return cty.UnknownVal(cty.String), err
+ }
+
+ return cty.StringVal(re.ReplaceAllString(str, replace)), nil
+ },
+})
+
+// Replace searches a given string for another given substring,
+// and replaces all occurrences with a given replacement string.
+func Replace(str, substr, replace cty.Value) (cty.Value, error) {
+ return ReplaceFunc.Call([]cty.Value{str, substr, replace})
+}
+
+func RegexReplace(str, substr, replace cty.Value) (cty.Value, error) {
+ return RegexReplaceFunc.Call([]cty.Value{str, substr, replace})
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go
new file mode 100644
index 00000000000..3495550af58
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go
@@ -0,0 +1,31 @@
+package function
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// Unpredictable wraps a given function such that it retains the same arguments
+// and type checking behavior but will return an unknown value when called.
+//
+// It is recommended that most functions be "pure", which is to say that they
+// will always produce the same value given particular input. However,
+// sometimes it is necessary to offer functions whose behavior depends on
+// some external state, such as reading a file or determining the current time.
+// In such cases, an unpredictable wrapper might be used to stand in for
+// the function during some sort of prior "checking" phase in order to delay
+// the actual effect until later.
+//
+// While Unpredictable can support a function that isn't pure in its
+// implementation, it still expects a function to be pure in its type checking
+// behavior, except for the special case of returning cty.DynamicPseudoType
+// if it is not yet able to predict its return value based on current argument
+// information.
+func Unpredictable(f Function) Function {
+ newSpec := *f.spec // shallow copy
+ newSpec.Impl = unpredictableImpl
+ return New(&newSpec)
+}
+
+func unpredictableImpl(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return cty.UnknownVal(retType), nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go
new file mode 100644
index 00000000000..a5177d22b27
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/doc.go
@@ -0,0 +1,7 @@
+// Package gocty deals with converting between cty Values and native go
+// values.
+//
+// It operates under a similar principle to the encoding/json and
+// encoding/xml packages in the standard library, using reflection to
+// populate native Go data structures from cty values and vice-versa.
+package gocty
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go
new file mode 100644
index 00000000000..c95d92a24d6
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go
@@ -0,0 +1,43 @@
+package gocty
+
+import (
+ "math/big"
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+var valueType = reflect.TypeOf(cty.Value{})
+var typeType = reflect.TypeOf(cty.Type{})
+
+var setType = reflect.TypeOf(set.Set[any]{})
+
+var bigFloatType = reflect.TypeOf(big.Float{})
+var bigIntType = reflect.TypeOf(big.Int{})
+
+var emptyInterfaceType = reflect.TypeOf(any(nil))
+
+var stringType = reflect.TypeOf("")
+
+// structTagIndices interrogates the fields of the given type (which must
+// be a struct type, or we'll panic) and returns a map from the cty
+// attribute names declared via struct tags to the indices of the
+// fields holding those tags.
+//
+// This function will panic if two fields within the struct are tagged with
+// the same cty attribute name.
+func structTagIndices(st reflect.Type) map[string]int {
+ ct := st.NumField()
+ ret := make(map[string]int, ct)
+
+ for i := 0; i < ct; i++ {
+ field := st.Field(i)
+ attrName := field.Tag.Get("cty")
+ if attrName != "" {
+ ret[attrName] = i
+ }
+ }
+
+ return ret
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/in.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
new file mode 100644
index 00000000000..72aac4c5a87
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/in.go
@@ -0,0 +1,548 @@
+package gocty
+
+import (
+ "math/big"
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// ToCtyValue produces a cty.Value from a Go value. The result will conform
+// to the given type, or an error will be returned if this is not possible.
+//
+// The target type serves as a hint to resolve ambiguities in the mapping.
+// For example, the Go type set.Set tells us that the value is a set but
+// does not describe the set's element type. This also allows for convenient
+// conversions, such as populating a set from a slice rather than having to
+// first explicitly instantiate a set.Set.
+//
+// The audience of this function is assumed to be the developers of Go code
+// that is integrating with cty, and thus the error messages it returns are
+// presented from Go's perspective. These messages are thus not appropriate
+// for display to end-users. An error returned from ToCtyValue represents a
+// bug in the calling program, not user error.
+func ToCtyValue(val any, ty cty.Type) (cty.Value, error) {
+ // 'path' starts off as empty but will grow for each level of recursive
+ // call we make, so by the time toCtyValue returns it is likely to have
+ // unused capacity on the end of it, depending on how deeply-recursive
+ // the given Type is.
+ path := make(cty.Path, 0)
+ return toCtyValue(reflect.ValueOf(val), ty, path)
+}
+
+func toCtyValue(val reflect.Value, ty cty.Type, path cty.Path) (cty.Value, error) {
+ if val != (reflect.Value{}) && val.Type().AssignableTo(valueType) {
+ // If the source value is a cty.Value then we'll try to just pass
+ // through to the target type directly.
+ return toCtyPassthrough(val, ty, path)
+ }
+
+ switch ty {
+ case cty.Bool:
+ return toCtyBool(val, path)
+ case cty.Number:
+ return toCtyNumber(val, path)
+ case cty.String:
+ return toCtyString(val, path)
+ case cty.DynamicPseudoType:
+ return toCtyDynamic(val, path)
+ }
+
+ switch {
+ case ty.IsListType():
+ return toCtyList(val, ty.ElementType(), path)
+ case ty.IsMapType():
+ return toCtyMap(val, ty.ElementType(), path)
+ case ty.IsSetType():
+ return toCtySet(val, ty.ElementType(), path)
+ case ty.IsObjectType():
+ return toCtyObject(val, ty.AttributeTypes(), path)
+ case ty.IsTupleType():
+ return toCtyTuple(val, ty.TupleElementTypes(), path)
+ case ty.IsCapsuleType():
+ return toCtyCapsule(val, ty, path)
+ }
+
+ // We should never fall out here
+ return cty.NilVal, path.NewErrorf("unsupported target type %#v", ty)
+}
+
+func toCtyBool(val reflect.Value, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.Bool), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Bool:
+ return cty.BoolVal(val.Bool()), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to bool", val.Kind())
+
+ }
+
+}
+
+func toCtyNumber(val reflect.Value, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.Number), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return cty.NumberIntVal(val.Int()), nil
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return cty.NumberUIntVal(val.Uint()), nil
+
+ case reflect.Float32, reflect.Float64:
+ return cty.NumberFloatVal(val.Float()), nil
+
+ case reflect.Struct:
+ if val.Type().AssignableTo(bigIntType) {
+ bigInt := val.Interface().(big.Int)
+ bigFloat := (&big.Float{}).SetInt(&bigInt)
+ val = reflect.ValueOf(*bigFloat)
+ }
+
+ if val.Type().AssignableTo(bigFloatType) {
+ bigFloat := val.Interface().(big.Float)
+ return cty.NumberVal(&bigFloat), nil
+ }
+
+ fallthrough
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to number", val.Kind())
+
+ }
+
+}
+
+func toCtyString(val reflect.Value, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.String), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.String:
+ return cty.StringVal(val.String()), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to string", val.Kind())
+
+ }
+
+}
+
+func toCtyList(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.List(ety)), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Slice:
+ if val.IsNil() {
+ return cty.NullVal(cty.List(ety)), nil
+ }
+ fallthrough
+ case reflect.Array:
+ if val.Len() == 0 {
+ return cty.ListValEmpty(ety), nil
+ }
+
+ // While we work on our elements we'll temporarily grow
+ // path to give us a place to put our index step.
+ path = append(path, cty.PathStep(nil))
+
+ vals := make([]cty.Value, val.Len())
+ for i := range vals {
+ var err error
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+ vals[i], err = toCtyValue(val.Index(i), ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ // Discard our extra path segment, retaining it as extra capacity
+ // for future appending to the path.
+ path = path[:len(path)-1]
+
+ return cty.ListVal(vals), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.List(ety))
+
+ }
+}
+
+func toCtyMap(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.Map(ety)), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Map:
+ if val.IsNil() {
+ return cty.NullVal(cty.Map(ety)), nil
+ }
+
+ if val.Len() == 0 {
+ return cty.MapValEmpty(ety), nil
+ }
+
+ keyType := val.Type().Key()
+ if keyType.Kind() != reflect.String {
+ return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType)
+ }
+
+ // While we work on our elements we'll temporarily grow
+ // path to give us a place to put our index step.
+ path = append(path, cty.PathStep(nil))
+
+ vals := make(map[string]cty.Value, val.Len())
+ for _, kv := range val.MapKeys() {
+ k := kv.String()
+ var err error
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.StringVal(k),
+ }
+ vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ // Discard our extra path segment, retaining it as extra capacity
+ // for future appending to the path.
+ path = path[:len(path)-1]
+
+ return cty.MapVal(vals), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Map(ety))
+
+ }
+}
+
+func toCtySet(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.Set(ety)), nil
+ }
+
+ var vals []cty.Value
+
+ switch val.Kind() {
+
+ case reflect.Slice:
+ if val.IsNil() {
+ return cty.NullVal(cty.Set(ety)), nil
+ }
+ fallthrough
+ case reflect.Array:
+ if val.Len() == 0 {
+ return cty.SetValEmpty(ety), nil
+ }
+
+ vals = make([]cty.Value, val.Len())
+ for i := range vals {
+ var err error
+ vals[i], err = toCtyValue(val.Index(i), ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ case reflect.Struct:
+
+ if !val.Type().AssignableTo(setType) {
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Type(), cty.Set(ety))
+ }
+
+ rawSet := val.Interface().(set.Set[any])
+ inVals := rawSet.Values()
+
+ if len(inVals) == 0 {
+ return cty.SetValEmpty(ety), nil
+ }
+
+ vals = make([]cty.Value, len(inVals))
+ for i := range inVals {
+ var err error
+ vals[i], err = toCtyValue(reflect.ValueOf(inVals[i]), ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Set(ety))
+
+ }
+
+ return cty.SetVal(vals), nil
+}
+
+func toCtyObject(val reflect.Value, attrTypes map[string]cty.Type, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.Object(attrTypes)), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Map:
+ if val.IsNil() {
+ return cty.NullVal(cty.Object(attrTypes)), nil
+ }
+
+ keyType := val.Type().Key()
+ if keyType.Kind() != reflect.String {
+ return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType)
+ }
+
+ if len(attrTypes) == 0 {
+ return cty.EmptyObjectVal, nil
+ }
+
+ // While we work on our elements we'll temporarily grow
+ // path to give us a place to put our GetAttr step.
+ path = append(path, cty.PathStep(nil))
+
+ haveKeys := make(map[string]struct{}, val.Len())
+ for _, kv := range val.MapKeys() {
+ haveKeys[kv.String()] = struct{}{}
+ }
+
+ vals := make(map[string]cty.Value, len(attrTypes))
+ for k, at := range attrTypes {
+ var err error
+ path[len(path)-1] = cty.GetAttrStep{
+ Name: k,
+ }
+
+ if _, have := haveKeys[k]; !have {
+ vals[k] = cty.NullVal(at)
+ continue
+ }
+
+ vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), at, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ // Discard our extra path segment, retaining it as extra capacity
+ // for future appending to the path.
+ path = path[:len(path)-1]
+
+ return cty.ObjectVal(vals), nil
+
+ case reflect.Struct:
+ if len(attrTypes) == 0 {
+ return cty.EmptyObjectVal, nil
+ }
+
+ // While we work on our elements we'll temporarily grow
+ // path to give us a place to put our GetAttr step.
+ path = append(path, cty.PathStep(nil))
+
+ attrFields := structTagIndices(val.Type())
+
+ vals := make(map[string]cty.Value, len(attrTypes))
+ for k, at := range attrTypes {
+ path[len(path)-1] = cty.GetAttrStep{
+ Name: k,
+ }
+
+ if fieldIdx, have := attrFields[k]; have {
+ var err error
+ vals[k], err = toCtyValue(val.Field(fieldIdx), at, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ } else {
+ vals[k] = cty.NullVal(at)
+ }
+ }
+
+ // Discard our extra path segment, retaining it as extra capacity
+ // for future appending to the path.
+ path = path[:len(path)-1]
+
+ return cty.ObjectVal(vals), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Object(attrTypes))
+
+ }
+}
+
+func toCtyTuple(val reflect.Value, elemTypes []cty.Type, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.Tuple(elemTypes)), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Slice:
+ if val.IsNil() {
+ return cty.NullVal(cty.Tuple(elemTypes)), nil
+ }
+
+ if val.Len() != len(elemTypes) {
+ return cty.NilVal, path.NewErrorf("wrong number of elements %d; need %d", val.Len(), len(elemTypes))
+ }
+
+ if len(elemTypes) == 0 {
+ return cty.EmptyTupleVal, nil
+ }
+
+ // While we work on our elements we'll temporarily grow
+ // path to give us a place to put our Index step.
+ path = append(path, cty.PathStep(nil))
+
+ vals := make([]cty.Value, len(elemTypes))
+ for i, ety := range elemTypes {
+ var err error
+
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+
+ vals[i], err = toCtyValue(val.Index(i), ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ // Discard our extra path segment, retaining it as extra capacity
+ // for future appending to the path.
+ path = path[:len(path)-1]
+
+ return cty.TupleVal(vals), nil
+
+ case reflect.Struct:
+ fieldCount := val.Type().NumField()
+ if fieldCount != len(elemTypes) {
+ return cty.NilVal, path.NewErrorf("wrong number of struct fields %d; need %d", fieldCount, len(elemTypes))
+ }
+
+ if len(elemTypes) == 0 {
+ return cty.EmptyTupleVal, nil
+ }
+
+ // While we work on our elements we'll temporarily grow
+ // path to give us a place to put our Index step.
+ path = append(path, cty.PathStep(nil))
+
+ vals := make([]cty.Value, len(elemTypes))
+ for i, ety := range elemTypes {
+ var err error
+
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+
+ vals[i], err = toCtyValue(val.Field(i), ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ }
+
+ // Discard our extra path segment, retaining it as extra capacity
+ // for future appending to the path.
+ path = path[:len(path)-1]
+
+ return cty.TupleVal(vals), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Tuple(elemTypes))
+
+ }
+}
+
+func toCtyCapsule(val reflect.Value, capsuleType cty.Type, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(capsuleType), nil
+ }
+
+ if val.Kind() != reflect.Ptr {
+ if !val.CanAddr() {
+ return cty.NilVal, path.NewErrorf("source value for capsule %#v must be addressable", capsuleType)
+ }
+
+ val = val.Addr()
+ }
+
+ if !val.Type().Elem().AssignableTo(capsuleType.EncapsulatedType()) {
+ return cty.NilVal, path.NewErrorf("value of type %T not compatible with capsule %#v", val.Interface(), capsuleType)
+ }
+
+ return cty.CapsuleVal(capsuleType, val.Interface()), nil
+}
+
+func toCtyDynamic(val reflect.Value, path cty.Path) (cty.Value, error) {
+ if val = toCtyUnwrapPointer(val); !val.IsValid() {
+ return cty.NullVal(cty.DynamicPseudoType), nil
+ }
+
+ switch val.Kind() {
+
+ case reflect.Struct:
+ if !val.Type().AssignableTo(valueType) {
+ return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Type())
+ }
+
+ return val.Interface().(cty.Value), nil
+
+ default:
+ return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Kind())
+
+ }
+
+}
+
+func toCtyPassthrough(wrappedVal reflect.Value, wantTy cty.Type, path cty.Path) (cty.Value, error) {
+ if wrappedVal = toCtyUnwrapPointer(wrappedVal); !wrappedVal.IsValid() {
+ return cty.NullVal(wantTy), nil
+ }
+
+ givenVal := wrappedVal.Interface().(cty.Value)
+
+ val, err := convert.Convert(givenVal, wantTy)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("unsuitable value: %s", err)
+ }
+ return val, nil
+}
+
+// toCtyUnwrapPointer is a helper for dealing with Go pointers. It has three
+// possible outcomes:
+//
+// - Given value isn't a pointer, so it's just returned as-is.
+// - Given value is a non-nil pointer, in which case it is dereferenced
+// and the result returned.
+// - Given value is a nil pointer, in which case an invalid value is returned.
+//
+// For nested pointer types, like **int, they are all dereferenced in turn
+// until a non-pointer value is found, or until a nil pointer is encountered.
+func toCtyUnwrapPointer(val reflect.Value) reflect.Value {
+ for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
+ if val.IsNil() {
+ return reflect.Value{}
+ }
+
+ val = val.Elem()
+ }
+
+ return val
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/out.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
new file mode 100644
index 00000000000..b7588ee0c16
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/out.go
@@ -0,0 +1,686 @@
+package gocty
+
+import (
+ "math"
+ "math/big"
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FromCtyValue assigns a cty.Value to a reflect.Value, which must be a pointer,
+// using a fixed set of conversion rules.
+//
+// This function considers its audience to be the creator of the cty Value
+// given, and thus the error messages it generates are (unlike with ToCtyValue)
+// presented in cty terminology that is generally appropriate to return to
+// end-users in applications where cty data structures are built from
+// user-provided configuration. In particular this means that if incorrect
+// target types are provided by the calling application the resulting error
+// messages are likely to be confusing, since we assume that the given target
+// type is correct and the cty.Value is where the error lies.
+//
+// If an error is returned, the target data structure may have been partially
+// populated, but the degree to which this is true is an implementation
+// detail that the calling application should not rely on.
+//
+// The function will panic if given a non-pointer as the Go value target,
+// since that is considered to be a bug in the calling program.
+func FromCtyValue(val cty.Value, target any) error {
+ tVal := reflect.ValueOf(target)
+ if tVal.Kind() != reflect.Ptr {
+ panic("target value is not a pointer")
+ }
+ if tVal.IsNil() {
+ panic("target value is nil pointer")
+ }
+
+ // 'path' starts off as empty but will grow for each level of recursive
+ // call we make, so by the time fromCtyValue returns it is likely to have
+ // unused capacity on the end of it, depending on how deeply-recursive
+ // the given cty.Value is.
+ path := make(cty.Path, 0)
+ return fromCtyValue(val, tVal, path)
+}
+
+func fromCtyValue(val cty.Value, target reflect.Value, path cty.Path) error {
+ ty := val.Type()
+
+ deepTarget := fromCtyPopulatePtr(target, false)
+
+ // If we're decoding into a cty.Value then we just pass through the
+ // value as-is, to enable partial decoding. This is the only situation
+ // where unknown values are permitted.
+ if deepTarget.Kind() == reflect.Struct && deepTarget.Type().AssignableTo(valueType) {
+ deepTarget.Set(reflect.ValueOf(val))
+ return nil
+ }
+
+ // Lists and maps can be nil without indirection, but everything else
+ // requires a pointer and we set it immediately to nil.
+ // We also make an exception for capsule types because we want to handle
+ // pointers specially for these.
+ // (fromCtyList and fromCtyMap must therefore deal with val.IsNull, while
+ // other types can assume no nulls after this point.)
+ if val.IsNull() && !val.Type().IsListType() && !val.Type().IsMapType() && !val.Type().IsCapsuleType() {
+ target = fromCtyPopulatePtr(target, true)
+ if target.Kind() != reflect.Ptr {
+ return path.NewErrorf("null value is not allowed")
+ }
+
+ target.Set(reflect.Zero(target.Type()))
+ return nil
+ }
+
+ target = deepTarget
+
+ if !val.IsKnown() {
+ return path.NewErrorf("value must be known")
+ }
+
+ switch ty {
+ case cty.Bool:
+ return fromCtyBool(val, target, path)
+ case cty.Number:
+ return fromCtyNumber(val, target, path)
+ case cty.String:
+ return fromCtyString(val, target, path)
+ }
+
+ switch {
+ case ty.IsListType():
+ return fromCtyList(val, target, path)
+ case ty.IsMapType():
+ return fromCtyMap(val, target, path)
+ case ty.IsSetType():
+ return fromCtySet(val, target, path)
+ case ty.IsObjectType():
+ return fromCtyObject(val, target, path)
+ case ty.IsTupleType():
+ return fromCtyTuple(val, target, path)
+ case ty.IsCapsuleType():
+ return fromCtyCapsule(val, target, path)
+ }
+
+ // We should never fall out here; reaching here indicates a bug in this
+ // function.
+ return path.NewErrorf("unsupported source type %#v", ty)
+}
+
+func fromCtyBool(val cty.Value, target reflect.Value, path cty.Path) error {
+ switch target.Kind() {
+
+ case reflect.Bool:
+ target.SetBool(val.True())
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyNumber(val cty.Value, target reflect.Value, path cty.Path) error {
+ bf := val.AsBigFloat()
+
+ switch target.Kind() {
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return fromCtyNumberInt(bf, target, path)
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return fromCtyNumberUInt(bf, target, path)
+
+ case reflect.Float32, reflect.Float64:
+ return fromCtyNumberFloat(bf, target, path)
+
+ case reflect.Struct:
+ return fromCtyNumberBig(bf, target, path)
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyNumberInt(bf *big.Float, target reflect.Value, path cty.Path) error {
+ // Doing this with switch rather than << arithmetic because << with
+ // result >32-bits is not portable to 32-bit systems.
+ var min int64
+ var max int64
+ switch target.Type().Bits() {
+ case 8:
+ min = math.MinInt8
+ max = math.MaxInt8
+ case 16:
+ min = math.MinInt16
+ max = math.MaxInt16
+ case 32:
+ min = math.MinInt32
+ max = math.MaxInt32
+ case 64:
+ min = math.MinInt64
+ max = math.MaxInt64
+ default:
+ panic("weird number of bits in target int")
+ }
+
+ iv, accuracy := bf.Int64()
+ if accuracy != big.Exact || iv < min || iv > max {
+ return path.NewErrorf("value must be a whole number, between %d and %d", min, max)
+ }
+
+ target.SetInt(iv)
+ return nil
+}
+
+func fromCtyNumberUInt(bf *big.Float, target reflect.Value, path cty.Path) error {
+ // Doing this with switch rather than << arithmetic because << with
+ // result >32-bits is not portable to 32-bit systems.
+ var max uint64
+ switch target.Type().Bits() {
+ case 8:
+ max = math.MaxUint8
+ case 16:
+ max = math.MaxUint16
+ case 32:
+ max = math.MaxUint32
+ case 64:
+ max = math.MaxUint64
+ default:
+ panic("weird number of bits in target uint")
+ }
+
+ iv, accuracy := bf.Uint64()
+ if accuracy != big.Exact || iv > max {
+ return path.NewErrorf("value must be a whole number, between 0 and %d inclusive", max)
+ }
+
+ target.SetUint(iv)
+ return nil
+}
+
+func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) error {
+ switch target.Kind() {
+ case reflect.Float32, reflect.Float64:
+ fv, accuracy := bf.Float64()
+ if accuracy != big.Exact {
+ // We allow the precision to be truncated as part of our conversion,
+ // but we don't want to silently introduce infinities.
+ if math.IsInf(fv, 0) {
+ return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat64, math.MaxFloat64)
+ }
+ }
+ target.SetFloat(fv)
+ return nil
+ default:
+ panic("unsupported kind of float")
+ }
+}
+
+func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error {
+ switch {
+
+ case bigFloatType.ConvertibleTo(target.Type()):
+ // Easy!
+ target.Set(reflect.ValueOf(bf).Elem().Convert(target.Type()))
+ return nil
+
+ case bigIntType.ConvertibleTo(target.Type()):
+ bi, accuracy := bf.Int(nil)
+ if accuracy != big.Exact {
+ return path.NewErrorf("value must be a whole number")
+ }
+ target.Set(reflect.ValueOf(bi).Elem().Convert(target.Type()))
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+ }
+}
+
+func fromCtyString(val cty.Value, target reflect.Value, path cty.Path) error {
+ switch target.Kind() {
+ case reflect.String:
+ target.SetString(val.AsString())
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyList(val cty.Value, target reflect.Value, path cty.Path) error {
+ switch target.Kind() {
+
+ case reflect.Slice:
+ if val.IsNull() {
+ target.Set(reflect.Zero(target.Type()))
+ return nil
+ }
+
+ length := val.LengthInt()
+ tv := reflect.MakeSlice(target.Type(), length, length)
+
+ path = append(path, nil)
+
+ i := 0
+ var err error
+ val.ForEachElement(func(key cty.Value, val cty.Value) bool {
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+
+ targetElem := tv.Index(i)
+ err = fromCtyValue(val, targetElem, path)
+ if err != nil {
+ return true
+ }
+
+ i++
+ return false
+ })
+ if err != nil {
+ return err
+ }
+
+ path = path[:len(path)-1]
+
+ target.Set(tv)
+ return nil
+
+ case reflect.Array:
+ if val.IsNull() {
+ return path.NewErrorf("null value is not allowed")
+ }
+
+ length := val.LengthInt()
+ if length != target.Len() {
+ return path.NewErrorf("must be a list of length %d", target.Len())
+ }
+
+ path = append(path, nil)
+
+ i := 0
+ var err error
+ val.ForEachElement(func(key cty.Value, val cty.Value) bool {
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+
+ targetElem := target.Index(i)
+ err = fromCtyValue(val, targetElem, path)
+ if err != nil {
+ return true
+ }
+
+ i++
+ return false
+ })
+ if err != nil {
+ return err
+ }
+
+ path = path[:len(path)-1]
+
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyMap(val cty.Value, target reflect.Value, path cty.Path) error {
+
+ switch target.Kind() {
+
+ case reflect.Map:
+ if val.IsNull() {
+ target.Set(reflect.Zero(target.Type()))
+ return nil
+ }
+
+ tv := reflect.MakeMap(target.Type())
+ et := target.Type().Elem()
+
+ path = append(path, nil)
+
+ var err error
+ val.ForEachElement(func(key cty.Value, val cty.Value) bool {
+ path[len(path)-1] = cty.IndexStep{
+ Key: key,
+ }
+
+ ks := key.AsString()
+
+ targetElem := reflect.New(et)
+ err = fromCtyValue(val, targetElem, path)
+
+ tv.SetMapIndex(reflect.ValueOf(ks), targetElem.Elem())
+
+ return err != nil
+ })
+ if err != nil {
+ return err
+ }
+
+ path = path[:len(path)-1]
+
+ target.Set(tv)
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtySet(val cty.Value, target reflect.Value, path cty.Path) error {
+ switch target.Kind() {
+
+ case reflect.Slice:
+ if val.IsNull() {
+ target.Set(reflect.Zero(target.Type()))
+ return nil
+ }
+
+ length := val.LengthInt()
+ tv := reflect.MakeSlice(target.Type(), length, length)
+
+ i := 0
+ var err error
+ val.ForEachElement(func(key cty.Value, val cty.Value) bool {
+ targetElem := tv.Index(i)
+ err = fromCtyValue(val, targetElem, path)
+ if err != nil {
+ return true
+ }
+
+ i++
+ return false
+ })
+ if err != nil {
+ return err
+ }
+
+ target.Set(tv)
+ return nil
+
+ case reflect.Array:
+ if val.IsNull() {
+ return path.NewErrorf("null value is not allowed")
+ }
+
+ length := val.LengthInt()
+ if length != target.Len() {
+ return path.NewErrorf("must be a set of length %d", target.Len())
+ }
+
+ i := 0
+ var err error
+ val.ForEachElement(func(key cty.Value, val cty.Value) bool {
+ targetElem := target.Index(i)
+ err = fromCtyValue(val, targetElem, path)
+ if err != nil {
+ return true
+ }
+
+ i++
+ return false
+ })
+ if err != nil {
+ return err
+ }
+
+ return nil
+
+ // TODO: decode into set.Set instance
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyObject(val cty.Value, target reflect.Value, path cty.Path) error {
+
+ switch target.Kind() {
+
+ case reflect.Struct:
+
+ attrTypes := val.Type().AttributeTypes()
+ targetFields := structTagIndices(target.Type())
+
+ path = append(path, nil)
+
+ for k, i := range targetFields {
+ if _, exists := attrTypes[k]; !exists {
+ // If the field in question isn't able to represent nil,
+ // that's an error.
+ fk := target.Field(i).Kind()
+ switch fk {
+ case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
+ // okay
+ default:
+ return path.NewErrorf("missing required attribute %q", k)
+ }
+ }
+ }
+
+ for k := range attrTypes {
+ path[len(path)-1] = cty.GetAttrStep{
+ Name: k,
+ }
+
+ fieldIdx, exists := targetFields[k]
+ if !exists {
+ return path.NewErrorf("unsupported attribute %q", k)
+ }
+
+ ev := val.GetAttr(k)
+
+ targetField := target.Field(fieldIdx)
+ err := fromCtyValue(ev, targetField, path)
+ if err != nil {
+ return err
+ }
+ }
+
+ path = path[:len(path)-1]
+
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyTuple(val cty.Value, target reflect.Value, path cty.Path) error {
+
+ switch target.Kind() {
+
+ case reflect.Struct:
+
+ elemTypes := val.Type().TupleElementTypes()
+ fieldCount := target.Type().NumField()
+
+ if fieldCount != len(elemTypes) {
+ return path.NewErrorf("a tuple of %d elements is required", fieldCount)
+ }
+
+ path = append(path, nil)
+
+ for i := range elemTypes {
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(i)),
+ }
+
+ ev := val.Index(cty.NumberIntVal(int64(i)))
+
+ targetField := target.Field(i)
+ err := fromCtyValue(ev, targetField, path)
+ if err != nil {
+ return err
+ }
+ }
+
+ path = path[:len(path)-1]
+
+ return nil
+
+ default:
+ return likelyRequiredTypesError(path, target)
+
+ }
+}
+
+func fromCtyCapsule(val cty.Value, target reflect.Value, path cty.Path) error {
+
+ if target.Kind() == reflect.Ptr {
+ // Walk through indirection until we get to the last pointer,
+ // which we might set to null below.
+ target = fromCtyPopulatePtr(target, true)
+
+ if val.IsNull() {
+ target.Set(reflect.Zero(target.Type()))
+ return nil
+ }
+
+ // Since a capsule contains a pointer to an object, we'll preserve
+ // that pointer on the way out and thus allow the caller to recover
+ // the original object, rather than a copy of it.
+
+ eType := val.Type().EncapsulatedType()
+
+ if !eType.AssignableTo(target.Elem().Type()) {
+ // Our interface contract promises that we won't expose Go
+ // implementation details in error messages, so we need to keep
+ // this vague. This can only arise if a calling application has
+ // more than one capsule type in play and a user mixes them up.
+ return path.NewErrorf("incorrect type %s", val.Type().FriendlyName())
+ }
+
+ target.Set(reflect.ValueOf(val.EncapsulatedValue()))
+
+ return nil
+ } else {
+ if val.IsNull() {
+ return path.NewErrorf("null value is not allowed")
+ }
+
+ // If our target isn't a pointer then we will attempt to copy
+ // the encapsulated value into it.
+
+ eType := val.Type().EncapsulatedType()
+
+ if !eType.AssignableTo(target.Type()) {
+ // Our interface contract promises that we won't expose Go
+ // implementation details in error messages, so we need to keep
+ // this vague. This can only arise if a calling application has
+ // more than one capsule type in play and a user mixes them up.
+ return path.NewErrorf("incorrect type %s", val.Type().FriendlyName())
+ }
+
+ // We know that EncapsulatedValue is always a pointer, so we
+ // can safely call .Elem on its reflect.Value.
+ target.Set(reflect.ValueOf(val.EncapsulatedValue()).Elem())
+
+ return nil
+ }
+
+}
+
+// fromCtyPopulatePtr recognizes when target is a pointer type and allocates
+// a value to assign to that pointer, which it returns.
+//
+// If the given value has multiple levels of indirection, like **int, these
+// will be processed in turn so that the return value is guaranteed to be
+// a non-pointer.
+//
+// As an exception, if decodingNull is true then the returned value will be
+// the final level of pointer, if any, so that the caller can assign it
+// as nil to represent a null value. If the given target value is not a pointer
+// at all then the returned value will be just the given target, so the caller
+// must test if the returned value is a pointer before trying to assign nil
+// to it.
+func fromCtyPopulatePtr(target reflect.Value, decodingNull bool) reflect.Value {
+ for {
+ if target.Kind() == reflect.Interface && !target.IsNil() {
+ e := target.Elem()
+ if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
+ target = e
+ }
+ }
+
+ if target.Kind() != reflect.Ptr {
+ break
+ }
+
+ // Stop early if we're decodingNull and we've found our last indirection
+ if target.Elem().Kind() != reflect.Ptr && decodingNull && target.CanSet() {
+ break
+ }
+
+ if target.IsNil() {
+ target.Set(reflect.New(target.Type().Elem()))
+ }
+
+ target = target.Elem()
+ }
+ return target
+}
+
+// likelyRequiredTypesError returns an error that states which types are
+// acceptable by making some assumptions about what types we support for
+// each target Go kind. It's not a precise science but it allows us to return
+// an error message that is cty-user-oriented rather than Go-oriented.
+//
+// Generally these error messages should be a matter of last resort, since
+// the calling application should be validating user-provided value types
+// before decoding anyway.
+func likelyRequiredTypesError(path cty.Path, target reflect.Value) error {
+ switch target.Kind() {
+
+ case reflect.Bool:
+ return path.NewErrorf("bool value is required")
+
+ case reflect.String:
+ return path.NewErrorf("string value is required")
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ fallthrough
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ fallthrough
+ case reflect.Float32, reflect.Float64:
+ return path.NewErrorf("number value is required")
+
+ case reflect.Slice, reflect.Array:
+ return path.NewErrorf("list or set value is required")
+
+ case reflect.Map:
+ return path.NewErrorf("map or object value is required")
+
+ case reflect.Struct:
+ switch {
+
+ case target.Type().AssignableTo(bigFloatType) || target.Type().AssignableTo(bigIntType):
+ return path.NewErrorf("number value is required")
+
+ case target.Type().AssignableTo(setType):
+ return path.NewErrorf("set or list value is required")
+
+ default:
+ return path.NewErrorf("object or tuple value is required")
+
+ }
+
+ default:
+ // We should avoid getting into this path, since this error
+ // message is rather useless.
+ return path.NewErrorf("incorrect type")
+
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go
new file mode 100644
index 00000000000..14bbe14303f
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go
@@ -0,0 +1,108 @@
+package gocty
+
+import (
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// ImpliedType takes an arbitrary Go value (as an any) and attempts
+// to find a suitable cty.Type instance that could be used for a conversion
+// with ToCtyValue.
+//
+// This allows -- for simple situations at least -- types to be defined just
+// once in Go and the cty types derived from the Go types, but in the process
+// it makes some assumptions that may be undesirable so applications are
+// encouraged to build their cty types directly if exacting control is
+// required.
+//
+// Not all Go types can be represented as cty types, so an error may be
+// returned which is usually considered to be a bug in the calling program.
+// In particular, ImpliedType will never use capsule types in its returned
+// type, because it cannot know the capsule types supported by the calling
+// program.
+func ImpliedType(gv any) (cty.Type, error) {
+ rt := reflect.TypeOf(gv)
+ var path cty.Path
+ return impliedType(rt, path)
+}
+
+func impliedType(rt reflect.Type, path cty.Path) (cty.Type, error) {
+ switch rt.Kind() {
+
+ case reflect.Ptr:
+ return impliedType(rt.Elem(), path)
+
+ // Primitive types
+ case reflect.Bool:
+ return cty.Bool, nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return cty.Number, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return cty.Number, nil
+ case reflect.Float32, reflect.Float64:
+ return cty.Number, nil
+ case reflect.String:
+ return cty.String, nil
+
+ // Collection types
+ case reflect.Slice:
+ path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.Number)})
+ ety, err := impliedType(rt.Elem(), path)
+ if err != nil {
+ return cty.NilType, err
+ }
+ return cty.List(ety), nil
+ case reflect.Map:
+ if !stringType.AssignableTo(rt.Key()) {
+ return cty.NilType, path.NewErrorf("no cty.Type for %s (must have string keys)", rt)
+ }
+ path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.String)})
+ ety, err := impliedType(rt.Elem(), path)
+ if err != nil {
+ return cty.NilType, err
+ }
+ return cty.Map(ety), nil
+
+ // Structural types
+ case reflect.Struct:
+ return impliedStructType(rt, path)
+
+ default:
+ return cty.NilType, path.NewErrorf("no cty.Type for %s", rt)
+ }
+}
+
+func impliedStructType(rt reflect.Type, path cty.Path) (cty.Type, error) {
+ if valueType.AssignableTo(rt) {
+ // Special case: cty.Value represents cty.DynamicPseudoType, for
+ // type conformance checking.
+ return cty.DynamicPseudoType, nil
+ }
+
+ fieldIdxs := structTagIndices(rt)
+ if len(fieldIdxs) == 0 {
+ return cty.NilType, path.NewErrorf("no cty.Type for %s (no cty field tags)", rt)
+ }
+
+ atys := make(map[string]cty.Type, len(fieldIdxs))
+
+ {
+ // Temporary extension of path for attributes
+ path := append(path, nil)
+
+ for k, fi := range fieldIdxs {
+ path[len(path)-1] = cty.GetAttrStep{Name: k}
+
+ ft := rt.Field(fi).Type
+ aty, err := impliedType(ft, path)
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ atys[k] = aty
+ }
+ }
+
+ return cty.Object(atys), nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/helper.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/helper.go
new file mode 100644
index 00000000000..c342f13cba3
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/helper.go
@@ -0,0 +1,99 @@
+package cty
+
+import (
+ "fmt"
+)
+
+// anyUnknown is a helper to easily check if a set of values contains any
+// unknowns, for operations that short-circuit to return unknown in that case.
+func anyUnknown(values ...Value) bool {
+ for _, val := range values {
+ if _, unknown := val.v.(*unknownType); unknown {
+ return true
+ }
+ }
+ return false
+}
+
+// typeCheck tests whether all of the given values belong to the given type.
+// If the given types are a mixture of the given type and the dynamic
+// pseudo-type then a short-circuit dynamic value is returned. If the given
+// values are all of the correct type but at least one is unknown then
+// a short-circuit unknown value is returned. If any other types appear then
+// an error is returned. Otherwise (finally!) the result is nil, nil.
+func typeCheck(required Type, ret Type, values ...Value) (shortCircuit *Value, err error) {
+ hasDynamic := false
+ hasUnknown := false
+
+ for i, val := range values {
+ if val.ty == DynamicPseudoType {
+ hasDynamic = true
+ continue
+ }
+
+ if !val.Type().Equals(required) {
+ return nil, fmt.Errorf(
+ "type mismatch: want %s but value %d is %s",
+ required.FriendlyName(),
+ i, val.ty.FriendlyName(),
+ )
+ }
+
+ if _, unknown := val.v.(*unknownType); unknown {
+ hasUnknown = true
+ }
+ }
+
+ if hasDynamic {
+ return &DynamicVal, nil
+ }
+
+ if hasUnknown {
+ ret := UnknownVal(ret)
+ return &ret, nil
+ }
+
+ return nil, nil
+}
+
+// mustTypeCheck is a wrapper around typeCheck that immediately panics if
+// any error is returned.
+func mustTypeCheck(required Type, ret Type, values ...Value) *Value {
+ shortCircuit, err := typeCheck(required, ret, values...)
+ if err != nil {
+ panic(err)
+ }
+ return shortCircuit
+}
+
+// shortCircuitForceType takes the return value from mustTypeCheck and
+// replaces it with an unknown of the given type if the original value was
+// DynamicVal.
+//
+// This is useful for operations that are specified to always return a
+// particular type, since then a dynamic result can safely be "upgrade" to
+// a strongly-typed unknown, which then allows subsequent operations to
+// be actually type-checked.
+//
+// It is safe to use this only if the operation in question is defined as
+// returning either a value of the given type or panicking, since we know
+// then that subsequent operations won't run if the operation panics.
+//
+// If the given short-circuit value is *not* DynamicVal then it must be
+// of the given type, or this function will panic.
+func forceShortCircuitType(shortCircuit *Value, ty Type) *Value {
+ if shortCircuit == nil {
+ return nil
+ }
+
+ if shortCircuit.ty == DynamicPseudoType {
+ ret := UnknownVal(ty)
+ return &ret
+ }
+
+ if !shortCircuit.ty.Equals(ty) {
+ panic("forceShortCircuitType got value of wrong type")
+ }
+
+ return shortCircuit
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json.go
new file mode 100644
index 00000000000..2222e0f80bb
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json.go
@@ -0,0 +1,199 @@
+package cty
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "sort"
+)
+
+// MarshalJSON is an implementation of json.Marshaler that allows Type
+// instances to be serialized as JSON.
+//
+// All standard types can be serialized, but capsule types cannot since there
+// is no way to automatically recover the original pointer and capsule types
+// compare by equality.
+func (t Type) MarshalJSON() ([]byte, error) {
+ switch impl := t.typeImpl.(type) {
+ case primitiveType:
+ switch impl.Kind {
+ case primitiveTypeBool:
+ return []byte{'"', 'b', 'o', 'o', 'l', '"'}, nil
+ case primitiveTypeNumber:
+ return []byte{'"', 'n', 'u', 'm', 'b', 'e', 'r', '"'}, nil
+ case primitiveTypeString:
+ return []byte{'"', 's', 't', 'r', 'i', 'n', 'g', '"'}, nil
+ default:
+ panic("unknown primitive type kind")
+ }
+ case typeList, typeMap, typeSet:
+ buf := &bytes.Buffer{}
+ etyJSON, err := t.ElementType().MarshalJSON()
+ if err != nil {
+ return nil, err
+ }
+ buf.WriteRune('[')
+ switch impl.(type) {
+ case typeList:
+ buf.WriteString(`"list"`)
+ case typeMap:
+ buf.WriteString(`"map"`)
+ case typeSet:
+ buf.WriteString(`"set"`)
+ }
+ buf.WriteRune(',')
+ buf.Write(etyJSON)
+ buf.WriteRune(']')
+ return buf.Bytes(), nil
+ case typeObject:
+ buf := &bytes.Buffer{}
+ atysJSON, err := json.Marshal(t.AttributeTypes())
+ if err != nil {
+ return nil, err
+ }
+ buf.WriteString(`["object",`)
+ buf.Write(atysJSON)
+ if optionals := t.OptionalAttributes(); len(optionals) > 0 {
+ buf.WriteByte(',')
+ optionalNames := make([]string, 0, len(optionals))
+ for k := range optionals {
+ optionalNames = append(optionalNames, k)
+ }
+ sort.Strings(optionalNames)
+ optionalsJSON, err := json.Marshal(optionalNames)
+ if err != nil {
+ return nil, err
+ }
+ buf.Write(optionalsJSON)
+ }
+ buf.WriteRune(']')
+ return buf.Bytes(), nil
+ case typeTuple:
+ buf := &bytes.Buffer{}
+ etysJSON, err := json.Marshal(t.TupleElementTypes())
+ if err != nil {
+ return nil, err
+ }
+ buf.WriteString(`["tuple",`)
+ buf.Write(etysJSON)
+ buf.WriteRune(']')
+ return buf.Bytes(), nil
+ case pseudoTypeDynamic:
+ return []byte{'"', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '"'}, nil
+ case *capsuleType:
+ return nil, fmt.Errorf("type not allowed: %s", t.FriendlyName())
+ default:
+ // should never happen
+ panic("unknown type implementation")
+ }
+}
+
+// UnmarshalJSON is the opposite of MarshalJSON. See the documentation of
+// MarshalJSON for information on the limitations of JSON serialization of
+// types.
+func (t *Type) UnmarshalJSON(buf []byte) error {
+ r := bytes.NewReader(buf)
+ dec := json.NewDecoder(r)
+
+ tok, err := dec.Token()
+ if err != nil {
+ return err
+ }
+
+ switch v := tok.(type) {
+ case string:
+ switch v {
+ case "bool":
+ *t = Bool
+ case "number":
+ *t = Number
+ case "string":
+ *t = String
+ case "dynamic":
+ *t = DynamicPseudoType
+ default:
+ return fmt.Errorf("invalid primitive type name %q", v)
+ }
+
+ if dec.More() {
+ return fmt.Errorf("extraneous data after type description")
+ }
+ return nil
+ case json.Delim:
+ if rune(v) != '[' {
+ return fmt.Errorf("invalid complex type description")
+ }
+
+ tok, err = dec.Token()
+ if err != nil {
+ return err
+ }
+
+ kind, ok := tok.(string)
+ if !ok {
+ return fmt.Errorf("invalid complex type kind name")
+ }
+
+ switch kind {
+ case "list":
+ var ety Type
+ err = dec.Decode(&ety)
+ if err != nil {
+ return err
+ }
+ *t = List(ety)
+ case "map":
+ var ety Type
+ err = dec.Decode(&ety)
+ if err != nil {
+ return err
+ }
+ *t = Map(ety)
+ case "set":
+ var ety Type
+ err = dec.Decode(&ety)
+ if err != nil {
+ return err
+ }
+ *t = Set(ety)
+ case "object":
+ var atys map[string]Type
+ err = dec.Decode(&atys)
+ if err != nil {
+ return err
+ }
+ if dec.More() {
+ var optionals []string
+ err = dec.Decode(&optionals)
+ if err != nil {
+ return err
+ }
+ *t = ObjectWithOptionalAttrs(atys, optionals)
+ } else {
+ *t = Object(atys)
+ }
+ case "tuple":
+ var etys []Type
+ err = dec.Decode(&etys)
+ if err != nil {
+ return err
+ }
+ *t = Tuple(etys)
+ default:
+ return fmt.Errorf("invalid complex type kind name")
+ }
+
+ tok, err = dec.Token()
+ if err != nil {
+ return err
+ }
+ if delim, ok := tok.(json.Delim); !ok || rune(delim) != ']' || dec.More() {
+ return fmt.Errorf("unexpected extra data in type description")
+ }
+
+ return nil
+
+ default:
+ return fmt.Errorf("invalid type description")
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/doc.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/doc.go
new file mode 100644
index 00000000000..8916513d673
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/doc.go
@@ -0,0 +1,11 @@
+// Package json provides functions for serializing cty types and values in
+// JSON format, and for decoding them again.
+//
+// Since the cty type system is a superset of the JSON type system,
+// round-tripping through JSON is lossy unless type information is provided
+// both at encoding time and decoding time. Callers of this package are
+// therefore suggested to define their expected structure as a cty.Type
+// and pass it in consistently both when encoding and when decoding, though
+// default (type-lossy) behavior is provided for situations where the precise
+// representation of the data is not significant.
+package json
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/marshal.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/marshal.go
new file mode 100644
index 00000000000..07d9f33178b
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/marshal.go
@@ -0,0 +1,195 @@
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "sort"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+func marshal(val cty.Value, t cty.Type, path cty.Path, b *bytes.Buffer) error {
+ if val.IsMarked() {
+ return path.NewErrorf("value has marks, so it cannot be serialized as JSON")
+ }
+ if !val.IsKnown() {
+ return path.NewErrorf("value is not known")
+ }
+
+ // If we're going to decode as DynamicPseudoType then we need to save
+ // dynamic type information to recover the real type.
+ if t == cty.DynamicPseudoType && val.Type() != cty.DynamicPseudoType {
+ return marshalDynamic(val, path, b)
+ }
+
+ if val.IsNull() {
+ b.WriteString("null")
+ return nil
+ }
+
+ // The caller should've guaranteed that the given val is conformant with
+ // the given type t, so we'll proceed under that assumption here.
+
+ switch {
+ case t.IsPrimitiveType():
+ switch t {
+ case cty.String:
+ json, err := json.Marshal(val.AsString())
+ if err != nil {
+ return path.NewErrorf("failed to serialize value: %s", err)
+ }
+ b.Write(json)
+ return nil
+ case cty.Number:
+ if val.RawEquals(cty.PositiveInfinity) || val.RawEquals(cty.NegativeInfinity) {
+ return path.NewErrorf("cannot serialize infinity as JSON")
+ }
+ b.WriteString(val.AsBigFloat().Text('f', -1))
+ return nil
+ case cty.Bool:
+ if val.True() {
+ b.WriteString("true")
+ } else {
+ b.WriteString("false")
+ }
+ return nil
+ default:
+ panic("unsupported primitive type")
+ }
+ case t.IsListType(), t.IsSetType():
+ b.WriteRune('[')
+ first := true
+ ety := t.ElementType()
+ it := val.ElementIterator()
+ path := append(path, nil) // local override of 'path' with extra element
+ for it.Next() {
+ if !first {
+ b.WriteRune(',')
+ }
+ ek, ev := it.Element()
+ path[len(path)-1] = cty.IndexStep{
+ Key: ek,
+ }
+ err := marshal(ev, ety, path, b)
+ if err != nil {
+ return err
+ }
+ first = false
+ }
+ b.WriteRune(']')
+ return nil
+ case t.IsMapType():
+ b.WriteRune('{')
+ first := true
+ ety := t.ElementType()
+ it := val.ElementIterator()
+ path := append(path, nil) // local override of 'path' with extra element
+ for it.Next() {
+ if !first {
+ b.WriteRune(',')
+ }
+ ek, ev := it.Element()
+ path[len(path)-1] = cty.IndexStep{
+ Key: ek,
+ }
+ var err error
+ err = marshal(ek, ek.Type(), path, b)
+ if err != nil {
+ return err
+ }
+ b.WriteRune(':')
+ err = marshal(ev, ety, path, b)
+ if err != nil {
+ return err
+ }
+ first = false
+ }
+ b.WriteRune('}')
+ return nil
+ case t.IsTupleType():
+ b.WriteRune('[')
+ etys := t.TupleElementTypes()
+ it := val.ElementIterator()
+ path := append(path, nil) // local override of 'path' with extra element
+ i := 0
+ for it.Next() {
+ if i > 0 {
+ b.WriteRune(',')
+ }
+ ety := etys[i]
+ ek, ev := it.Element()
+ path[len(path)-1] = cty.IndexStep{
+ Key: ek,
+ }
+ err := marshal(ev, ety, path, b)
+ if err != nil {
+ return err
+ }
+ i++
+ }
+ b.WriteRune(']')
+ return nil
+ case t.IsObjectType():
+ b.WriteRune('{')
+ atys := t.AttributeTypes()
+ path := append(path, nil) // local override of 'path' with extra element
+
+ names := make([]string, 0, len(atys))
+ for k := range atys {
+ names = append(names, k)
+ }
+ sort.Strings(names)
+
+ for i, k := range names {
+ aty := atys[k]
+ if i > 0 {
+ b.WriteRune(',')
+ }
+ av := val.GetAttr(k)
+ path[len(path)-1] = cty.GetAttrStep{
+ Name: k,
+ }
+ var err error
+ err = marshal(cty.StringVal(k), cty.String, path, b)
+ if err != nil {
+ return err
+ }
+ b.WriteRune(':')
+ err = marshal(av, aty, path, b)
+ if err != nil {
+ return err
+ }
+ }
+ b.WriteRune('}')
+ return nil
+ case t.IsCapsuleType():
+ rawVal := val.EncapsulatedValue()
+ jsonVal, err := json.Marshal(rawVal)
+ if err != nil {
+ return path.NewError(err)
+ }
+ b.Write(jsonVal)
+ return nil
+ default:
+ // should never happen
+ return path.NewErrorf("cannot JSON-serialize %s", t.FriendlyName())
+ }
+}
+
+// marshalDynamic adds an extra wrapping object containing dynamic type
+// information for the given value.
+func marshalDynamic(val cty.Value, path cty.Path, b *bytes.Buffer) error {
+ typeJSON, err := MarshalType(val.Type())
+ if err != nil {
+ return path.NewErrorf("failed to serialize type: %s", err)
+ }
+ b.WriteString(`{"value":`)
+ err = marshal(val, val.Type(), path, b)
+ if err != nil {
+ return path.NewErrorf("failed to serialize value: %s", err)
+ }
+ b.WriteString(`,"type":`)
+ b.Write(typeJSON)
+ b.WriteRune('}')
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/simple.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/simple.go
new file mode 100644
index 00000000000..507c9cc2c60
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/simple.go
@@ -0,0 +1,41 @@
+package json
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// SimpleJSONValue is a wrapper around cty.Value that adds implementations of
+// json.Marshaler and json.Unmarshaler for simple-but-type-lossy automatic
+// encoding and decoding of values.
+//
+// The couplet Marshal and Unmarshal both take extra type information to
+// inform the encoding and decoding process so that all of the cty types
+// can be represented even though JSON's type system is a subset.
+//
+// SimpleJSONValue instead takes the approach of discarding the value's type
+// information and then deriving a new type from the stored structure when
+// decoding. This results in the same data being returned but not necessarily
+// with exactly the same type.
+//
+// For information on how types are inferred when decoding, see the
+// documentation of the function ImpliedType.
+type SimpleJSONValue struct {
+ cty.Value
+}
+
+// MarshalJSON is an implementation of json.Marshaler. See the documentation
+// of SimpleJSONValue for more information.
+func (v SimpleJSONValue) MarshalJSON() ([]byte, error) {
+ return Marshal(v.Value, v.Type())
+}
+
+// UnmarshalJSON is an implementation of json.Unmarshaler. See the
+// documentation of SimpleJSONValue for more information.
+func (v *SimpleJSONValue) UnmarshalJSON(buf []byte) error {
+ t, err := ImpliedType(buf)
+ if err != nil {
+ return err
+ }
+ v.Value, err = Unmarshal(buf, t)
+ return err
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/type.go
new file mode 100644
index 00000000000..9131c6c7743
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/type.go
@@ -0,0 +1,23 @@
+package json
+
+import (
+ "github.com/zclconf/go-cty/cty"
+)
+
+// MarshalType returns a JSON serialization of the given type.
+//
+// This is just a thin wrapper around t.MarshalJSON, for symmetry with
+// UnmarshalType.
+func MarshalType(t cty.Type) ([]byte, error) {
+ return t.MarshalJSON()
+}
+
+// UnmarshalType decodes a JSON serialization of the given type as produced
+// by either Type.MarshalJSON or MarshalType.
+//
+// This is a convenience wrapper around Type.UnmarshalJSON.
+func UnmarshalType(buf []byte) (cty.Type, error) {
+ var t cty.Type
+ err := t.UnmarshalJSON(buf)
+ return t, err
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go
new file mode 100644
index 00000000000..1c90f342c42
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/type_implied.go
@@ -0,0 +1,193 @@
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// ImpliedType returns the cty Type implied by the structure of the given
+// JSON-compliant buffer. This function implements the default type mapping
+// behavior used when decoding arbitrary JSON without explicit cty Type
+// information.
+//
+// The rules are as follows:
+//
+// JSON strings, numbers and bools map to their equivalent primitive type in
+// cty.
+//
+// JSON objects map to cty object types, with the attributes defined by the
+// object keys and the types of their values.
+//
+// JSON arrays map to cty tuple types, with the elements defined by the
+// types of the array members.
+//
+// Any nulls are typed as DynamicPseudoType, so callers of this function
+// must be prepared to deal with this. Callers that do not wish to deal with
+// dynamic typing should not use this function and should instead describe
+// their required types explicitly with a cty.Type instance when decoding.
+//
+// Any JSON syntax errors will be returned as an error, and the type will
+// be the invalid value cty.NilType.
+func ImpliedType(buf []byte) (cty.Type, error) {
+ r := bytes.NewReader(buf)
+ dec := json.NewDecoder(r)
+ dec.UseNumber()
+
+ ty, err := impliedType(dec)
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ if dec.More() {
+ return cty.NilType, fmt.Errorf("extraneous data after JSON object")
+ }
+
+ return ty, nil
+}
+
+func impliedType(dec *json.Decoder) (cty.Type, error) {
+ tok, err := dec.Token()
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ return impliedTypeForTok(tok, dec)
+}
+
+func impliedTypeForTok(tok json.Token, dec *json.Decoder) (cty.Type, error) {
+ if tok == nil {
+ return cty.DynamicPseudoType, nil
+ }
+
+ switch ttok := tok.(type) {
+ case bool:
+ return cty.Bool, nil
+
+ case json.Number:
+ return cty.Number, nil
+
+ case string:
+ return cty.String, nil
+
+ case json.Delim:
+
+ switch rune(ttok) {
+ case '{':
+ return impliedObjectType(dec)
+ case '[':
+ return impliedTupleType(dec)
+ default:
+ return cty.NilType, fmt.Errorf("unexpected token %q", ttok)
+ }
+
+ default:
+ return cty.NilType, fmt.Errorf("unsupported JSON token %#v", tok)
+ }
+}
+
+func impliedObjectType(dec *json.Decoder) (cty.Type, error) {
+ // By the time we get in here, we've already consumed the { delimiter
+ // and so our next token should be the first object key.
+
+ var atys map[string]cty.Type
+
+ for {
+ // Read the object key first
+ tok, err := dec.Token()
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ if ttok, ok := tok.(json.Delim); ok {
+ if rune(ttok) != '}' {
+ return cty.NilType, fmt.Errorf("unexpected delimiter %q", ttok)
+ }
+ break
+ }
+
+ key, ok := tok.(string)
+ if !ok {
+ return cty.NilType, fmt.Errorf("expected string but found %T", tok)
+ }
+
+ // Now read the value
+ tok, err = dec.Token()
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ aty, err := impliedTypeForTok(tok, dec)
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ if atys == nil {
+ atys = make(map[string]cty.Type)
+ }
+ if existing, exists := atys[key]; exists {
+ // We didn't originally have any special treatment for multiple properties
+ // of the same name, having the type of the last one "win". But that caused
+ // some confusing error messages when the same input was subsequently used
+ // with [Unmarshal] using the returned object type, since [Unmarshal] would
+ // try to fit all of the property values of that name to whatever type
+ // the last one had, and would likely fail in doing so if the earlier
+ // properties of the same name had different types.
+ //
+ // As a compromise to avoid breaking existing successful use of _consistently-typed_
+ // redundant properties, we return an error here only if the new type
+ // differs from the old type. The error message doesn't mention that subtlety
+ // because the equal type carveout is a compatibility concession rather than
+ // a feature folks should rely on in new code.
+ if !existing.Equals(aty) {
+ // This error message is low-quality because ImpliedType doesn't do
+ // path tracking while it traverses, unlike Unmarshal. However, this
+ // is a rare enough case that we don't want to pay the cost of allocating
+ // another path-tracking buffer that would in most cases be ignored,
+ // so we just accept a low-context error message. :(
+ return cty.NilType, fmt.Errorf("duplicate %q property in JSON object", key)
+ }
+ }
+ atys[key] = aty
+ }
+
+ if len(atys) == 0 {
+ return cty.EmptyObject, nil
+ }
+
+ return cty.Object(atys), nil
+}
+
+func impliedTupleType(dec *json.Decoder) (cty.Type, error) {
+ // By the time we get in here, we've already consumed the [ delimiter
+ // and so our next token should be the first value.
+
+ var etys []cty.Type
+
+ for {
+ tok, err := dec.Token()
+ if err != nil {
+ return cty.NilType, err
+ }
+
+ if ttok, ok := tok.(json.Delim); ok {
+ if rune(ttok) == ']' {
+ break
+ }
+ }
+
+ ety, err := impliedTypeForTok(tok, dec)
+ if err != nil {
+ return cty.NilType, err
+ }
+ etys = append(etys, ety)
+ }
+
+ if len(etys) == 0 {
+ return cty.EmptyTuple, nil
+ }
+
+ return cty.Tuple(etys), nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
new file mode 100644
index 00000000000..38106455fed
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/unmarshal.go
@@ -0,0 +1,459 @@
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+func unmarshal(buf []byte, t cty.Type, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+
+ tok, err := dec.Token()
+ if err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ if tok == nil {
+ return cty.NullVal(t), nil
+ }
+
+ if t == cty.DynamicPseudoType {
+ return unmarshalDynamic(buf, path)
+ }
+
+ switch {
+ case t.IsPrimitiveType():
+ val, err := unmarshalPrimitive(tok, t, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+ return val, nil
+ case t.IsListType():
+ return unmarshalList(buf, t.ElementType(), path)
+ case t.IsSetType():
+ return unmarshalSet(buf, t.ElementType(), path)
+ case t.IsMapType():
+ return unmarshalMap(buf, t.ElementType(), path)
+ case t.IsTupleType():
+ return unmarshalTuple(buf, t.TupleElementTypes(), path)
+ case t.IsObjectType():
+ return unmarshalObject(buf, t.AttributeTypes(), path)
+ case t.IsCapsuleType():
+ return unmarshalCapsule(buf, t, path)
+ default:
+ return cty.NilVal, path.NewErrorf("unsupported type %s", t.FriendlyName())
+ }
+}
+
+func unmarshalPrimitive(tok json.Token, t cty.Type, path cty.Path) (cty.Value, error) {
+
+ switch t {
+ case cty.Bool:
+ switch v := tok.(type) {
+ case bool:
+ return cty.BoolVal(v), nil
+ case string:
+ val, err := convert.Convert(cty.StringVal(v), t)
+ if err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+ return val, nil
+ default:
+ return cty.NilVal, path.NewErrorf("bool is required")
+ }
+ case cty.Number:
+ if v, ok := tok.(json.Number); ok {
+ tok = string(v)
+ }
+ switch v := tok.(type) {
+ case string:
+ val, err := cty.ParseNumberVal(v)
+ if err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+ return val, nil
+ default:
+ return cty.NilVal, path.NewErrorf("number is required")
+ }
+ case cty.String:
+ switch v := tok.(type) {
+ case string:
+ return cty.StringVal(v), nil
+ case json.Number:
+ return cty.StringVal(string(v)), nil
+ case bool:
+ val, err := convert.Convert(cty.BoolVal(v), t)
+ if err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+ return val, nil
+ default:
+ return cty.NilVal, path.NewErrorf("string is required")
+ }
+ default:
+ // should never happen
+ panic("unsupported primitive type")
+ }
+}
+
+func unmarshalList(buf []byte, ety cty.Type, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+ if err := requireDelim(dec, '['); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ var vals []cty.Value
+
+ {
+ path := append(path, nil)
+ var idx int64
+
+ for dec.More() {
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(idx),
+ }
+ idx++
+
+ rawVal, err := readRawValue(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read list value: %s", err)
+ }
+
+ el, err := unmarshal(rawVal, ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ vals = append(vals, el)
+ }
+ }
+
+ if err := requireDelim(dec, ']'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ if len(vals) == 0 {
+ return cty.ListValEmpty(ety), nil
+ }
+
+ return cty.ListVal(vals), nil
+}
+
+func unmarshalSet(buf []byte, ety cty.Type, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+ if err := requireDelim(dec, '['); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ var vals []cty.Value
+
+ {
+ path := append(path, nil)
+
+ for dec.More() {
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.UnknownVal(ety),
+ }
+
+ rawVal, err := readRawValue(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read set value: %s", err)
+ }
+
+ el, err := unmarshal(rawVal, ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ vals = append(vals, el)
+ }
+ }
+
+ if err := requireDelim(dec, ']'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ if len(vals) == 0 {
+ return cty.SetValEmpty(ety), nil
+ }
+
+ return cty.SetVal(vals), nil
+}
+
+func unmarshalMap(buf []byte, ety cty.Type, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+ if err := requireDelim(dec, '{'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ vals := make(map[string]cty.Value)
+
+ {
+ path := append(path, nil)
+
+ for dec.More() {
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.UnknownVal(cty.String),
+ }
+
+ var err error
+
+ k, err := requireObjectKey(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read map key: %s", err)
+ }
+
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.StringVal(k),
+ }
+
+ rawVal, err := readRawValue(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read map value: %s", err)
+ }
+
+ el, err := unmarshal(rawVal, ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ vals[k] = el
+ }
+ }
+
+ if err := requireDelim(dec, '}'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ if len(vals) == 0 {
+ return cty.MapValEmpty(ety), nil
+ }
+
+ return cty.MapVal(vals), nil
+}
+
+func unmarshalTuple(buf []byte, etys []cty.Type, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+ if err := requireDelim(dec, '['); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ var vals []cty.Value
+
+ {
+ path := append(path, nil)
+ var idx int
+
+ for dec.More() {
+ if idx >= len(etys) {
+ return cty.NilVal, path[:len(path)-1].NewErrorf("too many tuple elements (need %d)", len(etys))
+ }
+
+ path[len(path)-1] = cty.IndexStep{
+ Key: cty.NumberIntVal(int64(idx)),
+ }
+ ety := etys[idx]
+ idx++
+
+ rawVal, err := readRawValue(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read tuple value: %s", err)
+ }
+
+ el, err := unmarshal(rawVal, ety, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ vals = append(vals, el)
+ }
+ }
+
+ if err := requireDelim(dec, ']'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ if len(vals) != len(etys) {
+ return cty.NilVal, path[:len(path)-1].NewErrorf("not enough tuple elements (need %d)", len(etys))
+ }
+
+ if len(vals) == 0 {
+ return cty.EmptyTupleVal, nil
+ }
+
+ return cty.TupleVal(vals), nil
+}
+
+func unmarshalObject(buf []byte, atys map[string]cty.Type, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+ if err := requireDelim(dec, '{'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ vals := make(map[string]cty.Value)
+
+ {
+ objPath := path // some errors report from the object's perspective
+ path := append(path, nil) // path to a specific attribute
+
+ for dec.More() {
+
+ var err error
+
+ k, err := requireObjectKey(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read object key: %s", err)
+ }
+
+ aty, ok := atys[k]
+ if !ok {
+ return cty.NilVal, objPath.NewErrorf("unsupported attribute %q", k)
+ }
+
+ path[len(path)-1] = cty.GetAttrStep{
+ Name: k,
+ }
+
+ rawVal, err := readRawValue(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read object value: %s", err)
+ }
+
+ el, err := unmarshal(rawVal, aty, path)
+ if err != nil {
+ return cty.NilVal, err
+ }
+
+ vals[k] = el
+ }
+ }
+
+ if err := requireDelim(dec, '}'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ // Make sure we have a value for every attribute
+ for k, aty := range atys {
+ if _, exists := vals[k]; !exists {
+ vals[k] = cty.NullVal(aty)
+ }
+ }
+
+ if len(vals) == 0 {
+ return cty.EmptyObjectVal, nil
+ }
+
+ return cty.ObjectVal(vals), nil
+}
+
+func unmarshalCapsule(buf []byte, t cty.Type, path cty.Path) (cty.Value, error) {
+ rawType := t.EncapsulatedType()
+ ptrPtr := reflect.New(reflect.PtrTo(rawType))
+ ptrPtr.Elem().Set(reflect.New(rawType))
+ ptr := ptrPtr.Elem().Interface()
+ err := json.Unmarshal(buf, ptr)
+ if err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ return cty.CapsuleVal(t, ptr), nil
+}
+
+func unmarshalDynamic(buf []byte, path cty.Path) (cty.Value, error) {
+ dec := bufDecoder(buf)
+ if err := requireDelim(dec, '{'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ var t cty.Type
+ var valBody []byte // defer actual decoding until we know the type
+
+ for dec.More() {
+ var err error
+
+ key, err := requireObjectKey(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read dynamic type descriptor key: %s", err)
+ }
+
+ rawVal, err := readRawValue(dec)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to read dynamic type descriptor value: %s", err)
+ }
+
+ switch key {
+ case "type":
+ err := json.Unmarshal(rawVal, &t)
+ if err != nil {
+ return cty.NilVal, path.NewErrorf("failed to decode type for dynamic value: %s", err)
+ }
+ case "value":
+ valBody = rawVal
+ default:
+ return cty.NilVal, path.NewErrorf("invalid key %q in dynamically-typed value", key)
+ }
+
+ }
+
+ if err := requireDelim(dec, '}'); err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+
+ if t == cty.NilType {
+ return cty.NilVal, path.NewErrorf("missing type in dynamically-typed value")
+ }
+ if valBody == nil {
+ return cty.NilVal, path.NewErrorf("missing value in dynamically-typed value")
+ }
+
+ val, err := Unmarshal([]byte(valBody), t)
+ if err != nil {
+ return cty.NilVal, path.NewError(err)
+ }
+ return val, nil
+}
+
+func requireDelim(dec *json.Decoder, d rune) error {
+ tok, err := dec.Token()
+ if err != nil {
+ return err
+ }
+
+ if tok != json.Delim(d) {
+ return fmt.Errorf("missing expected %c", d)
+ }
+
+ return nil
+}
+
+func requireObjectKey(dec *json.Decoder) (string, error) {
+ tok, err := dec.Token()
+ if err != nil {
+ return "", err
+ }
+ if s, ok := tok.(string); ok {
+ return s, nil
+ }
+ return "", fmt.Errorf("missing expected object key")
+}
+
+func readRawValue(dec *json.Decoder) ([]byte, error) {
+ var rawVal json.RawMessage
+ err := dec.Decode(&rawVal)
+ if err != nil {
+ return nil, err
+ }
+ return []byte(rawVal), nil
+}
+
+func bufDecoder(buf []byte) *json.Decoder {
+ r := bytes.NewReader(buf)
+ dec := json.NewDecoder(r)
+ dec.UseNumber()
+ return dec
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/value.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/value.go
new file mode 100644
index 00000000000..f2f7dd56c77
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/json/value.go
@@ -0,0 +1,65 @@
+package json
+
+import (
+ "bytes"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+// Marshal produces a JSON representation of the given value that can later
+// be decoded into a value of the given type.
+//
+// A type is specified separately to allow for the given type to include
+// cty.DynamicPseudoType to represent situations where any type is permitted
+// and so type information must be included to allow recovery of the stored
+// structure when decoding.
+//
+// The given type will also be used to attempt automatic conversions of any
+// non-conformant types in the given value, although this will not always
+// be possible. If the value cannot be made to be conformant then an error is
+// returned, which may be a cty.PathError.
+//
+// Capsule-typed values can be marshalled, but with some caveats. Since
+// capsule values are compared by pointer equality, it is impossible to recover
+// a value that will compare equal to the original value. Additionally,
+// it's not possible to JSON-serialize the capsule type itself, so it's not
+// valid to use capsule types within parts of the value that are conformed to
+// cty.DynamicPseudoType. Otherwise, a capsule value can be used as long as
+// the encapsulated type itself is serializable with the Marshal function
+// in encoding/json.
+func Marshal(val cty.Value, t cty.Type) ([]byte, error) {
+ errs := val.Type().TestConformance(t)
+ if errs != nil {
+ // Attempt a conversion
+ var err error
+ val, err = convert.Convert(val, t)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // From this point onward, val can be assumed to be conforming to t.
+
+ buf := &bytes.Buffer{}
+ var path cty.Path
+ err := marshal(val, t, path, buf)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+// Unmarshal decodes a JSON representation of the given value into a cty Value
+// conforming to the given type.
+//
+// While decoding, type conversions will be done where possible to make
+// the result conformant even if the types given in JSON are not exactly
+// correct. If conversion isn't possible then an error is returned, which
+// may be a cty.PathError.
+func Unmarshal(buf []byte, t cty.Type) (cty.Value, error) {
+ var path cty.Path
+ return unmarshal(buf, t, path)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/list_type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/list_type.go
new file mode 100644
index 00000000000..2ef02a12f3e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/list_type.go
@@ -0,0 +1,74 @@
+package cty
+
+import (
+ "fmt"
+)
+
+// TypeList instances represent specific list types. Each distinct ElementType
+// creates a distinct, non-equal list type.
+type typeList struct {
+ typeImplSigil
+ ElementTypeT Type
+}
+
+// List creates a map type with the given element Type.
+//
+// List types are CollectionType implementations.
+func List(elem Type) Type {
+ return Type{
+ typeList{
+ ElementTypeT: elem,
+ },
+ }
+}
+
+// Equals returns true if the other Type is a list whose element type is
+// equal to that of the receiver.
+func (t typeList) Equals(other Type) bool {
+ ot, isList := other.typeImpl.(typeList)
+ if !isList {
+ return false
+ }
+
+ return t.ElementTypeT.Equals(ot.ElementTypeT)
+}
+
+func (t typeList) FriendlyName(mode friendlyTypeNameMode) string {
+ elemName := t.ElementTypeT.friendlyNameMode(mode)
+ if mode == friendlyTypeConstraintName {
+ if t.ElementTypeT == DynamicPseudoType {
+ elemName = "any single type"
+ }
+ }
+ return "list of " + elemName
+}
+
+func (t typeList) ElementType() Type {
+ return t.ElementTypeT
+}
+
+func (t typeList) GoString() string {
+ return fmt.Sprintf("cty.List(%#v)", t.ElementTypeT)
+}
+
+// IsListType returns true if the given type is a list type, regardless of its
+// element type.
+func (t Type) IsListType() bool {
+ _, ok := t.typeImpl.(typeList)
+ return ok
+}
+
+// ListElementType is a convenience method that checks if the given type is
+// a list type, returning a pointer to its element type if so and nil
+// otherwise. This is intended to allow convenient conditional branches,
+// like so:
+//
+// if et := t.ListElementType(); et != nil {
+// // Do something with *et
+// }
+func (t Type) ListElementType() *Type {
+ if lt, ok := t.typeImpl.(typeList); ok {
+ return <.ElementTypeT
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/map_type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/map_type.go
new file mode 100644
index 00000000000..732c78a80d3
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/map_type.go
@@ -0,0 +1,74 @@
+package cty
+
+import (
+ "fmt"
+)
+
+// TypeList instances represent specific list types. Each distinct ElementType
+// creates a distinct, non-equal list type.
+type typeMap struct {
+ typeImplSigil
+ ElementTypeT Type
+}
+
+// Map creates a map type with the given element Type.
+//
+// Map types are CollectionType implementations.
+func Map(elem Type) Type {
+ return Type{
+ typeMap{
+ ElementTypeT: elem,
+ },
+ }
+}
+
+// Equals returns true if the other Type is a map whose element type is
+// equal to that of the receiver.
+func (t typeMap) Equals(other Type) bool {
+ ot, isMap := other.typeImpl.(typeMap)
+ if !isMap {
+ return false
+ }
+
+ return t.ElementTypeT.Equals(ot.ElementTypeT)
+}
+
+func (t typeMap) FriendlyName(mode friendlyTypeNameMode) string {
+ elemName := t.ElementTypeT.friendlyNameMode(mode)
+ if mode == friendlyTypeConstraintName {
+ if t.ElementTypeT == DynamicPseudoType {
+ elemName = "any single type"
+ }
+ }
+ return "map of " + elemName
+}
+
+func (t typeMap) ElementType() Type {
+ return t.ElementTypeT
+}
+
+func (t typeMap) GoString() string {
+ return fmt.Sprintf("cty.Map(%#v)", t.ElementTypeT)
+}
+
+// IsMapType returns true if the given type is a map type, regardless of its
+// element type.
+func (t Type) IsMapType() bool {
+ _, ok := t.typeImpl.(typeMap)
+ return ok
+}
+
+// MapElementType is a convenience method that checks if the given type is
+// a map type, returning a pointer to its element type if so and nil
+// otherwise. This is intended to allow convenient conditional branches,
+// like so:
+//
+// if et := t.MapElementType(); et != nil {
+// // Do something with *et
+// }
+func (t Type) MapElementType() *Type {
+ if lt, ok := t.typeImpl.(typeMap); ok {
+ return <.ElementTypeT
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/marks.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/marks.go
new file mode 100644
index 00000000000..44287f5197c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/marks.go
@@ -0,0 +1,439 @@
+package cty
+
+import (
+ "fmt"
+ "iter"
+ "strings"
+
+ "github.com/zclconf/go-cty/cty/ctymarks"
+)
+
+// marker is an internal wrapper type used to add special "marks" to values.
+//
+// A "mark" is an annotation that can be used to represent additional
+// characteristics of values that propagate through operation methods to
+// result values. However, a marked value cannot be used with integration
+// methods normally associated with its type, in order to ensure that
+// calling applications don't inadvertently drop marks as they round-trip
+// values out of cty and back in again.
+//
+// Marked values are created only explicitly by the calling application, so
+// an application that never marks a value does not need to worry about
+// encountering marked values.
+type marker struct {
+ realV any
+ marks ValueMarks
+}
+
+// ValueMarks is a map, representing a set, of "mark" values associated with
+// a Value. See Value.Mark for more information on the usage of mark values.
+type ValueMarks map[any]struct{}
+
+// NewValueMarks constructs a new ValueMarks set with the given mark values.
+//
+// If any of the arguments are already ValueMarks values then they'll be merged
+// into the result, rather than used directly as individual marks.
+func NewValueMarks(marks ...any) ValueMarks {
+ if len(marks) == 0 {
+ return nil
+ }
+ ret := make(ValueMarks, len(marks))
+ for _, v := range marks {
+ if vm, ok := v.(ValueMarks); ok {
+ // Constructing a new ValueMarks with an existing ValueMarks
+ // implements a merge operation. (This can cause our result to
+ // have a larger size than we expected, but that's okay.)
+ for v := range vm {
+ ret[v] = struct{}{}
+ }
+ continue
+ }
+ ret[v] = struct{}{}
+ }
+ if len(ret) == 0 {
+ // If we were merging ValueMarks values together and they were all
+ // empty then we'll avoid returning a zero-length map and return a
+ // nil instead, as is conventional.
+ return nil
+ }
+ return ret
+}
+
+// Equal returns true if the receiver and the given ValueMarks both contain
+// the same marks.
+func (m ValueMarks) Equal(o ValueMarks) bool {
+ if len(m) != len(o) {
+ return false
+ }
+ for v := range m {
+ if _, ok := o[v]; !ok {
+ return false
+ }
+ }
+ return true
+}
+
+func (m ValueMarks) GoString() string {
+ var s strings.Builder
+ s.WriteString("cty.NewValueMarks(")
+ i := 0
+ for mv := range m {
+ if i != 0 {
+ s.WriteString(", ")
+ }
+ s.WriteString(fmt.Sprintf("%#v", mv))
+ i++
+ }
+ s.WriteString(")")
+ return s.String()
+}
+
+// PathValueMarks is a structure that enables tracking marks
+// and the paths where they are located in one type
+type PathValueMarks struct {
+ Path Path
+ Marks ValueMarks
+}
+
+func (p PathValueMarks) Equal(o PathValueMarks) bool {
+ if !p.Path.Equals(o.Path) {
+ return false
+ }
+ if !p.Marks.Equal(o.Marks) {
+ return false
+ }
+ return true
+}
+
+// IsMarked returns true if and only if the receiving value carries at least
+// one mark. A marked value cannot be used directly with integration methods
+// without explicitly unmarking it (and retrieving the markings) first.
+func (val Value) IsMarked() bool {
+ _, ok := val.v.(marker)
+ return ok
+}
+
+// HasMark returns true if and only if the receiving value has the given mark.
+func (val Value) HasMark(mark any) bool {
+ if mr, ok := val.v.(marker); ok {
+ _, ok := mr.marks[mark]
+ return ok
+ }
+ return false
+}
+
+// HasMarkDeep is like [HasMark] but also searches any values nested inside
+// the given value.
+func (val Value) HasMarkDeep(mark any) bool {
+ for _, v := range DeepValues(val) {
+ if v.HasMark(mark) {
+ return true
+ }
+ }
+ return false
+}
+
+// ValueMarksOfType returns an iterable sequence of any marks directly
+// associated with the given value that can be type-asserted to the given
+// type.
+func ValueMarksOfType[T any](v Value) iter.Seq[T] {
+ return func(yield func(T) bool) {
+ yieldValueMarksOfType(v, yield)
+ }
+}
+
+// ValueMarksOfTypeDeep is like [ValueMarksOfType] but also visits any values
+// nested inside the given value.
+//
+// The same value may be produced multiple times if multiple nested values are
+// marked with it.
+func ValueMarksOfTypeDeep[T any](v Value) iter.Seq[T] {
+ return func(yield func(T) bool) {
+ for _, v := range DeepValues(v) {
+ if !yieldValueMarksOfType(v, yield) {
+ break
+ }
+ }
+ }
+}
+
+func yieldValueMarksOfType[T any](v Value, yield func(T) bool) bool {
+ mr, ok := v.v.(marker)
+ if !ok {
+ return true
+ }
+ for mark := range mr.marks {
+ if v, ok := mark.(T); ok {
+ if !yield(v) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// ContainsMarked returns true if the receiving value or any value within it
+// is marked.
+//
+// This operation is relatively expensive. If you only need a shallow result,
+// use IsMarked instead.
+func (val Value) ContainsMarked() bool {
+ for _, v := range DeepValues(val) {
+ if v.IsMarked() {
+ return true
+ }
+ }
+ return false
+}
+
+func (val Value) assertUnmarked() {
+ if val.IsMarked() {
+ panic("value is marked, so must be unmarked first")
+ }
+}
+
+// Marks returns a map (representing a set) of all of the mark values
+// associated with the receiving value, without changing the marks. Returns nil
+// if the value is not marked at all.
+func (val Value) Marks() ValueMarks {
+ if mr, ok := val.v.(marker); ok {
+ // copy so that the caller can't mutate our internals
+ ret := make(ValueMarks, len(mr.marks))
+ for k, v := range mr.marks {
+ ret[k] = v
+ }
+ return ret
+ }
+ return nil
+}
+
+// HasSameMarks returns true if an only if the receiver and the given other
+// value have identical marks.
+func (val Value) HasSameMarks(other Value) bool {
+ vm, vmOK := val.v.(marker)
+ om, omOK := other.v.(marker)
+ if vmOK != omOK {
+ return false
+ }
+ if vmOK {
+ return vm.marks.Equal(om.marks)
+ }
+ return true
+}
+
+// Mark returns a new value that as the same type and underlying value as
+// the receiver but that also carries the given value as a "mark".
+//
+// Marks are used to carry additional application-specific characteristics
+// associated with values. A marked value can be used with operation methods,
+// in which case the marks are propagated to the operation results. A marked
+// value _cannot_ be used with integration methods, so callers of those
+// must derive an unmarked value using Unmark (and thus explicitly handle
+// the markings) before calling the integration methods.
+//
+// The mark value can be any value that would be valid to use as a map key.
+// The mark value should be of a named type in order to use the type itself
+// as a namespace for markings. That type can be unexported if desired, in
+// order to ensure that the mark can only be handled through the defining
+// package's own functions.
+//
+// An application that never calls this method does not need to worry about
+// handling marked values.
+func (val Value) Mark(mark any) Value {
+ if _, ok := mark.(ValueMarks); ok {
+ panic("cannot call Value.Mark with a ValueMarks value (use WithMarks instead)")
+ }
+ var newMarker marker
+ newMarker.realV = val.v
+ if mr, ok := val.v.(marker); ok {
+ // It's already a marker, so we'll retain existing marks.
+ newMarker.marks = make(ValueMarks, len(mr.marks)+1)
+ for k, v := range mr.marks {
+ newMarker.marks[k] = v
+ }
+ // unwrap the inner marked value, so we don't get multiple layers
+ // of marking.
+ newMarker.realV = mr.realV
+ } else {
+ // It's not a marker yet, so we're creating the first mark.
+ newMarker.marks = make(ValueMarks, 1)
+ }
+ newMarker.marks[mark] = struct{}{}
+ return Value{
+ ty: val.ty,
+ v: newMarker,
+ }
+}
+
+type applyPathValueMarksTransformer struct {
+ pvm []PathValueMarks
+}
+
+func (t *applyPathValueMarksTransformer) Enter(p Path, v Value) (Value, error) {
+ return v, nil
+}
+
+func (t *applyPathValueMarksTransformer) Exit(p Path, v Value) (Value, error) {
+ for _, path := range t.pvm {
+ if p.Equals(path.Path) {
+ return v.WithMarks(path.Marks), nil
+ }
+ }
+ return v, nil
+}
+
+// MarkWithPaths accepts a slice of PathValueMarks to apply
+// markers to particular paths and returns the marked
+// Value.
+func (val Value) MarkWithPaths(pvm []PathValueMarks) Value {
+ if len(pvm) == 0 {
+ // If we have no marks to apply then there's nothing to do, so we'll
+ // just return the same value rather than wastefully rebuilding it.
+ return val
+ }
+ ret, _ := TransformWithTransformer(val, &applyPathValueMarksTransformer{pvm})
+ return ret
+}
+
+// Unmark separates the marks of the receiving value from the value itself,
+// removing a new unmarked value and a map (representing a set) of the marks.
+//
+// If the receiver isn't marked, Unmark returns it verbatim along with a nil
+// map of marks.
+func (val Value) Unmark() (Value, ValueMarks) {
+ if !val.IsMarked() {
+ return val, nil
+ }
+ mr := val.v.(marker)
+ marks := val.Marks() // copy so that the caller can't mutate our internals
+ return Value{
+ ty: val.ty,
+ v: mr.realV,
+ }, marks
+}
+
+// UnmarkDeep is similar to Unmark, but it works with an entire nested structure
+// rather than just the given value directly.
+//
+// The result is guaranteed to contain no nested values that are marked, and
+// the returned marks set includes the superset of all of the marks encountered
+// during the operation.
+func (val Value) UnmarkDeep() (Value, ValueMarks) {
+ retMarks := make(ValueMarks)
+ retVal, _ := val.WrangleMarksDeep(func(mark any, path Path) (ctymarks.WrangleAction, error) {
+ retMarks[mark] = struct{}{}
+ return ctymarks.WrangleDrop, nil
+ })
+ return retVal, retMarks
+}
+
+// UnmarkDeepWithPaths is like UnmarkDeep, except it returns a slice
+// of PathValueMarks rather than a superset of all marks. This allows
+// a caller to know which marks are associated with which paths
+// in the Value.
+func (val Value) UnmarkDeepWithPaths() (Value, []PathValueMarks) {
+ var pvm []PathValueMarks
+ retVal, _ := val.WrangleMarksDeep(func(mark any, path Path) (ctymarks.WrangleAction, error) {
+ if len(pvm) != 0 {
+ // We'll try to modify the most recent item instead of adding
+ // a new one, if the path hasn't changed.
+ latest := &pvm[len(pvm)-1]
+ if latest.Path.Equals(path) {
+ latest.Marks[mark] = struct{}{}
+ return ctymarks.WrangleDrop, nil
+ }
+ }
+ pvm = append(pvm, PathValueMarks{
+ Path: path.Copy(),
+ Marks: NewValueMarks(mark),
+ })
+ return ctymarks.WrangleDrop, nil
+ })
+ return retVal, pvm
+}
+
+func (val Value) unmarkForce() Value {
+ unw, _ := val.Unmark()
+ return unw
+}
+
+// WithMarks returns a new value that has the same type and underlying value
+// as the receiver and also has the marks from the given maps (representing
+// sets).
+func (val Value) WithMarks(marks ...ValueMarks) Value {
+ if len(marks) == 0 {
+ return val
+ }
+ ownMarks := val.Marks()
+ markCount := len(ownMarks)
+ for _, s := range marks {
+ markCount += len(s)
+ }
+ if markCount == 0 {
+ return val
+ }
+ newMarks := make(ValueMarks, markCount)
+ for m := range ownMarks {
+ newMarks[m] = struct{}{}
+ }
+ for _, s := range marks {
+ for m := range s {
+ newMarks[m] = struct{}{}
+ }
+ }
+ v := val.v
+ if mr, ok := v.(marker); ok {
+ v = mr.realV
+ }
+ return Value{
+ ty: val.ty,
+ v: marker{
+ realV: v,
+ marks: newMarks,
+ },
+ }
+}
+
+// WithSameMarks returns a new value that has the same type and underlying
+// value as the receiver and also has the marks from the given source values.
+//
+// Use this if you are implementing your own higher-level operations against
+// cty using the integration methods, to re-introduce the marks from the
+// source values of the operation.
+func (val Value) WithSameMarks(srcs ...Value) Value {
+ if len(srcs) == 0 {
+ return val
+ }
+ ownMarks := val.Marks()
+ markCount := len(ownMarks)
+ for _, sv := range srcs {
+ if mr, ok := sv.v.(marker); ok {
+ markCount += len(mr.marks)
+ }
+ }
+ if markCount == 0 {
+ return val
+ }
+ newMarks := make(ValueMarks, markCount)
+ for m := range ownMarks {
+ newMarks[m] = struct{}{}
+ }
+ for _, sv := range srcs {
+ if mr, ok := sv.v.(marker); ok {
+ for m := range mr.marks {
+ newMarks[m] = struct{}{}
+ }
+ }
+ }
+ v := val.v
+ if mr, ok := v.(marker); ok {
+ v = mr.realV
+ }
+ return Value{
+ ty: val.ty,
+ v: marker{
+ realV: v,
+ marks: newMarks,
+ },
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/marks_wrangle.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/marks_wrangle.go
new file mode 100644
index 00000000000..123453c3bf3
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/marks_wrangle.go
@@ -0,0 +1,289 @@
+package cty
+
+import (
+ "errors"
+ "fmt"
+ "iter"
+ "maps"
+
+ "github.com/zclconf/go-cty/cty/ctymarks"
+)
+
+// WrangleMarksDeep is a specialized variant of [Transform] that is focused
+// on interrogating and modifying any marks present throughout a data structure,
+// without modifying anything else about the value.
+//
+// Refer to the [WrangleFunc] documentation for more information. Each of
+// the provided functions is called in turn for each mark at each distinct path,
+// and the first function that returns a non-nil [ctymarks.WrangleAction] "wins"
+// and prevents any later ones from running for a particular mark/path pair.
+//
+// The implementation makes a best effort to avoid constructing new values
+// unless marks have actually changed, to keep this operation relatively cheap
+// in the presumed-common case where no marks are present at all.
+func (v Value) WrangleMarksDeep(wranglers ...WrangleFunc) (Value, error) {
+ // This function is implemented in this package, rather than in the
+ // separate "ctymarks", so that it can intrude into the unexported
+ // internal details of [Value] to minimize overhead when no marks
+ // are present at all.
+ var path Path
+ if v.IsKnown() && !v.Type().IsPrimitiveType() && !v.IsNull() {
+ // If we have a known, non-null, non-primitive-typed value then we
+ // can assume there will be at least a little nesting we need to
+ // represent using our path, and so we'll preallocate some capacity
+ // which we'll be able to share across all calls that are shallower
+ // than this level of nesting.
+ path = make(Path, 0, 4)
+ }
+ topMarks := make(ValueMarks)
+ var errs []error
+ new := wrangleMarksDeep(v, wranglers, path, topMarks, &errs)
+ if new == NilVal {
+ new = v // completely unchanged
+ }
+ var err error
+ switch len(errs) {
+ case 0:
+ // nil err is fine, then
+ case 1:
+ err = errs[0]
+ default:
+ err = errors.Join(errs...)
+ }
+ return new.WithMarks(topMarks), err
+}
+
+// wrangleMarksDeep is the main implementation of [WrangleMarksDeep], which
+// calls itself recursively to handle nested data structures.
+//
+// If the returned value is [NilVal] then that means that no changes were
+// needed to anything at or beneath that nesting level and so the caller should
+// just keep the original value exactly.
+//
+// Modifies topMarks and errs during traversal to collect (respectively) any
+// marks that caused [ctymarks.WrangleExpand] and and errors returned by
+// wrangle functions.
+func wrangleMarksDeep(v Value, wranglers []WrangleFunc, path Path, topMarks ValueMarks, errs *[]error) Value {
+ var givenMarks, newMarks ValueMarks
+ makeNewValue := false
+ // The following is the same idea as [Value.Unmark], but implemented inline
+ // here so that we can skip copying any existing ValueMarks that might
+ // already be present, since we know we're not going to try to mutate it.
+ if marked, ok := v.v.(marker); ok {
+ v = Value{
+ ty: v.ty,
+ v: marked.realV,
+ }
+ givenMarks = marked.marks
+ }
+
+ // We call this whenever we know we're returning a new value, to perform
+ // a one-time copy of the given marks into a new marks map we can modify
+ // and to set a flag to force us to construct a newly-marked value when
+ // we return below.
+ needNewValue := func() {
+ if newMarks == nil && len(givenMarks) != 0 {
+ newMarks = make(ValueMarks, len(givenMarks))
+ maps.Copy(newMarks, givenMarks)
+ }
+ makeNewValue = true
+ }
+
+ for mark := range givenMarks {
+ Wranglers:
+ for _, wrangler := range wranglers {
+ action, err := wrangler(mark, path)
+ if err != nil {
+ if len(path) != 0 {
+ err = path.NewError(err)
+ }
+ *errs = append(*errs, err)
+ }
+ switch action {
+ case nil:
+ continue Wranglers
+ case ctymarks.WrangleKeep:
+ break Wranglers
+ case ctymarks.WrangleExpand:
+ topMarks[mark] = struct{}{}
+ break Wranglers
+ case ctymarks.WrangleDrop:
+ needNewValue()
+ delete(newMarks, mark)
+ break Wranglers
+ default:
+ newMark := ctymarks.WrangleReplaceMark(action)
+ if newMark == nil {
+ // Should not get here because these cases should be
+ // exhaustive for all possible WrangleAction values.
+ panic(fmt.Sprintf("unhandled WrangleAction %#v", action))
+ }
+ needNewValue()
+ delete(newMarks, mark)
+ newMarks[newMark] = struct{}{}
+ break Wranglers
+ }
+ }
+ }
+
+ // We're not going to make any further changes to our _direct_ marks
+ // after this, so if we didn't already make a copy of the given marks
+ // we can now safely alias our original set to reuse when we return.
+ // (We might still construct a new value though, if we recurse into
+ // a nested value that needs its own changes.)
+ if newMarks == nil {
+ newMarks = givenMarks // might still be nil if we didn't have any marks on entry
+ }
+
+ // Now we'll visit nested values recursively, if any.
+ // The cases below intentionally don't cover primitive types, set types,
+ // or capsule types, because none of them can possibly have nested marks
+ // inside. (For set types in particular, any marks on inner values get
+ // aggregated on the top-level set itself during construction.)
+ ty := v.Type()
+ switch {
+ case v.IsNull() || !v.IsKnown():
+ // Can't recurse into null or unknown values, regardless of type,
+ // so nothing to do here.
+
+ case ty.IsListType() || ty.IsTupleType():
+ // These types both have the same internal representation, and we
+ // know we're not going to change anything about the type, so we
+ // can share the same implementation for both.
+ l := v.LengthInt()
+ if l == 0 {
+ break // nothing to do for an empty container
+ }
+
+ // We'll avoid allocating a new slice until we know we're going
+ // to make a change.
+ var newElems []any // as would appear in Value.v for all three of these types
+ for i, innerV := range replaceKWithIdx(v.Elements()) {
+ path := append(path, IndexStep{Key: NumberIntVal(int64(i))})
+ newInnerV := wrangleMarksDeep(innerV, wranglers, path, topMarks, errs)
+ if newInnerV != NilVal {
+ needNewValue()
+ if newElems == nil {
+ // If this is the first change we've found then we need to
+ // allocate our new elems array and retroactively copy
+ // anything we previously skipped because it was unchanged.
+ newElems = make([]any, i, l)
+ copy(newElems, v.v.([]any))
+ }
+ newElems = append(newElems, newInnerV.v)
+ } else if newElems != nil {
+ // Once we've started building a new value we need to append
+ // everything to it whether it's changed or not, but we can
+ // reuse the unchanged element's internal value.
+ newElems = append(newElems, innerV.v)
+ }
+ }
+ if newElems != nil {
+ // if we built a new array of elements then it should replace
+ // the one from our input value.
+ v.v = newElems
+ }
+
+ case ty.IsMapType() || ty.IsObjectType():
+ // These types both have the same internal representation, and we
+ // know we're not going to change anything about the type, so we
+ // can share the same implementation for both.
+ l := v.LengthInt()
+ if l == 0 {
+ break // nothing to do for an empty container
+ }
+
+ // We'll avoid allocating a new map until we know we're going to
+ // make a change.
+ var newElems map[string]any
+ for keyV, innerV := range v.Elements() {
+ var pathStep PathStep
+ if ty.IsObjectType() {
+ pathStep = GetAttrStep{Name: keyV.AsString()}
+ } else {
+ pathStep = IndexStep{Key: keyV}
+ }
+ path := append(path, pathStep)
+ newInnerV := wrangleMarksDeep(innerV, wranglers, path, topMarks, errs)
+ if newInnerV != NilVal {
+ needNewValue()
+ if newElems == nil {
+ // If this is the first change we've found then we need to
+ // allocate our new elems map and retroactively copy
+ // everything from the original map before we overwrite
+ // the elements that need to change.
+ newElems = make(map[string]any, l)
+ maps.Copy(newElems, v.v.(map[string]any))
+ }
+ newElems[keyV.AsString()] = newInnerV.v
+ }
+ }
+ if newElems != nil {
+ // if we built a new map of elements then it should replace
+ // the one from our input value.
+ v.v = newElems
+ }
+ }
+
+ if !makeNewValue {
+ // We didn't make any changes to the marks, so we don't need to
+ // construct a new value.
+ return NilVal
+ }
+ return v.WithMarks(newMarks)
+}
+
+// WrangleFunc is the signature of a callback function used to visit a
+// particular mark associated with a particular path within a value.
+//
+// [Path] values passed to successive calls to a [WrangleFunc] may share a
+// backing array, and so if the function wishes to retain a particular path
+// after it returns it must use [Path.Copy] to produce a copy in an unaliased
+// backing array.
+//
+// A function of this type must decide what change to make, if any, to the
+// presence of this mark at this location. Returning nil means to take no
+// action at all and to potentially allow other later functions of this
+// type to decide what to do instead.
+//
+// If the function returns an error then [Value.WrangleMarksDeep] collects it
+// and any other errors returned during traversal, automatically wraps in a
+// [cty.PathError] if not at the root, and returns an [`errors.Join`] of all
+// of the errors if there are more than one. The indicated action is still taken
+// and continued "wrangling" occurs as normal to visit other marks and other
+// paths.
+//
+// [cty.Value.WrangleMarksDeep], and this callback signature used with it,
+// are together designed with some assumptions that don't always hold but
+// have been common enough to make it seem worth supporting with a first-class
+// feature:
+//
+// - All of the different marks on any specific value are orthogonal to one
+// another, and so it's possible to decide an action for each one in
+// isolation.
+// - Marks within a data structure are orthogonal to the specific values they
+// are associated with, and so it's possible to decide an action without
+// knowning the value it's associated with. (Though it's possible in
+// principle to use the given path to retrieve more information when needed,
+// at the expense of some additional traversal overhead.)
+// - Most values have no marks at all and when marks are present there are
+// relatively few of them, and so it's worth making some extra effort to
+// handle the no-marks case cheaply even if it makes the marks-present case
+// a little more expensive.
+//
+// If any of these assumptions don't apply to your situation then this may not
+// be an appropriate solution. [cty.Transform] or [cty.TransformWithTransformer]
+// might serve as a more general alternative if you need more control.
+type WrangleFunc func(mark any, path Path) (ctymarks.WrangleAction, error)
+
+func replaceKWithIdx[K any, V any](in iter.Seq2[K, V]) iter.Seq2[int, V] {
+ return func(yield func(int, V) bool) {
+ i := 0
+ for _, v := range in {
+ if !yield(i, v) {
+ break
+ }
+ i++
+ }
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/null.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/null.go
new file mode 100644
index 00000000000..d58d0287b64
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/null.go
@@ -0,0 +1,14 @@
+package cty
+
+// NullVal returns a null value of the given type. A null can be created of any
+// type, but operations on such values will always panic. Calling applications
+// are encouraged to use nulls only sparingly, particularly when user-provided
+// expressions are to be evaluated, since the precence of nulls creates a
+// much higher chance of evaluation errors that can't be caught by a type
+// checker.
+func NullVal(t Type) Value {
+ return Value{
+ ty: t,
+ v: nil,
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/object_type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/object_type.go
new file mode 100644
index 00000000000..555ef6c7f20
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/object_type.go
@@ -0,0 +1,220 @@
+package cty
+
+import (
+ "fmt"
+ "sort"
+)
+
+type typeObject struct {
+ typeImplSigil
+ AttrTypes map[string]Type
+ AttrOptional map[string]struct{}
+}
+
+// Object creates an object type with the given attribute types.
+//
+// After a map is passed to this function the caller must no longer access it,
+// since ownership is transferred to this library.
+func Object(attrTypes map[string]Type) Type {
+ return ObjectWithOptionalAttrs(attrTypes, nil)
+}
+
+// ObjectWithOptionalAttrs creates an object type where some of its attributes
+// are optional.
+//
+// This function is EXPERIMENTAL. The behavior of the function or of any other
+// functions working either directly or indirectly with a type created by
+// this function is not currently considered as a compatibility constraint, and
+// is subject to change even in minor-version releases of this module. Other
+// modules that work with cty types and values may or may not support object
+// types with optional attributes; if they do not, their behavior when
+// receiving one may be non-ideal.
+//
+// Optional attributes are significant only when an object type is being used
+// as a target type for conversion in the "convert" package. A value of an
+// object type always has a value for each of the attributes in the attribute
+// types table, with optional values replaced with null during conversion.
+//
+// All keys in the optional slice must also exist in the attrTypes map. If not,
+// this function will panic.
+//
+// After a map or array is passed to this function the caller must no longer
+// access it, since ownership is transferred to this library.
+func ObjectWithOptionalAttrs(attrTypes map[string]Type, optional []string) Type {
+ attrTypesNorm := make(map[string]Type, len(attrTypes))
+ for k, v := range attrTypes {
+ attrTypesNorm[NormalizeString(k)] = v
+ }
+
+ var optionalSet map[string]struct{}
+ if len(optional) > 0 {
+ optionalSet = make(map[string]struct{}, len(optional))
+ for _, k := range optional {
+ k = NormalizeString(k)
+ if _, exists := attrTypesNorm[k]; !exists {
+ panic(fmt.Sprintf("optional contains undeclared attribute %q", k))
+ }
+ optionalSet[k] = struct{}{}
+ }
+ }
+
+ return Type{
+ typeObject{
+ AttrTypes: attrTypesNorm,
+ AttrOptional: optionalSet,
+ },
+ }
+}
+
+func (t typeObject) Equals(other Type) bool {
+ if ot, ok := other.typeImpl.(typeObject); ok {
+ if len(t.AttrTypes) != len(ot.AttrTypes) {
+ // Fast path: if we don't have the same number of attributes
+ // then we can't possibly be equal. This also avoids the need
+ // to test attributes in both directions below, since we know
+ // there can't be extras in "other".
+ return false
+ }
+
+ for attr, ty := range t.AttrTypes {
+ oty, ok := ot.AttrTypes[attr]
+ if !ok {
+ return false
+ }
+ if !oty.Equals(ty) {
+ return false
+ }
+ _, opt := t.AttrOptional[attr]
+ _, oopt := ot.AttrOptional[attr]
+ if opt != oopt {
+ return false
+ }
+ }
+
+ return true
+ }
+ return false
+}
+
+func (t typeObject) FriendlyName(mode friendlyTypeNameMode) string {
+ // There isn't really a friendly way to write an object type due to its
+ // complexity, so we'll just do something English-ish. Callers will
+ // probably want to make some extra effort to avoid ever printing out
+ // an object type FriendlyName in its entirety. For example, could
+ // produce an error message by diffing two object types and saying
+ // something like "Expected attribute foo to be string, but got number".
+ // TODO: Finish this
+ return "object"
+}
+
+func (t typeObject) GoString() string {
+ if len(t.AttrTypes) == 0 {
+ return "cty.EmptyObject"
+ }
+ if len(t.AttrOptional) > 0 {
+ var opt []string
+ for k := range t.AttrOptional {
+ opt = append(opt, k)
+ }
+ sort.Strings(opt)
+ return fmt.Sprintf("cty.ObjectWithOptionalAttrs(%#v, %#v)", t.AttrTypes, opt)
+ }
+ return fmt.Sprintf("cty.Object(%#v)", t.AttrTypes)
+}
+
+// EmptyObject is a shorthand for Object(map[string]Type{}), to more
+// easily talk about the empty object type.
+var EmptyObject Type
+
+// EmptyObjectVal is the only possible non-null, non-unknown value of type
+// EmptyObject.
+var EmptyObjectVal Value
+
+func init() {
+ EmptyObject = Object(map[string]Type{})
+ EmptyObjectVal = Value{
+ ty: EmptyObject,
+ v: map[string]any{},
+ }
+}
+
+// IsObjectType returns true if the given type is an object type, regardless
+// of its element type.
+func (t Type) IsObjectType() bool {
+ _, ok := t.typeImpl.(typeObject)
+ return ok
+}
+
+// HasAttribute returns true if the receiver has an attribute with the given
+// name, regardless of its type. Will panic if the reciever isn't an object
+// type; use IsObjectType to determine whether this operation will succeed.
+func (t Type) HasAttribute(name string) bool {
+ name = NormalizeString(name)
+ if ot, ok := t.typeImpl.(typeObject); ok {
+ _, hasAttr := ot.AttrTypes[name]
+ return hasAttr
+ }
+ panic("HasAttribute on non-object Type")
+}
+
+// AttributeType returns the type of the attribute with the given name. Will
+// panic if the receiver is not an object type (use IsObjectType to confirm)
+// or if the object type has no such attribute (use HasAttribute to confirm).
+func (t Type) AttributeType(name string) Type {
+ name = NormalizeString(name)
+ if ot, ok := t.typeImpl.(typeObject); ok {
+ aty, hasAttr := ot.AttrTypes[name]
+ if !hasAttr {
+ panic("no such attribute")
+ }
+ return aty
+ }
+ panic("AttributeType on non-object Type")
+}
+
+// AttributeTypes returns a map from attribute names to their associated
+// types. Will panic if the receiver is not an object type (use IsObjectType
+// to confirm).
+//
+// The returned map is part of the internal state of the type, and is provided
+// for read access only. It is forbidden for any caller to modify the returned
+// map. For many purposes the attribute-related methods of Value are more
+// appropriate and more convenient to use.
+func (t Type) AttributeTypes() map[string]Type {
+ if ot, ok := t.typeImpl.(typeObject); ok {
+ return ot.AttrTypes
+ }
+ panic("AttributeTypes on non-object Type")
+}
+
+// OptionalAttributes returns a map representing the set of attributes
+// that are optional. Will panic if the receiver is not an object type
+// (use IsObjectType to confirm).
+//
+// The returned map is part of the internal state of the type, and is provided
+// for read access only. It is forbidden for any caller to modify the returned
+// map.
+func (t Type) OptionalAttributes() map[string]struct{} {
+ if ot, ok := t.typeImpl.(typeObject); ok {
+ return ot.AttrOptional
+ }
+ panic("OptionalAttributes on non-object Type")
+}
+
+// AttributeOptional returns true if the attribute of the given name is
+// optional.
+//
+// Will panic if the receiver is not an object type (use IsObjectType to
+// confirm) or if the object type has no such attribute (use HasAttribute to
+// confirm).
+func (t Type) AttributeOptional(name string) bool {
+ name = NormalizeString(name)
+ if ot, ok := t.typeImpl.(typeObject); ok {
+ if _, hasAttr := ot.AttrTypes[name]; !hasAttr {
+ panic("no such attribute")
+ }
+ _, exists := ot.AttrOptional[name]
+ return exists
+ }
+ panic("AttributeDefaultValue on non-object Type")
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/path.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/path.go
new file mode 100644
index 00000000000..2049bb5b6ad
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/path.go
@@ -0,0 +1,302 @@
+package cty
+
+import (
+ "errors"
+ "fmt"
+)
+
+// A Path is a sequence of operations to locate a nested value within a
+// data structure.
+//
+// The empty Path represents the given item. Any PathSteps within represent
+// taking a single step down into a data structure.
+//
+// Path has some convenience methods for gradually constructing a path,
+// but callers can also feel free to just produce a slice of PathStep manually
+// and convert to this type, which may be more appropriate in environments
+// where memory pressure is a concern.
+//
+// Although a Path is technically mutable, by convention callers should not
+// mutate a path once it has been built and passed to some other subsystem.
+// Instead, use Copy and then mutate the copy before using it.
+type Path []PathStep
+
+// PathStep represents a single step down into a data structure, as part
+// of a Path. PathStep is a closed interface, meaning that the only
+// permitted implementations are those within this package.
+type PathStep interface {
+ pathStepSigil() pathStepImpl
+ Apply(Value) (Value, error)
+}
+
+// embed pathImpl into a struct to declare it a PathStep implementation
+type pathStepImpl struct{}
+
+func (p pathStepImpl) pathStepSigil() pathStepImpl {
+ return p
+}
+
+// Index returns a new Path that is the reciever with an IndexStep appended
+// to the end.
+//
+// This is provided as a convenient way to construct paths, but each call
+// will create garbage so it should not be used where memory pressure is a
+// concern.
+func (p Path) Index(v Value) Path {
+ ret := make(Path, len(p)+1)
+ copy(ret, p)
+ ret[len(p)] = IndexStep{
+ Key: v,
+ }
+ return ret
+}
+
+// IndexInt is a typed convenience method for Index.
+func (p Path) IndexInt(v int) Path {
+ return p.Index(NumberIntVal(int64(v)))
+}
+
+// IndexString is a typed convenience method for Index.
+func (p Path) IndexString(v string) Path {
+ return p.Index(StringVal(v))
+}
+
+// IndexPath is a convenience method to start a new Path with an IndexStep.
+func IndexPath(v Value) Path {
+ return Path{}.Index(v)
+}
+
+// IndexIntPath is a typed convenience method for IndexPath.
+func IndexIntPath(v int) Path {
+ return IndexPath(NumberIntVal(int64(v)))
+}
+
+// IndexStringPath is a typed convenience method for IndexPath.
+func IndexStringPath(v string) Path {
+ return IndexPath(StringVal(v))
+}
+
+// GetAttr returns a new Path that is the reciever with a GetAttrStep appended
+// to the end.
+//
+// This is provided as a convenient way to construct paths, but each call
+// will create garbage so it should not be used where memory pressure is a
+// concern.
+func (p Path) GetAttr(name string) Path {
+ ret := make(Path, len(p)+1)
+ copy(ret, p)
+ ret[len(p)] = GetAttrStep{
+ Name: name,
+ }
+ return ret
+}
+
+// Equals compares 2 Paths for exact equality.
+func (p Path) Equals(other Path) bool {
+ if len(p) != len(other) {
+ return false
+ }
+
+ for i := range p {
+ pv := p[i]
+ switch pv := pv.(type) {
+ case GetAttrStep:
+ ov, ok := other[i].(GetAttrStep)
+ if !ok || pv != ov {
+ return false
+ }
+ case IndexStep:
+ ov, ok := other[i].(IndexStep)
+ if !ok {
+ return false
+ }
+
+ if !pv.Key.RawEquals(ov.Key) {
+ return false
+ }
+ default:
+ // Any invalid steps default to evaluating false.
+ return false
+ }
+ }
+
+ return true
+
+}
+
+// HasPrefix determines if the path p contains the provided prefix.
+func (p Path) HasPrefix(prefix Path) bool {
+ if len(prefix) > len(p) {
+ return false
+ }
+
+ return p[:len(prefix)].Equals(prefix)
+}
+
+// GetAttrPath is a convenience method to start a new Path with a GetAttrStep.
+func GetAttrPath(name string) Path {
+ return Path{}.GetAttr(name)
+}
+
+// Apply applies each of the steps in turn to successive values starting with
+// the given value, and returns the result. If any step returns an error,
+// the whole operation returns an error.
+func (p Path) Apply(val Value) (Value, error) {
+ var err error
+ for i, step := range p {
+ val, err = step.Apply(val)
+ if err != nil {
+ return NilVal, fmt.Errorf("at step %d: %s", i, err)
+ }
+ }
+ return val, nil
+}
+
+// LastStep applies the given path up to the last step and then returns
+// the resulting value and the final step.
+//
+// This is useful when dealing with assignment operations, since in that
+// case the *value* of the last step is not important (and may not, in fact,
+// present at all) and we care only about its location.
+//
+// Since LastStep applies all steps except the last, it will return errors
+// for those steps in the same way as Apply does.
+//
+// If the path has *no* steps then the returned PathStep will be nil,
+// representing that any operation should be applied directly to the
+// given value.
+func (p Path) LastStep(val Value) (Value, PathStep, error) {
+ var err error
+
+ if len(p) == 0 {
+ return val, nil, nil
+ }
+
+ journey := p[:len(p)-1]
+ val, err = journey.Apply(val)
+ if err != nil {
+ return NilVal, nil, err
+ }
+ return val, p[len(p)-1], nil
+}
+
+// Copy makes a shallow copy of the receiver. Often when paths are passed to
+// caller code they come with the constraint that they are valid only until
+// the caller returns, due to how they are constructed internally. Callers
+// can use Copy to conveniently produce a copy of the value that _they_ control
+// the validity of.
+func (p Path) Copy() Path {
+ ret := make(Path, len(p))
+ copy(ret, p)
+ return ret
+}
+
+// IndexStep is a Step implementation representing applying the index operation
+// to a value, which must be of either a list, map, or set type.
+//
+// When describing a path through a *type* rather than a concrete value,
+// the Key may be an unknown value, indicating that the step applies to
+// *any* key of the given type.
+//
+// When indexing into a set, the Key is actually the element being accessed
+// itself, since in sets elements are their own identity. Applying such an
+// index step to a set will test if the key is present in the set and return
+// it if so, but note that if the key contains any unknown values then the
+// result is itself an unknown value because we cannot know whether the element
+// is present or not.
+type IndexStep struct {
+ pathStepImpl
+ Key Value
+}
+
+// Apply returns the value resulting from indexing the given value with
+// our key value.
+func (s IndexStep) Apply(val Value) (Value, error) {
+ if val == NilVal || val.IsNull() {
+ return NilVal, errors.New("cannot index a null value")
+ }
+
+ if valType := val.Type(); valType.IsSetType() {
+ // Indexing into a set with [Value.Index] is not allowed because
+ // sets don't have indices, but [Path] is often used to describe
+ // the current location in a nested data structure when working
+ // with functions like [Walk] or [Transform] and in that case
+ // traversal into a set is represented as an IndexStep whose
+ // key is the set element value itself, with the idea that a set
+ // element effectively acts as its own "key" in the set.
+ //
+ // To make it possible to use that kind of path with [Path.Apply],
+ // we have a special case here: if the index step's key is in the
+ // set then we return that value.
+ markedPresent := val.HasElement(s.Key)
+ present, marks := markedPresent.Unmark()
+ if !present.IsKnown() {
+ return UnknownVal(valType.ElementType()).WithMarks(marks), nil
+ }
+ if present.False() {
+ return NilVal, errors.New("set does not contain the requested element")
+ }
+ // We transfer the marks from the set here too, which is sufficient
+ // because cty cannot not preserve marks deeply within a set so they
+ // always aggregate onto the set as a whole during set construction.
+ return s.Key.WithMarks(marks), nil
+ }
+
+ switch s.Key.Type() {
+ case Number:
+ if !(val.Type().IsListType() || val.Type().IsTupleType()) {
+ return NilVal, errors.New("not a list type")
+ }
+ case String:
+ if !val.Type().IsMapType() {
+ return NilVal, errors.New("not a map type")
+ }
+ default:
+ return NilVal, errors.New("key value not number or string")
+ }
+
+ // This value needs to be stripped of marks to check True(), but Index will
+ // apply the correct marks for the result.
+ has, _ := val.HasIndex(s.Key).Unmark()
+ if !has.IsKnown() {
+ return UnknownVal(val.Type().ElementType()), nil
+ }
+ if !has.True() {
+ return NilVal, errors.New("value does not have given index key")
+ }
+
+ return val.Index(s.Key), nil
+}
+
+func (s IndexStep) GoString() string {
+ return fmt.Sprintf("cty.IndexStep{Key:%#v}", s.Key)
+}
+
+// GetAttrStep is a Step implementation representing retrieving an attribute
+// from a value, which must be of an object type.
+type GetAttrStep struct {
+ pathStepImpl
+ Name string
+}
+
+// Apply returns the value of our named attribute from the given value, which
+// must be of an object type that has a value of that name.
+func (s GetAttrStep) Apply(val Value) (Value, error) {
+ if val == NilVal || val.IsNull() {
+ return NilVal, errors.New("cannot access attributes on a null value")
+ }
+
+ if !val.Type().IsObjectType() {
+ return NilVal, errors.New("not an object type")
+ }
+
+ if !val.Type().HasAttribute(s.Name) {
+ return NilVal, fmt.Errorf("object has no attribute %q", s.Name)
+ }
+
+ return val.GetAttr(s.Name), nil
+}
+
+func (s GetAttrStep) GoString() string {
+ return fmt.Sprintf("cty.GetAttrStep{Name:%q}", s.Name)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/path_set.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/path_set.go
new file mode 100644
index 00000000000..3ebfdc3859d
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/path_set.go
@@ -0,0 +1,200 @@
+package cty
+
+import (
+ "fmt"
+ "hash/crc64"
+
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// PathSet represents a set of Path objects. This can be used, for example,
+// to talk about a subset of paths within a value that meet some criteria,
+// without directly modifying the values at those paths.
+type PathSet struct {
+ set set.Set[Path]
+}
+
+// NewPathSet creates and returns a PathSet, with initial contents optionally
+// set by the given arguments.
+func NewPathSet(paths ...Path) PathSet {
+ ret := PathSet{
+ set: set.NewSet(set.Rules[Path](pathSetRules{})),
+ }
+
+ for _, path := range paths {
+ ret.Add(path)
+ }
+
+ return ret
+}
+
+// Add inserts a single given path into the set.
+//
+// Paths are immutable after construction by convention. It is particularly
+// important not to mutate a path after it has been placed into a PathSet.
+// If a Path is mutated while in a set, behavior is undefined.
+func (s PathSet) Add(path Path) {
+ s.set.Add(path)
+}
+
+// AddAllSteps is like Add but it also adds all of the steps leading to
+// the given path.
+//
+// For example, if given a path representing "foo.bar", it will add both
+// "foo" and "bar".
+func (s PathSet) AddAllSteps(path Path) {
+ for i := 1; i <= len(path); i++ {
+ s.Add(path[:i])
+ }
+}
+
+// Has returns true if the given path is in the receiving set.
+func (s PathSet) Has(path Path) bool {
+ return s.set.Has(path)
+}
+
+// List makes and returns a slice of all of the paths in the receiving set,
+// in an undefined but consistent order.
+func (s PathSet) List() []Path {
+ if s.Empty() {
+ return nil
+ }
+ ret := make([]Path, 0, s.set.Length())
+ for it := s.set.Iterator(); it.Next(); {
+ ret = append(ret, it.Value())
+ }
+ return ret
+}
+
+// Remove modifies the receving set to no longer include the given path.
+// If the given path was already absent, this is a no-op.
+func (s PathSet) Remove(path Path) {
+ s.set.Remove(path)
+}
+
+// Empty returns true if the length of the receiving set is zero.
+func (s PathSet) Empty() bool {
+ return s.set.Length() == 0
+}
+
+// Union returns a new set whose contents are the union of the receiver and
+// the given other set.
+func (s PathSet) Union(other PathSet) PathSet {
+ return PathSet{
+ set: s.set.Union(other.set),
+ }
+}
+
+// Intersection returns a new set whose contents are the intersection of the
+// receiver and the given other set.
+func (s PathSet) Intersection(other PathSet) PathSet {
+ return PathSet{
+ set: s.set.Intersection(other.set),
+ }
+}
+
+// Subtract returns a new set whose contents are those from the receiver with
+// any elements of the other given set subtracted.
+func (s PathSet) Subtract(other PathSet) PathSet {
+ return PathSet{
+ set: s.set.Subtract(other.set),
+ }
+}
+
+// SymmetricDifference returns a new set whose contents are the symmetric
+// difference of the receiver and the given other set.
+func (s PathSet) SymmetricDifference(other PathSet) PathSet {
+ return PathSet{
+ set: s.set.SymmetricDifference(other.set),
+ }
+}
+
+// Equal returns true if and only if both the receiver and the given other
+// set contain exactly the same paths.
+func (s PathSet) Equal(other PathSet) bool {
+ if s.set.Length() != other.set.Length() {
+ return false
+ }
+ // Now we know the lengths are the same we only need to test in one
+ // direction whether everything in one is in the other.
+ for it := s.set.Iterator(); it.Next(); {
+ if !other.set.Has(it.Value()) {
+ return false
+ }
+ }
+ return true
+}
+
+var crc64Table = crc64.MakeTable(crc64.ISO)
+
+var indexStepPlaceholder = []byte("#")
+
+// pathSetRules is an implementation of set.Rules from the set package,
+// used internally within PathSet.
+type pathSetRules struct {
+}
+
+func (r pathSetRules) Hash(path Path) int {
+ hash := crc64.New(crc64Table)
+
+ for _, rawStep := range path {
+ switch step := rawStep.(type) {
+ case GetAttrStep:
+ // (this creates some garbage converting the string name to a
+ // []byte, but that's okay since cty is not designed to be
+ // used in tight loops under memory pressure.)
+ hash.Write([]byte(step.Name))
+ default:
+ // For any other step type we just append a predefined value,
+ // which means that e.g. all indexes into a given collection will
+ // hash to the same value but we assume that collections are
+ // small and thus this won't hurt too much.
+ hash.Write(indexStepPlaceholder)
+ }
+ }
+
+ // We discard half of the hash on 32-bit platforms; collisions just make
+ // our lookups take marginally longer, so not a big deal.
+ return int(hash.Sum64())
+}
+
+func (r pathSetRules) Equivalent(aPath, bPath Path) bool {
+ if len(aPath) != len(bPath) {
+ return false
+ }
+
+ for i := range aPath {
+ switch aStep := aPath[i].(type) {
+ case GetAttrStep:
+ bStep, ok := bPath[i].(GetAttrStep)
+ if !ok {
+ return false
+ }
+
+ if aStep.Name != bStep.Name {
+ return false
+ }
+ case IndexStep:
+ bStep, ok := bPath[i].(IndexStep)
+ if !ok {
+ return false
+ }
+
+ eq := aStep.Key.Equals(bStep.Key)
+ if !eq.IsKnown() || eq.False() {
+ return false
+ }
+ default:
+ // Should never happen, since we document PathStep as a closed type.
+ panic(fmt.Errorf("unsupported step type %T", aStep))
+ }
+ }
+
+ return true
+}
+
+// SameRules is true if both Rules instances are pathSetRules structs.
+func (r pathSetRules) SameRules(other set.Rules[Path]) bool {
+ _, ok := other.(pathSetRules)
+ return ok
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/primitive_type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
new file mode 100644
index 00000000000..2beea652d87
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/primitive_type.go
@@ -0,0 +1,183 @@
+package cty
+
+import (
+ "math/big"
+)
+
+// primitiveType is the hidden implementation of the various primitive types
+// that are exposed as variables in this package.
+type primitiveType struct {
+ typeImplSigil
+ Kind primitiveTypeKind
+}
+
+type primitiveTypeKind byte
+
+const (
+ primitiveTypeBool primitiveTypeKind = 'B'
+ primitiveTypeNumber primitiveTypeKind = 'N'
+ primitiveTypeString primitiveTypeKind = 'S'
+)
+
+func (t primitiveType) Equals(other Type) bool {
+ if otherP, ok := other.typeImpl.(primitiveType); ok {
+ return otherP.Kind == t.Kind
+ }
+ return false
+}
+
+func (t primitiveType) FriendlyName(mode friendlyTypeNameMode) string {
+ switch t.Kind {
+ case primitiveTypeBool:
+ return "bool"
+ case primitiveTypeNumber:
+ return "number"
+ case primitiveTypeString:
+ return "string"
+ default:
+ // should never happen
+ panic("invalid primitive type")
+ }
+}
+
+func (t primitiveType) GoString() string {
+ switch t.Kind {
+ case primitiveTypeBool:
+ return "cty.Bool"
+ case primitiveTypeNumber:
+ return "cty.Number"
+ case primitiveTypeString:
+ return "cty.String"
+ default:
+ // should never happen
+ panic("invalid primitive type")
+ }
+}
+
+// rawNumberEqual is our cty-specific definition of whether two big floats
+// underlying cty.Number are "equal" for the purposes of the Value.Equals and
+// Value.RawEquals methods.
+//
+// The built-in equality for big.Float is a direct comparison of the mantissa
+// bits and the exponent, but that's too precise a check for cty because we
+// routinely send numbers through decimal approximations and back and so
+// we only promise to accurately represent the subset of binary floating point
+// numbers that can be derived from a decimal string representation.
+//
+// In respect of the fact that cty only tries to preserve numbers that can
+// reasonably be written in JSON documents, we use the string representation of
+// a decimal approximation of the number as our comparison, relying on the
+// big.Float type's heuristic for discarding extraneous mantissa bits that seem
+// likely to only be there as a result of an earlier decimal-to-binary
+// approximation during parsing, e.g. in ParseNumberVal.
+func rawNumberEqual(a, b *big.Float) bool {
+ switch {
+ case (a == nil) != (b == nil):
+ return false
+ case a == nil: // b == nil too then, due to previous case
+ return true
+ case a.Sign() != b.Sign():
+ return false
+ default:
+ // First check if these are integers, and compare them directly. Floats
+ // need a more nuanced approach.
+ aInt, aAcc := a.Int(nil)
+ bInt, bAcc := b.Int(nil)
+ if aAcc != bAcc {
+ // only one is an exact integer value, so they can't be equal
+ return false
+ }
+ if aAcc == big.Exact {
+ return aInt.Cmp(bInt) == 0
+ }
+
+ // This format and precision matches that used by cty/json.Marshal,
+ // and thus achieves our definition of "two numbers are equal if
+ // we'd use the same JSON serialization for both of them".
+ const format = 'f'
+ const prec = -1
+ aStr := a.Text(format, prec)
+ bStr := b.Text(format, prec)
+
+ // The one exception to our rule about equality-by-stringification is
+ // negative zero, because we want -0 to always be equal to +0.
+ const posZero = "0"
+ const negZero = "-0"
+ if aStr == negZero {
+ aStr = posZero
+ }
+ if bStr == negZero {
+ bStr = posZero
+ }
+ return aStr == bStr
+ }
+}
+
+// Number is the numeric type. Number values are arbitrary-precision
+// decimal numbers, which can then be converted into Go's various numeric
+// types only if they are in the appropriate range.
+var Number Type
+
+// String is the string type. String values are sequences of unicode codepoints
+// encoded internally as UTF-8.
+var String Type
+
+// Bool is the boolean type. The two values of this type are True and False.
+var Bool Type
+
+// True is the truthy value of type Bool
+var True Value
+
+// False is the falsey value of type Bool
+var False Value
+
+// Zero is a number value representing exactly zero.
+var Zero Value
+
+// PositiveInfinity is a Number value representing positive infinity
+var PositiveInfinity Value
+
+// NegativeInfinity is a Number value representing negative infinity
+var NegativeInfinity Value
+
+func init() {
+ Number = Type{
+ primitiveType{Kind: primitiveTypeNumber},
+ }
+ String = Type{
+ primitiveType{Kind: primitiveTypeString},
+ }
+ Bool = Type{
+ primitiveType{Kind: primitiveTypeBool},
+ }
+ True = Value{
+ ty: Bool,
+ v: true,
+ }
+ False = Value{
+ ty: Bool,
+ v: false,
+ }
+ Zero = Value{
+ ty: Number,
+ v: big.NewFloat(0),
+ }
+ PositiveInfinity = Value{
+ ty: Number,
+ v: (&big.Float{}).SetInf(false),
+ }
+ NegativeInfinity = Value{
+ ty: Number,
+ v: (&big.Float{}).SetInf(true),
+ }
+}
+
+// IsPrimitiveType returns true if and only if the reciever is a primitive
+// type, which means it's either number, string, or bool. Any two primitive
+// types can be safely compared for equality using the standard == operator
+// without panic, which is not a guarantee that holds for all types. Primitive
+// types can therefore also be used in switch statements.
+func (t Type) IsPrimitiveType() bool {
+ _, ok := t.typeImpl.(primitiveType)
+ return ok
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/iterator.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
new file mode 100644
index 00000000000..60825b0c2de
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/iterator.go
@@ -0,0 +1,15 @@
+package set
+
+type Iterator[T any] struct {
+ vals []T
+ idx int
+}
+
+func (it *Iterator[T]) Value() T {
+ return it.vals[it.idx]
+}
+
+func (it *Iterator[T]) Next() bool {
+ it.idx++
+ return it.idx < len(it.vals)
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/ops.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/ops.go
new file mode 100644
index 00000000000..ffd950ac6b3
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/ops.go
@@ -0,0 +1,210 @@
+package set
+
+import (
+ "sort"
+)
+
+// Add inserts the given value into the receiving Set.
+//
+// This mutates the set in-place. This operation is not thread-safe.
+func (s Set[T]) Add(val T) {
+ hv := s.rules.Hash(val)
+ if _, ok := s.vals[hv]; !ok {
+ s.vals[hv] = make([]T, 0, 1)
+ }
+ bucket := s.vals[hv]
+
+ // See if an equivalent value is already present
+ for _, ev := range bucket {
+ if s.rules.Equivalent(val, ev) {
+ return
+ }
+ }
+
+ s.vals[hv] = append(bucket, val)
+}
+
+// Remove deletes the given value from the receiving set, if indeed it was
+// there in the first place. If the value is not present, this is a no-op.
+func (s Set[T]) Remove(val T) {
+ hv := s.rules.Hash(val)
+ bucket, ok := s.vals[hv]
+ if !ok {
+ return
+ }
+
+ for i, ev := range bucket {
+ if s.rules.Equivalent(val, ev) {
+ newBucket := make([]T, 0, len(bucket)-1)
+ newBucket = append(newBucket, bucket[:i]...)
+ newBucket = append(newBucket, bucket[i+1:]...)
+ if len(newBucket) > 0 {
+ s.vals[hv] = newBucket
+ } else {
+ delete(s.vals, hv)
+ }
+ return
+ }
+ }
+}
+
+// Has returns true if the given value is in the receiving set, or false if
+// it is not.
+func (s Set[T]) Has(val T) bool {
+ hv := s.rules.Hash(val)
+ bucket, ok := s.vals[hv]
+ if !ok {
+ return false
+ }
+
+ for _, ev := range bucket {
+ if s.rules.Equivalent(val, ev) {
+ return true
+ }
+ }
+ return false
+}
+
+// Copy performs a shallow copy of the receiving set, returning a new set
+// with the same rules and elements.
+func (s Set[T]) Copy() Set[T] {
+ ret := NewSet(s.rules)
+ for k, v := range s.vals {
+ ret.vals[k] = v
+ }
+ return ret
+}
+
+// Iterator returns an iterator over values in the set. If the set's rules
+// implement OrderedRules then the result is ordered per those rules. If
+// no order is provided, or if it is not a total order, then the iteration
+// order is undefined but consistent for a particular version of cty. Do not
+// rely on specific ordering between cty releases unless the rules order is a
+// total order.
+//
+// The pattern for using the returned iterator is:
+//
+// it := set.Iterator()
+// for it.Next() {
+// val := it.Value()
+// // ...
+// }
+//
+// Once an iterator has been created for a set, the set *must not* be mutated
+// until the iterator is no longer in use.
+func (s Set[T]) Iterator() *Iterator[T] {
+ vals := s.Values()
+
+ return &Iterator[T]{
+ vals: vals,
+ idx: -1,
+ }
+}
+
+// EachValue calls the given callback once for each value in the set, in an
+// undefined order that callers should not depend on.
+func (s Set[T]) EachValue(cb func(T)) {
+ it := s.Iterator()
+ for it.Next() {
+ cb(it.Value())
+ }
+}
+
+// Values returns a slice of all the values in the set. If the set rules have
+// an order then the result is in that order. If no order is provided or if
+// it is not a total order then the result order is undefined, but consistent
+// for a particular set value within a specific release of cty.
+func (s Set[T]) Values() []T {
+ var ret []T
+ // Sort the bucketIds to ensure that we always traverse in a
+ // consistent order.
+ bucketIDs := make([]int, 0, len(s.vals))
+ for id := range s.vals {
+ bucketIDs = append(bucketIDs, id)
+ }
+ sort.Ints(bucketIDs)
+
+ for _, bucketID := range bucketIDs {
+ ret = append(ret, s.vals[bucketID]...)
+ }
+
+ if orderRules, ok := s.rules.(OrderedRules[T]); ok {
+ sort.SliceStable(ret, func(i, j int) bool {
+ return orderRules.Less(ret[i], ret[j])
+ })
+ }
+
+ return ret
+}
+
+// Length returns the number of values in the set.
+func (s Set[T]) Length() int {
+ var count int
+ for _, bucket := range s.vals {
+ count = count + len(bucket)
+ }
+ return count
+}
+
+// Union returns a new set that contains all of the members of both the
+// receiving set and the given set. Both sets must have the same rules, or
+// else this function will panic.
+func (s1 Set[T]) Union(s2 Set[T]) Set[T] {
+ mustHaveSameRules(s1, s2)
+ rs := NewSet(s1.rules)
+ s1.EachValue(func(v T) {
+ rs.Add(v)
+ })
+ s2.EachValue(func(v T) {
+ rs.Add(v)
+ })
+ return rs
+}
+
+// Intersection returns a new set that contains the values that both the
+// receiver and given sets have in common. Both sets must have the same rules,
+// or else this function will panic.
+func (s1 Set[T]) Intersection(s2 Set[T]) Set[T] {
+ mustHaveSameRules(s1, s2)
+ rs := NewSet(s1.rules)
+ s1.EachValue(func(v T) {
+ if s2.Has(v) {
+ rs.Add(v)
+ }
+ })
+ return rs
+}
+
+// Subtract returns a new set that contains all of the values from the receiver
+// that are not also in the given set. Both sets must have the same rules,
+// or else this function will panic.
+func (s1 Set[T]) Subtract(s2 Set[T]) Set[T] {
+ mustHaveSameRules(s1, s2)
+ rs := NewSet(s1.rules)
+ s1.EachValue(func(v T) {
+ if !s2.Has(v) {
+ rs.Add(v)
+ }
+ })
+ return rs
+}
+
+// SymmetricDifference returns a new set that contains all of the values from
+// both the receiver and given sets, except those that both sets have in
+// common. Both sets must have the same rules, or else this function will
+// panic.
+func (s1 Set[T]) SymmetricDifference(s2 Set[T]) Set[T] {
+ mustHaveSameRules(s1, s2)
+ rs := NewSet(s1.rules)
+ s1.EachValue(func(v T) {
+ if !s2.Has(v) {
+ rs.Add(v)
+ }
+ })
+ s2.EachValue(func(v T) {
+ if !s1.Has(v) {
+ rs.Add(v)
+ }
+ })
+ return rs
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/rules.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/rules.go
new file mode 100644
index 00000000000..caffc5e1e9a
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/rules.go
@@ -0,0 +1,47 @@
+package set
+
+// Rules represents the operations that define membership for a Set.
+//
+// Each Set has a Rules instance, whose methods must satisfy the interface
+// contracts given below for any value that will be added to the set.
+type Rules[T any] interface {
+ // Hash returns an int that somewhat-uniquely identifies the given value.
+ //
+ // A good hash function will minimize collisions for values that will be
+ // added to the set, though collisions *are* permitted. Collisions will
+ // simply reduce the efficiency of operations on the set.
+ Hash(T) int
+
+ // Equivalent returns true if and only if the two values are considered
+ // equivalent for the sake of set membership. Two values that are
+ // equivalent cannot exist in the set at the same time, and if two
+ // equivalent values are added it is undefined which one will be
+ // returned when enumerating all of the set members.
+ //
+ // Two values that are equivalent *must* result in the same hash value,
+ // though it is *not* required that two values with the same hash value
+ // be equivalent.
+ Equivalent(T, T) bool
+
+ // SameRules returns true if the instance is equivalent to another Rules
+ // instance over the same element type.
+ SameRules(Rules[T]) bool
+}
+
+// OrderedRules is an extension of Rules that can apply a partial order to
+// element values. When a set's Rules implements OrderedRules an iterator
+// over the set will return items in the order described by the rules.
+//
+// If the given order is not a total order (that is, some pairs of non-equivalent
+// elements do not have a defined order) then the resulting iteration order
+// is undefined but consistent for a particular version of cty. The exact
+// order in that case is not part of the contract and is subject to change
+// between versions.
+type OrderedRules[T any] interface {
+ Rules[T]
+
+ // Less returns true if and only if the first argument should sort before
+ // the second argument. If the second argument should sort before the first
+ // or if there is no defined order for the values, return false.
+ Less(any, any) bool
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/set.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/set.go
new file mode 100644
index 00000000000..761b0ffe9f3
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set/set.go
@@ -0,0 +1,62 @@
+package set
+
+import (
+ "fmt"
+)
+
+// Set is an implementation of the concept of a set: a collection where all
+// values are conceptually either in or out of the set, but the members are
+// not ordered.
+//
+// This type primarily exists to be the internal type of sets in cty, but
+// it is considered to be at the same level of abstraction as Go's built in
+// slice and map collection types, and so should make no cty-specific
+// assumptions.
+//
+// Set operations are not thread safe. It is the caller's responsibility to
+// provide mutex guarantees where necessary.
+//
+// Set operations are not optimized to minimize memory pressure. Mutating
+// a set will generally create garbage and so should perhaps be avoided in
+// tight loops where memory pressure is a concern.
+type Set[T any] struct {
+ vals map[int][]T
+ rules Rules[T]
+}
+
+// NewSet returns an empty set with the membership rules given.
+func NewSet[T any](rules Rules[T]) Set[T] {
+ return Set[T]{
+ vals: map[int][]T{},
+ rules: rules,
+ }
+}
+
+func NewSetFromSlice[T any](rules Rules[T], vals []T) Set[T] {
+ s := NewSet(rules)
+ for _, v := range vals {
+ s.Add(v)
+ }
+ return s
+}
+
+func sameRules[T any](s1 Set[T], s2 Set[T]) bool {
+ return s1.rules.SameRules(s2.rules)
+}
+
+func mustHaveSameRules[T any](s1 Set[T], s2 Set[T]) {
+ if !sameRules(s1, s2) {
+ panic(fmt.Errorf("incompatible set rules: %#v, %#v", s1.rules, s2.rules))
+ }
+}
+
+// HasRules returns true if and only if the receiving set has the given rules
+// instance as its rules.
+func (s Set[T]) HasRules(rules Rules[T]) bool {
+ return s.rules.SameRules(rules)
+}
+
+// Rules returns the receiving set's rules instance.
+func (s Set[T]) Rules() Rules[T] {
+ return s.rules
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_helper.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_helper.go
new file mode 100644
index 00000000000..f309081e83b
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_helper.go
@@ -0,0 +1,132 @@
+package cty
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// ValueSet is to cty.Set what []cty.Value is to cty.List and
+// map[string]cty.Value is to cty.Map. It's provided to allow callers a
+// convenient interface for manipulating sets before wrapping them in cty.Set
+// values using cty.SetValFromValueSet.
+//
+// Unlike value slices and value maps, ValueSet instances have a single
+// homogenous element type because that is a requirement of the underlying
+// set implementation, which uses the element type to select a suitable
+// hashing function.
+//
+// Set mutations are not concurrency-safe.
+type ValueSet struct {
+ // ValueSet is just a thin wrapper around a set.Set with our value-oriented
+ // "rules" applied. We do this so that the caller can work in terms of
+ // cty.Value objects even though the set internals use the raw values.
+ s set.Set[any]
+}
+
+// NewValueSet creates and returns a new ValueSet with the given element type.
+func NewValueSet(ety Type) ValueSet {
+ return newValueSet(set.NewSet(newSetRules(ety)))
+}
+
+func newValueSet(s set.Set[any]) ValueSet {
+ return ValueSet{
+ s: s,
+ }
+}
+
+// ElementType returns the element type for the receiving ValueSet.
+func (s ValueSet) ElementType() Type {
+ return s.s.Rules().(setRules).Type
+}
+
+// Add inserts the given value into the receiving set.
+func (s ValueSet) Add(v Value) {
+ s.requireElementType(v)
+ s.s.Add(v.v)
+}
+
+// Remove deletes the given value from the receiving set, if indeed it was
+// there in the first place. If the value is not present, this is a no-op.
+func (s ValueSet) Remove(v Value) {
+ s.requireElementType(v)
+ s.s.Remove(v.v)
+}
+
+// Has returns true if the given value is in the receiving set, or false if
+// it is not.
+func (s ValueSet) Has(v Value) bool {
+ s.requireElementType(v)
+ return s.s.Has(v.v)
+}
+
+// Copy performs a shallow copy of the receiving set, returning a new set
+// with the same rules and elements.
+func (s ValueSet) Copy() ValueSet {
+ return newValueSet(s.s.Copy())
+}
+
+// Length returns the number of values in the set.
+func (s ValueSet) Length() int {
+ return s.s.Length()
+}
+
+// Values returns a slice of all of the values in the set in no particular
+// order.
+func (s ValueSet) Values() []Value {
+ l := s.s.Length()
+ if l == 0 {
+ return nil
+ }
+ ret := make([]Value, 0, l)
+ ety := s.ElementType()
+ for it := s.s.Iterator(); it.Next(); {
+ ret = append(ret, Value{
+ ty: ety,
+ v: it.Value(),
+ })
+ }
+ return ret
+}
+
+// Union returns a new set that contains all of the members of both the
+// receiving set and the given set. Both sets must have the same element type,
+// or else this function will panic.
+func (s ValueSet) Union(other ValueSet) ValueSet {
+ return newValueSet(s.s.Union(other.s))
+}
+
+// Intersection returns a new set that contains the values that both the
+// receiver and given sets have in common. Both sets must have the same element
+// type, or else this function will panic.
+func (s ValueSet) Intersection(other ValueSet) ValueSet {
+ return newValueSet(s.s.Intersection(other.s))
+}
+
+// Subtract returns a new set that contains all of the values from the receiver
+// that are not also in the given set. Both sets must have the same element
+// type, or else this function will panic.
+func (s ValueSet) Subtract(other ValueSet) ValueSet {
+ return newValueSet(s.s.Subtract(other.s))
+}
+
+// SymmetricDifference returns a new set that contains all of the values from
+// both the receiver and given sets, except those that both sets have in
+// common. Both sets must have the same element type, or else this function
+// will panic.
+func (s ValueSet) SymmetricDifference(other ValueSet) ValueSet {
+ return newValueSet(s.s.SymmetricDifference(other.s))
+}
+
+// requireElementType panics if the given value is not of the set's element type.
+//
+// It also panics if the given value is marked, because marked values cannot
+// be stored in sets.
+func (s ValueSet) requireElementType(v Value) {
+ if v.IsMarked() {
+ panic("cannot store marked value directly in a set (make the set itself unknown instead)")
+ }
+ if !v.Type().Equals(s.ElementType()) {
+ panic(fmt.Errorf("attempt to use %#v value with set of %#v", v.Type(), s.ElementType()))
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_internals.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_internals.go
new file mode 100644
index 00000000000..572fc863ffc
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_internals.go
@@ -0,0 +1,278 @@
+package cty
+
+import (
+ "bytes"
+ "fmt"
+ "hash/crc32"
+ "math/big"
+ "sort"
+
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// setRules provides a Rules implementation for the ./set package that
+// respects the equality rules for cty values of the given type.
+//
+// This implementation expects that values added to the set will be
+// valid internal values for the given Type, which is to say that wrapping
+// the given value in a Value struct along with the ruleset's type should
+// produce a valid, working Value.
+type setRules struct {
+ Type Type
+}
+
+var _ set.OrderedRules[any] = setRules{}
+
+func newSetRules(ety Type) set.Rules[any] {
+ return setRules{ety}
+}
+
+// Hash returns a hash value for the receiver that can be used for equality
+// checks where some inaccuracy is tolerable.
+//
+// The hash function is value-type-specific, so it is not meaningful to compare
+// hash results for values of different types.
+//
+// This function is not safe to use for security-related applications, since
+// the hash used is not strong enough.
+func (val Value) Hash() int {
+ hashBytes, marks := makeSetHashBytes(val)
+ if len(marks) > 0 {
+ panic("can't take hash of value that has marks or has embedded values that have marks")
+ }
+ return int(crc32.ChecksumIEEE(hashBytes))
+}
+
+func (r setRules) Hash(v any) int {
+ return Value{
+ ty: r.Type,
+ v: v,
+ }.Hash()
+}
+
+func (r setRules) Equivalent(v1 any, v2 any) bool {
+ v1v := Value{
+ ty: r.Type,
+ v: v1,
+ }
+ v2v := Value{
+ ty: r.Type,
+ v: v2,
+ }
+
+ eqv := v1v.Equals(v2v)
+
+ // By comparing the result to true we ensure that an Unknown result,
+ // which will result if either value is unknown, will be considered
+ // as non-equivalent. Two unknown values are not equivalent for the
+ // sake of set membership.
+ return eqv.v == true
+}
+
+// SameRules is only true if the other Rules instance is also a setRules struct,
+// and the types are considered equal.
+func (r setRules) SameRules(other set.Rules[any]) bool {
+ rules, ok := other.(setRules)
+ if !ok {
+ return false
+ }
+
+ return r.Type.Equals(rules.Type)
+}
+
+// Less is an implementation of set.OrderedRules so that we can iterate over
+// set elements in a consistent order, where such an order is possible.
+func (r setRules) Less(v1, v2 any) bool {
+ v1v := Value{
+ ty: r.Type,
+ v: v1,
+ }
+ v2v := Value{
+ ty: r.Type,
+ v: v2,
+ }
+
+ if v1v.RawEquals(v2v) { // Easy case: if they are equal then v1 can't be less
+ return false
+ }
+
+ // Null values always sort after non-null values
+ if v2v.IsNull() && !v1v.IsNull() {
+ return true
+ } else if v1v.IsNull() {
+ return false
+ }
+ // Unknown values always sort after known values
+ if v1v.IsKnown() && !v2v.IsKnown() {
+ return true
+ } else if !v1v.IsKnown() {
+ return false
+ }
+
+ switch r.Type {
+ case String:
+ // String values sort lexicographically
+ return v1v.AsString() < v2v.AsString()
+ case Bool:
+ // Weird to have a set of bools, but if we do then false sorts before true.
+ if v2v.True() || !v1v.True() {
+ return true
+ }
+ return false
+ case Number:
+ v1f := v1v.AsBigFloat()
+ v2f := v2v.AsBigFloat()
+ return v1f.Cmp(v2f) < 0
+ default:
+ // No other types have a well-defined ordering, so we just produce a
+ // default consistent-but-undefined ordering then. This situation is
+ // not considered a compatibility constraint; callers should rely only
+ // on the ordering rules for primitive values.
+ v1h, _ := makeSetHashBytes(v1v)
+ v2h, _ := makeSetHashBytes(v2v)
+ return bytes.Compare(v1h, v2h) < 0
+ }
+}
+
+func makeSetHashBytes(val Value) ([]byte, ValueMarks) {
+ var buf bytes.Buffer
+ marks := make(ValueMarks)
+ appendSetHashBytes(val, &buf, marks)
+ return buf.Bytes(), marks
+}
+
+func appendSetHashBytes(val Value, buf *bytes.Buffer, marks ValueMarks) {
+ // Exactly what bytes we generate here don't matter as long as the following
+ // constraints hold:
+ // - Unknown and null values all generate distinct strings from
+ // each other and from any normal value of the given type.
+ // - The delimiter used to separate items in a compound structure can
+ // never appear literally in any of its elements.
+ // Since we don't support hetrogenous lists we don't need to worry about
+ // collisions between values of different types, apart from
+ // PseudoTypeDynamic.
+ // If in practice we *do* get a collision then it's not a big deal because
+ // the Equivalent function will still distinguish values, but set
+ // performance will be best if we are able to produce a distinct string
+ // for each distinct value, unknown values notwithstanding.
+
+ // Marks aren't considered part of a value for equality-testing purposes,
+ // so we'll unmark our value before we work with it but we'll remember
+ // the marks in case the caller needs to re-apply them to a derived
+ // value.
+ if val.IsMarked() {
+ unmarkedVal, valMarks := val.Unmark()
+ for m := range valMarks {
+ marks[m] = struct{}{}
+ }
+ val = unmarkedVal
+ }
+
+ if !val.IsKnown() {
+ buf.WriteRune('?')
+ return
+ }
+ if val.IsNull() {
+ buf.WriteRune('~')
+ return
+ }
+
+ switch val.ty {
+ case Number:
+ // Due to an unfortunate quirk of gob encoding for big.Float, we end up
+ // with non-pointer values immediately after a gob round-trip, and
+ // we end up in here before we've had a chance to run
+ // gobDecodeFixNumberPtr on the inner values of a gob-encoded set,
+ // and so sadly we must make a special effort to handle that situation
+ // here just so that we can get far enough along to fix it up for
+ // everything else in this package.
+ if bf, ok := val.v.(big.Float); ok {
+ buf.WriteString(bf.String())
+ return
+ }
+ buf.WriteString(val.v.(*big.Float).String())
+ return
+ case Bool:
+ if val.v.(bool) {
+ buf.WriteRune('T')
+ } else {
+ buf.WriteRune('F')
+ }
+ return
+ case String:
+ buf.WriteString(fmt.Sprintf("%q", val.v.(string)))
+ return
+ }
+
+ if val.ty.IsMapType() {
+ buf.WriteRune('{')
+ val.ForEachElement(func(keyVal, elementVal Value) bool {
+ appendSetHashBytes(keyVal, buf, marks)
+ buf.WriteRune(':')
+ appendSetHashBytes(elementVal, buf, marks)
+ buf.WriteRune(';')
+ return false
+ })
+ buf.WriteRune('}')
+ return
+ }
+
+ if val.ty.IsListType() || val.ty.IsSetType() {
+ buf.WriteRune('[')
+ val.ForEachElement(func(keyVal, elementVal Value) bool {
+ appendSetHashBytes(elementVal, buf, marks)
+ buf.WriteRune(';')
+ return false
+ })
+ buf.WriteRune(']')
+ return
+ }
+
+ if val.ty.IsObjectType() {
+ buf.WriteRune('<')
+ attrNames := make([]string, 0, len(val.ty.AttributeTypes()))
+ for attrName := range val.ty.AttributeTypes() {
+ attrNames = append(attrNames, attrName)
+ }
+ sort.Strings(attrNames)
+ for _, attrName := range attrNames {
+ appendSetHashBytes(val.GetAttr(attrName), buf, marks)
+ buf.WriteRune(';')
+ }
+ buf.WriteRune('>')
+ return
+ }
+
+ if val.ty.IsTupleType() {
+ buf.WriteRune('<')
+ val.ForEachElement(func(keyVal, elementVal Value) bool {
+ appendSetHashBytes(elementVal, buf, marks)
+ buf.WriteRune(';')
+ return false
+ })
+ buf.WriteRune('>')
+ return
+ }
+
+ if val.ty.IsCapsuleType() {
+ buf.WriteRune('«')
+ ops := val.ty.CapsuleOps()
+ if ops != nil && ops.HashKey != nil {
+ key := ops.HashKey(val.EncapsulatedValue())
+ buf.WriteString(fmt.Sprintf("%q", key))
+ } else {
+ // If there isn't an explicit hash implementation then we'll
+ // just generate the same hash value for every value of this
+ // type, which is logically fine but less efficient for
+ // larger sets because we'll have to bucket all values
+ // together and scan over them with Equals to determine
+ // set membership.
+ buf.WriteRune('?')
+ }
+ buf.WriteRune('»')
+ return
+ }
+
+ // should never get down here
+ panic(fmt.Sprintf("unsupported type %#v in set hash", val.ty))
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_type.go
new file mode 100644
index 00000000000..cbc3706f2c4
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/set_type.go
@@ -0,0 +1,72 @@
+package cty
+
+import (
+ "fmt"
+)
+
+type typeSet struct {
+ typeImplSigil
+ ElementTypeT Type
+}
+
+// Set creates a set type with the given element Type.
+//
+// Set types are CollectionType implementations.
+func Set(elem Type) Type {
+ return Type{
+ typeSet{
+ ElementTypeT: elem,
+ },
+ }
+}
+
+// Equals returns true if the other Type is a set whose element type is
+// equal to that of the receiver.
+func (t typeSet) Equals(other Type) bool {
+ ot, isSet := other.typeImpl.(typeSet)
+ if !isSet {
+ return false
+ }
+
+ return t.ElementTypeT.Equals(ot.ElementTypeT)
+}
+
+func (t typeSet) FriendlyName(mode friendlyTypeNameMode) string {
+ elemName := t.ElementTypeT.friendlyNameMode(mode)
+ if mode == friendlyTypeConstraintName {
+ if t.ElementTypeT == DynamicPseudoType {
+ elemName = "any single type"
+ }
+ }
+ return "set of " + elemName
+}
+
+func (t typeSet) ElementType() Type {
+ return t.ElementTypeT
+}
+
+func (t typeSet) GoString() string {
+ return fmt.Sprintf("cty.Set(%#v)", t.ElementTypeT)
+}
+
+// IsSetType returns true if the given type is a list type, regardless of its
+// element type.
+func (t Type) IsSetType() bool {
+ _, ok := t.typeImpl.(typeSet)
+ return ok
+}
+
+// SetElementType is a convenience method that checks if the given type is
+// a set type, returning a pointer to its element type if so and nil
+// otherwise. This is intended to allow convenient conditional branches,
+// like so:
+//
+// if et := t.SetElementType(); et != nil {
+// // Do something with *et
+// }
+func (t Type) SetElementType() *Type {
+ if lt, ok := t.typeImpl.(typeSet); ok {
+ return <.ElementTypeT
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/tuple_type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
new file mode 100644
index 00000000000..05a8ebe6d10
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/tuple_type.go
@@ -0,0 +1,121 @@
+package cty
+
+import (
+ "fmt"
+)
+
+type typeTuple struct {
+ typeImplSigil
+ ElemTypes []Type
+}
+
+// Tuple creates a tuple type with the given element types.
+//
+// After a slice is passed to this function the caller must no longer access
+// the underlying array, since ownership is transferred to this library.
+func Tuple(elemTypes []Type) Type {
+ return Type{
+ typeTuple{
+ ElemTypes: elemTypes,
+ },
+ }
+}
+
+func (t typeTuple) Equals(other Type) bool {
+ if ot, ok := other.typeImpl.(typeTuple); ok {
+ if len(t.ElemTypes) != len(ot.ElemTypes) {
+ // Fast path: if we don't have the same number of elements
+ // then we can't possibly be equal.
+ return false
+ }
+
+ for i, ty := range t.ElemTypes {
+ oty := ot.ElemTypes[i]
+ if !ok {
+ return false
+ }
+ if !oty.Equals(ty) {
+ return false
+ }
+ }
+
+ return true
+ }
+ return false
+}
+
+func (t typeTuple) FriendlyName(mode friendlyTypeNameMode) string {
+ // There isn't really a friendly way to write a tuple type due to its
+ // complexity, so we'll just do something English-ish. Callers will
+ // probably want to make some extra effort to avoid ever printing out
+ // a tuple type FriendlyName in its entirety. For example, could
+ // produce an error message by diffing two object types and saying
+ // something like "Expected attribute foo to be string, but got number".
+ // TODO: Finish this
+ return "tuple"
+}
+
+func (t typeTuple) GoString() string {
+ if len(t.ElemTypes) == 0 {
+ return "cty.EmptyTuple"
+ }
+ return fmt.Sprintf("cty.Tuple(%#v)", t.ElemTypes)
+}
+
+// EmptyTuple is a shorthand for Tuple([]Type{}), to more easily talk about
+// the empty tuple type.
+var EmptyTuple Type
+
+// EmptyTupleVal is the only possible non-null, non-unknown value of type
+// EmptyTuple.
+var EmptyTupleVal Value
+
+func init() {
+ EmptyTuple = Tuple([]Type{})
+ EmptyTupleVal = Value{
+ ty: EmptyTuple,
+ v: []any{},
+ }
+}
+
+// IsTupleType returns true if the given type is an object type, regardless
+// of its element type.
+func (t Type) IsTupleType() bool {
+ _, ok := t.typeImpl.(typeTuple)
+ return ok
+}
+
+// Length returns the number of elements of the receiving tuple type.
+// Will panic if the reciever isn't a tuple type; use IsTupleType to determine
+// whether this operation will succeed.
+func (t Type) Length() int {
+ if ot, ok := t.typeImpl.(typeTuple); ok {
+ return len(ot.ElemTypes)
+ }
+ panic("Length on non-tuple Type")
+}
+
+// TupleElementType returns the type of the element with the given index. Will
+// panic if the receiver is not a tuple type (use IsTupleType to confirm)
+// or if the index is out of range (use Length to confirm).
+func (t Type) TupleElementType(idx int) Type {
+ if ot, ok := t.typeImpl.(typeTuple); ok {
+ return ot.ElemTypes[idx]
+ }
+ panic("TupleElementType on non-tuple Type")
+}
+
+// TupleElementTypes returns a slice of the recieving tuple type's element
+// types. Will panic if the receiver is not a tuple type (use IsTupleType
+// to confirm).
+//
+// The returned slice is part of the internal state of the type, and is provided
+// for read access only. It is forbidden for any caller to modify the
+// underlying array. For many purposes the element-related methods of Value
+// are more appropriate and more convenient to use.
+func (t Type) TupleElementTypes() []Type {
+ if ot, ok := t.typeImpl.(typeTuple); ok {
+ return ot.ElemTypes
+ }
+ panic("TupleElementTypes on non-tuple Type")
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/type.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/type.go
new file mode 100644
index 00000000000..440690853fa
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/type.go
@@ -0,0 +1,161 @@
+package cty
+
+// Type represents value types within the type system.
+//
+// This is a closed interface type, meaning that only the concrete
+// implementations provided within this package are considered valid.
+type Type struct {
+ typeImpl
+}
+
+type typeImpl interface {
+ // isTypeImpl is a do-nothing method that exists only to express
+ // that a type is an implementation of typeImpl.
+ isTypeImpl() typeImplSigil
+
+ // Equals returns true if the other given Type exactly equals the
+ // receiver Type.
+ Equals(other Type) bool
+
+ // FriendlyName returns a human-friendly *English* name for the given
+ // type.
+ FriendlyName(mode friendlyTypeNameMode) string
+
+ // GoString implements the GoStringer interface from package fmt.
+ GoString() string
+}
+
+// Base implementation of Type to embed into concrete implementations
+// to signal that they are implementations of Type.
+type typeImplSigil struct{}
+
+func (t typeImplSigil) isTypeImpl() typeImplSigil {
+ return typeImplSigil{}
+}
+
+// Equals returns true if the other given Type exactly equals the receiver
+// type.
+func (t Type) Equals(other Type) bool {
+ if t == NilType || other == NilType {
+ return t == other
+ }
+ return t.typeImpl.Equals(other)
+}
+
+// FriendlyName returns a human-friendly *English* name for the given type.
+func (t Type) FriendlyName() string {
+ return t.typeImpl.FriendlyName(friendlyTypeName)
+}
+
+// FriendlyNameForConstraint is similar to FriendlyName except that the
+// result is specialized for describing type _constraints_ rather than types
+// themselves. This is more appropriate when reporting that a particular value
+// does not conform to an expected type constraint.
+//
+// In particular, this function uses the term "any type" to refer to
+// cty.DynamicPseudoType, rather than "dynamic" as returned by FriendlyName.
+func (t Type) FriendlyNameForConstraint() string {
+ return t.typeImpl.FriendlyName(friendlyTypeConstraintName)
+}
+
+// friendlyNameMode is an internal combination of the various FriendlyName*
+// variants that just directly takes a mode, for easy passthrough for
+// recursive name construction.
+func (t Type) friendlyNameMode(mode friendlyTypeNameMode) string {
+ return t.typeImpl.FriendlyName(mode)
+}
+
+// GoString returns a string approximating how the receiver type would be
+// expressed in Go source code.
+func (t Type) GoString() string {
+ if t.typeImpl == nil {
+ return "cty.NilType"
+ }
+
+ return t.typeImpl.GoString()
+}
+
+// NilType is an invalid type used when a function is returning an error
+// and has no useful type to return. It should not be used and any methods
+// called on it will panic.
+var NilType = Type{}
+
+// HasDynamicTypes returns true either if the receiver is itself
+// DynamicPseudoType or if it is a compound type whose descendent elements
+// are DynamicPseudoType.
+func (t Type) HasDynamicTypes() bool {
+ switch {
+ case t == DynamicPseudoType:
+ return true
+ case t.IsPrimitiveType():
+ return false
+ case t.IsCollectionType():
+ return t.ElementType().HasDynamicTypes()
+ case t.IsObjectType():
+ attrTypes := t.AttributeTypes()
+ for _, at := range attrTypes {
+ if at.HasDynamicTypes() {
+ return true
+ }
+ }
+ return false
+ case t.IsTupleType():
+ elemTypes := t.TupleElementTypes()
+ for _, et := range elemTypes {
+ if et.HasDynamicTypes() {
+ return true
+ }
+ }
+ return false
+ case t.IsCapsuleType():
+ return false
+ default:
+ // Should never happen, since above should be exhaustive
+ panic("HasDynamicTypes does not support the given type")
+ }
+}
+
+// WithoutOptionalAttributesDeep returns a type equivalent to the receiver but
+// with any objects with optional attributes converted into fully concrete
+// object types. This operation is applied recursively.
+func (t Type) WithoutOptionalAttributesDeep() Type {
+ switch {
+ case t == DynamicPseudoType, t.IsPrimitiveType(), t.IsCapsuleType():
+ return t
+ case t.IsMapType():
+ return Map(t.ElementType().WithoutOptionalAttributesDeep())
+ case t.IsListType():
+ return List(t.ElementType().WithoutOptionalAttributesDeep())
+ case t.IsSetType():
+ return Set(t.ElementType().WithoutOptionalAttributesDeep())
+ case t.IsTupleType():
+ originalElemTypes := t.TupleElementTypes()
+ elemTypes := make([]Type, len(originalElemTypes))
+ for i, et := range originalElemTypes {
+ elemTypes[i] = et.WithoutOptionalAttributesDeep()
+ }
+ return Tuple(elemTypes)
+ case t.IsObjectType():
+ originalAttrTypes := t.AttributeTypes()
+ attrTypes := make(map[string]Type, len(originalAttrTypes))
+ for k, t := range originalAttrTypes {
+ attrTypes[k] = t.WithoutOptionalAttributesDeep()
+ }
+
+ // This is the subtle line which does all the work of this function: by
+ // constructing a new Object type with these attribute types, we drop
+ // the list of optional attributes (if present). This results in a
+ // concrete Object type which requires all of the original attributes.
+ return Object(attrTypes)
+ default:
+ // Should never happen, since above should be exhaustive
+ panic("WithoutOptionalAttributesDeep does not support the given type")
+ }
+}
+
+type friendlyTypeNameMode rune
+
+const (
+ friendlyTypeName friendlyTypeNameMode = 'N'
+ friendlyTypeConstraintName friendlyTypeNameMode = 'C'
+)
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/type_conform.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/type_conform.go
new file mode 100644
index 00000000000..476eeea87fc
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/type_conform.go
@@ -0,0 +1,139 @@
+package cty
+
+// TestConformance recursively walks the receiver and the given other type and
+// returns nil if the receiver *conforms* to the given type.
+//
+// Type conformance is similar to type equality but has one crucial difference:
+// PseudoTypeDynamic can be used within the given type to represent that
+// *any* type is allowed.
+//
+// If any non-conformities are found, the returned slice will be non-nil and
+// contain at least one error value. It will be nil if the type is entirely
+// conformant.
+//
+// Note that the special behavior of PseudoTypeDynamic is the *only* exception
+// to normal type equality. Calling applications may wish to apply their own
+// automatic conversion logic to the given data structure to create a more
+// liberal notion of conformance to a type.
+//
+// Returned errors are usually (but not always) PathError instances that
+// indicate where in the structure the error was found. If a returned error
+// is of that type then the error message is written for (English-speaking)
+// end-users working within the cty type system, not mentioning any Go-oriented
+// implementation details.
+func (t Type) TestConformance(other Type) []error {
+ path := make(Path, 0)
+ var errs []error
+ testConformance(t, other, path, &errs)
+ return errs
+}
+
+func testConformance(given Type, want Type, path Path, errs *[]error) {
+ if want.Equals(DynamicPseudoType) {
+ // anything goes!
+ return
+ }
+
+ if given.Equals(want) {
+ // Any equal types are always conformant
+ return
+ }
+
+ // The remainder of this function is concerned with detecting
+ // and reporting the specific non-conformance, since we wouldn't
+ // have got here if the types were not divergent.
+ // We treat compound structures as special so that we can report
+ // specifically what is non-conforming, rather than simply returning
+ // the entire type names and letting the user puzzle it out.
+
+ if given.IsObjectType() && want.IsObjectType() {
+ givenAttrs := given.AttributeTypes()
+ wantAttrs := want.AttributeTypes()
+
+ for k := range givenAttrs {
+ if _, exists := wantAttrs[k]; !exists {
+ *errs = append(
+ *errs,
+ errorf(path, "unsupported attribute %q", k),
+ )
+ }
+ }
+ for k := range wantAttrs {
+ if _, exists := givenAttrs[k]; !exists {
+ *errs = append(
+ *errs,
+ errorf(path, "missing required attribute %q", k),
+ )
+ }
+ }
+
+ path = append(path, nil)
+ pathIdx := len(path) - 1
+
+ for k, wantAttrType := range wantAttrs {
+ if givenAttrType, exists := givenAttrs[k]; exists {
+ path[pathIdx] = GetAttrStep{Name: k}
+ testConformance(givenAttrType, wantAttrType, path, errs)
+ }
+ }
+
+ path = path[0:pathIdx]
+
+ return
+ }
+
+ if given.IsTupleType() && want.IsTupleType() {
+ givenElems := given.TupleElementTypes()
+ wantElems := want.TupleElementTypes()
+
+ if len(givenElems) != len(wantElems) {
+ *errs = append(
+ *errs,
+ errorf(path, "%d elements are required, but got %d", len(wantElems), len(givenElems)),
+ )
+ return
+ }
+
+ path = append(path, nil)
+ pathIdx := len(path) - 1
+
+ for i, wantElemType := range wantElems {
+ givenElemType := givenElems[i]
+ path[pathIdx] = IndexStep{Key: NumberIntVal(int64(i))}
+ testConformance(givenElemType, wantElemType, path, errs)
+ }
+
+ path = path[0:pathIdx]
+
+ return
+ }
+
+ if given.IsListType() && want.IsListType() {
+ path = append(path, IndexStep{Key: UnknownVal(Number)})
+ pathIdx := len(path) - 1
+ testConformance(given.ElementType(), want.ElementType(), path, errs)
+ path = path[0:pathIdx]
+ return
+ }
+
+ if given.IsMapType() && want.IsMapType() {
+ path = append(path, IndexStep{Key: UnknownVal(String)})
+ pathIdx := len(path) - 1
+ testConformance(given.ElementType(), want.ElementType(), path, errs)
+ path = path[0:pathIdx]
+ return
+ }
+
+ if given.IsSetType() && want.IsSetType() {
+ path = append(path, IndexStep{Key: UnknownVal(given.ElementType())})
+ pathIdx := len(path) - 1
+ testConformance(given.ElementType(), want.ElementType(), path, errs)
+ path = path[0:pathIdx]
+ return
+ }
+
+ *errs = append(
+ *errs,
+ errorf(path, "%s required, but received %s", want.FriendlyName(), given.FriendlyName()),
+ )
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown.go
new file mode 100644
index 00000000000..626772faa05
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown.go
@@ -0,0 +1,93 @@
+package cty
+
+// unknownType is the placeholder type used for the sigil value representing
+// "Unknown", to make it unambigiously distinct from any other possible value.
+type unknownType struct {
+ // refinement is an optional object which, if present, describes some
+ // additional constraints we know about the range of real values this
+ // unknown value could be a placeholder for.
+ refinement unknownValRefinement
+}
+
+// totallyUnknown is the representation a a value we know nothing about at
+// all. Subsequent refinements of an unknown value will cause creation of
+// other values of unknownType that can represent additional constraints
+// on the unknown value, but all unknown values start as totally unknown
+// and we will also typically lose all unknown value refinements when
+// round-tripping through serialization formats.
+var totallyUnknown any = &unknownType{}
+
+// UnknownVal returns an Value that represents an unknown value of the given
+// type. Unknown values can be used to represent a value that is
+// not yet known. Its meaning is undefined in cty, but it could be used by
+// an calling application to allow partial evaluation.
+//
+// Unknown values of any type can be created of any type. All operations on
+// Unknown values themselves return Unknown.
+func UnknownVal(t Type) Value {
+ return Value{
+ ty: t,
+ v: totallyUnknown,
+ }
+}
+
+func (t unknownType) GoString() string {
+ // This is the stringification of our internal unknown marker. The
+ // stringification of the public representation of unknowns is in
+ // Value.GoString.
+ return "cty.unknown"
+}
+
+type pseudoTypeDynamic struct {
+ typeImplSigil
+}
+
+// DynamicPseudoType represents the dynamic pseudo-type.
+//
+// This type can represent situations where a type is not yet known. Its
+// meaning is undefined in cty, but it could be used by a calling
+// application to allow expression type checking with some types not yet known.
+// For example, the application might optimistically permit any operation on
+// values of this type in type checking, allowing a partial type-check result,
+// and then repeat the check when more information is known to get the
+// final, concrete type.
+//
+// It is a pseudo-type because it is used only as a sigil to the calling
+// application. "Unknown" is the only valid value of this pseudo-type, so
+// operations on values of this type will always short-circuit as per
+// the rules for that special value.
+var DynamicPseudoType Type
+
+func (t pseudoTypeDynamic) Equals(other Type) bool {
+ _, ok := other.typeImpl.(pseudoTypeDynamic)
+ return ok
+}
+
+func (t pseudoTypeDynamic) FriendlyName(mode friendlyTypeNameMode) string {
+ switch mode {
+ case friendlyTypeConstraintName:
+ return "any type"
+ default:
+ return "dynamic"
+ }
+}
+
+func (t pseudoTypeDynamic) GoString() string {
+ return "cty.DynamicPseudoType"
+}
+
+// DynamicVal is the only valid value of the pseudo-type dynamic.
+// This value can be used as a placeholder where a value or expression's
+// type and value are both unknown, thus allowing partial evaluation. See
+// the docs for DynamicPseudoType for more information.
+var DynamicVal Value
+
+func init() {
+ DynamicPseudoType = Type{
+ pseudoTypeDynamic{},
+ }
+ DynamicVal = Value{
+ ty: DynamicPseudoType,
+ v: totallyUnknown,
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go
new file mode 100644
index 00000000000..73d592d0903
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown_as_null.go
@@ -0,0 +1,69 @@
+package cty
+
+// UnknownAsNull returns a value of the same type as the given value but
+// with any unknown values (including nested values) replaced with null
+// values of the same type.
+//
+// This can be useful if a result is to be serialized in a format that can't
+// represent unknowns, such as JSON, as long as the caller does not need to
+// retain the unknown value information.
+func UnknownAsNull(val Value) Value {
+ if val.IsMarked() {
+ val, valMarks := val.Unmark()
+ return UnknownAsNull(val).WithMarks(valMarks)
+ }
+
+ ty := val.Type()
+ switch {
+ case val.IsNull():
+ return val
+ case !val.IsKnown():
+ return NullVal(ty)
+ case ty.IsListType() || ty.IsTupleType() || ty.IsSetType():
+ length := val.LengthInt()
+ if length == 0 {
+ // If there are no elements then we can't have unknowns
+ return val
+ }
+ vals := make([]Value, 0, length)
+ it := val.ElementIterator()
+ for it.Next() {
+ _, v := it.Element()
+ vals = append(vals, UnknownAsNull(v))
+ }
+ switch {
+ case ty.IsListType():
+ return ListVal(vals)
+ case ty.IsTupleType():
+ return TupleVal(vals)
+ default:
+ return SetVal(vals)
+ }
+ case ty.IsMapType() || ty.IsObjectType():
+ var length int
+ switch {
+ case ty.IsMapType():
+ length = val.LengthInt()
+ default:
+ length = len(val.Type().AttributeTypes())
+ }
+ if length == 0 {
+ // If there are no elements then we can't have unknowns
+ return val
+ }
+ vals := make(map[string]Value, length)
+ it := val.ElementIterator()
+ for it.Next() {
+ k, v := it.Element()
+ vals[k.AsString()] = UnknownAsNull(v)
+ }
+ switch {
+ case ty.IsMapType():
+ return MapVal(vals)
+ default:
+ return ObjectVal(vals)
+ }
+ }
+
+ return val
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown_refinement.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown_refinement.go
new file mode 100644
index 00000000000..85fb28d632c
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/unknown_refinement.go
@@ -0,0 +1,788 @@
+package cty
+
+import (
+ "fmt"
+ "math"
+ "strings"
+
+ "github.com/zclconf/go-cty/cty/ctystrings"
+)
+
+// Refine creates a [RefinementBuilder] with which to annotate the reciever
+// with zero or more additional refinements that constrain the range of
+// the value.
+//
+// Calling methods on a RefinementBuilder for a known value essentially just
+// serves as assertions about the range of that value, leading to panics if
+// those assertions don't hold in practice. This is mainly supported just to
+// make programs that rely on refinements automatically self-check by using
+// the refinement codepath unconditionally on both placeholders and final
+// values for those placeholders. It's always a bug to refine the range of
+// an unknown value and then later substitute an exact value outside of the
+// refined range.
+//
+// Calling methods on a RefinementBuilder for an unknown value is perhaps
+// more useful because the newly-refined value will then be a placeholder for
+// a smaller range of values and so it may be possible for other operations
+// on the unknown value to return a known result despite the exact value not
+// yet being known.
+//
+// It is never valid to refine [DynamicVal], because that value is a
+// placeholder for a value about which we knkow absolutely nothing. A value
+// must at least have a known root type before it can support further
+// refinement.
+func (v Value) Refine() *RefinementBuilder {
+ v, marks := v.Unmark()
+ if unk, isUnk := v.v.(*unknownType); isUnk && unk.refinement != nil {
+ // We're refining a value that's already been refined before, so
+ // we'll start from a copy of its existing refinements.
+ wip := unk.refinement.copy()
+ return &RefinementBuilder{v, marks, wip}
+ }
+
+ ty := v.Type()
+ var wip unknownValRefinement
+ switch {
+ case ty == DynamicPseudoType && !v.IsKnown():
+ // This case specifically matches DynamicVal, which is constrained
+ // by backward compatibility to be a singleton and so we cannot allow
+ // any refinements to it.
+ // To preserve the typical assumption that DynamicVal is a safe
+ // placeholder to use when no value is known at all, we silently
+ // ignore all attempts to refine this particular value and just
+ // always echo back a totally-unrefined DynamicVal.
+ return &RefinementBuilder{
+ orig: DynamicVal,
+ marks: marks,
+ }
+ case ty == String:
+ wip = &refinementString{}
+ case ty == Number:
+ wip = &refinementNumber{}
+ case ty.IsCollectionType():
+ wip = &refinementCollection{
+ // A collection can never have a negative length, so we'll
+ // start with that already constrained.
+ minLen: 0,
+ maxLen: math.MaxInt,
+ }
+ case ty == Bool || ty.IsObjectType() || ty.IsTupleType() || ty.IsCapsuleType():
+ // For other known types we'll just track nullability
+ wip = &refinementNullable{}
+ case ty == DynamicPseudoType && v.IsNull():
+ // It's okay in principle to refine a null value of unknown type,
+ // although all we can refine about it is that it's definitely null and
+ // so this is pretty pointless and only supported to avoid callers
+ // always needing to treat this situation as a special case to avoid
+ // panic.
+ wip = &refinementNullable{
+ isNull: tristateTrue,
+ }
+ default:
+ // we leave "wip" as nil for all other types, representing that
+ // they don't support refinements at all and so any call on the
+ // RefinementBuilder should fail.
+
+ // NOTE: We intentionally don't allow any refinements for
+ // cty.DynamicVal here, even though it could be nice in principle
+ // to at least track non-nullness for those, because it's historically
+ // been valid to directly compare values with cty.DynamicVal using
+ // the Go "==" operator and recording a refinement for an untyped
+ // unknown value would break existing code relying on that.
+ }
+
+ return &RefinementBuilder{v, marks, wip}
+}
+
+// RefineWith is a variant of Refine which uses callback functions instead of
+// the builder pattern.
+//
+// The result is equivalent to passing the return value of [Value.Refine] to the
+// first callback, and then continue passing the builder through any other
+// callbacks in turn, and then calling [RefinementBuilder.NewValue] on the
+// final result.
+//
+// The builder pattern approach of [Value.Refine] is more convenient for inline
+// annotation of refinements when constructing a value, but this alternative
+// approach may be more convenient when applying pre-defined collections of
+// refinements, or when refinements are defined separately from the values
+// they will apply to.
+//
+// Each refiner callback should return the same pointer that it was given,
+// typically after having mutated it using the [RefinementBuilder] methods.
+// It's invalid to return a different builder.
+func (v Value) RefineWith(refiners ...func(*RefinementBuilder) *RefinementBuilder) Value {
+ if len(refiners) == 0 {
+ return v
+ }
+ origBuilder := v.Refine()
+ builder := origBuilder
+ for _, refiner := range refiners {
+ builder = refiner(builder)
+ if builder != origBuilder {
+ panic("refiner callback returned a different builder")
+ }
+ }
+ return builder.NewValue()
+}
+
+// RefineNotNull is a shorthand for Value.Refine().NotNull().NewValue(), because
+// declaring that a unknown value isn't null is by far the most common use of
+// refinements.
+func (v Value) RefineNotNull() Value {
+ return v.Refine().NotNull().NewValue()
+}
+
+// RefinementBuilder is a supporting type for the [Value.Refine] method,
+// using the builder pattern to apply zero or more constraints before
+// constructing a new value with all of those constraints applied.
+//
+// Most of the methods of this type return the same reciever to allow
+// for method call chaining. End call chains with a call to
+// [RefinementBuilder.NewValue] to obtain the newly-refined value.
+type RefinementBuilder struct {
+ orig Value
+ marks ValueMarks
+ wip unknownValRefinement
+}
+
+// refineable is an internal detail to help with two special situations
+// related to refinements:
+// - If the refinement is to a value of a type that doesn't support any
+// refinements at all, this function will immediately panic with a
+// message reporting that, because it's a caller bug to try to refine
+// a value in a way that's inappropriate for its known type.
+// - If the refinement is to an unknown value of an unknown type
+// (i.e. cty.DynamicVal) then it returns false, indicating that the
+// caller should just silently ignore whatever refinement was requested.
+// - In all other cases this function returns true, which means the direct
+// caller should attempt to apply the requested refinement, and then
+// panic itself if the requested refinement doesn't make sense for the
+// specific value being refined.
+func (b *RefinementBuilder) refineable() bool {
+ if b.orig == DynamicVal {
+ return false
+ }
+ if b.wip == nil {
+ panic(fmt.Sprintf("cannot refine a %#v value", b.orig.Type()))
+ }
+ return true
+}
+
+// NotNull constrains the value as definitely not being null.
+//
+// NotNull is valid when refining values of the following types:
+// - number, boolean, and string values
+// - list, set, or map types of any element type
+// - values of object types
+// - values of collection types
+// - values of capsule types
+//
+// When refining any other type this function will panic.
+//
+// In particular note that it is not valid to constrain an untyped value
+// -- a value whose type is `cty.DynamicPseudoType` -- as being non-null.
+// An unknown value of an unknown type is always completely unconstrained.
+func (b *RefinementBuilder) NotNull() *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ if b.orig.IsKnown() && b.orig.IsNull() {
+ panic("refining null value as non-null")
+ }
+ if b.wip.null() == tristateTrue {
+ panic("refining null value as non-null")
+ }
+
+ b.wip.setNull(tristateFalse)
+
+ return b
+}
+
+// Null constrains the value as definitely null.
+//
+// Null is valid for the same types as [RefinementBuilder.NotNull].
+// When refining any other type this function will panic.
+//
+// Explicitly cnstraining a value to be null is strange because that suggests
+// that the caller does actually know the value -- there is only one null
+// value for each type constraint -- but this is here for symmetry with the
+// fact that a [ValueRange] can also represent that a value is definitely null.
+func (b *RefinementBuilder) Null() *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ if b.orig.IsKnown() && !b.orig.IsNull() {
+ panic("refining non-null value as null")
+ }
+ if b.wip.null() == tristateFalse {
+ panic("refining non-null value as null")
+ }
+
+ b.wip.setNull(tristateTrue)
+
+ return b
+}
+
+// NumericRange constrains the upper and/or lower bounds of a number value,
+// or panics if this builder is not refining a number value.
+//
+// The two given values are interpreted as inclusive bounds and either one
+// may be an unknown number if only one of the two bounds is currently known.
+// If either of the given values is not a non-null number value then this
+// function will panic.
+func (b *RefinementBuilder) NumberRangeInclusive(min, max Value) *RefinementBuilder {
+ return b.NumberRangeLowerBound(min, true).NumberRangeUpperBound(max, true)
+}
+
+// NumberRangeLowerBound constraints the lower bound of a number value, or
+// panics if this builder is not refining a number value.
+func (b *RefinementBuilder) NumberRangeLowerBound(min Value, inclusive bool) *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ wip, ok := b.wip.(*refinementNumber)
+ if !ok {
+ panic(fmt.Sprintf("cannot refine numeric bounds for a %#v value", b.orig.Type()))
+ }
+
+ if !min.IsKnown() {
+ // Nothing to do if the lower bound is unknown.
+ return b
+ }
+ if min.IsNull() {
+ panic("number range lower bound must not be null")
+ }
+
+ if inclusive {
+ if gt := min.GreaterThan(b.orig); gt.IsKnown() && gt.True() {
+ panic(fmt.Sprintf("refining %#v to be >= %#v", b.orig, min))
+ }
+ } else {
+ if gt := min.GreaterThanOrEqualTo(b.orig); gt.IsKnown() && gt.True() {
+ panic(fmt.Sprintf("refining %#v to be > %#v", b.orig, min))
+ }
+ }
+
+ if wip.min != NilVal {
+ var ok Value
+ if inclusive && !wip.minInc {
+ ok = min.GreaterThan(wip.min)
+ } else {
+ ok = min.GreaterThanOrEqualTo(wip.min)
+ }
+ if ok.IsKnown() && ok.False() {
+ return b // Our existing refinement is more constrained
+ }
+ }
+
+ if min != NegativeInfinity {
+ wip.min = min
+ wip.minInc = inclusive
+ }
+
+ wip.assertConsistentBounds()
+ return b
+}
+
+// NumberRangeUpperBound constraints the upper bound of a number value, or
+// panics if this builder is not refining a number value.
+func (b *RefinementBuilder) NumberRangeUpperBound(max Value, inclusive bool) *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ wip, ok := b.wip.(*refinementNumber)
+ if !ok {
+ panic(fmt.Sprintf("cannot refine numeric bounds for a %#v value", b.orig.Type()))
+ }
+
+ if !max.IsKnown() {
+ // Nothing to do if the upper bound is unknown.
+ return b
+ }
+ if max.IsNull() {
+ panic("number range upper bound must not be null")
+ }
+
+ if inclusive {
+ if lt := max.LessThan(b.orig); lt.IsKnown() && lt.True() {
+ panic(fmt.Sprintf("refining %#v to be <= %#v", b.orig, max))
+ }
+ } else {
+ if lt := max.LessThanOrEqualTo(b.orig); lt.IsKnown() && lt.True() {
+ panic(fmt.Sprintf("refining %#v to be < %#v", b.orig, max))
+ }
+ }
+
+ if wip.max != NilVal {
+ var ok Value
+ if inclusive && !wip.maxInc {
+ ok = max.LessThan(wip.max)
+ } else {
+ ok = max.LessThanOrEqualTo(wip.max)
+ }
+ if ok.IsKnown() && ok.False() {
+ return b // Our existing refinement is more constrained
+ }
+ }
+
+ if max != PositiveInfinity {
+ wip.max = max
+ wip.maxInc = inclusive
+ }
+
+ wip.assertConsistentBounds()
+ return b
+}
+
+// CollectionLengthLowerBound constrains the lower bound of the length of a
+// collection value, or panics if this builder is not refining a collection
+// value.
+func (b *RefinementBuilder) CollectionLengthLowerBound(min int) *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ wip, ok := b.wip.(*refinementCollection)
+ if !ok {
+ panic(fmt.Sprintf("cannot refine collection length bounds for a %#v value", b.orig.Type()))
+ }
+
+ minVal := NumberIntVal(int64(min))
+ if b.orig.IsKnown() {
+ realLen := b.orig.Length()
+ if gt := minVal.GreaterThan(realLen); gt.IsKnown() && gt.True() {
+ panic(fmt.Sprintf("refining collection of length %#v with lower bound %#v", realLen, min))
+ }
+ }
+
+ if wip.minLen > min {
+ return b // Our existing refinement is more constrained
+ }
+
+ wip.minLen = min
+ wip.assertConsistentLengthBounds()
+
+ return b
+}
+
+// CollectionLengthUpperBound constrains the upper bound of the length of a
+// collection value, or panics if this builder is not refining a collection
+// value.
+//
+// The upper bound must be a known, non-null number or this function will
+// panic.
+func (b *RefinementBuilder) CollectionLengthUpperBound(max int) *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ wip, ok := b.wip.(*refinementCollection)
+ if !ok {
+ panic(fmt.Sprintf("cannot refine collection length bounds for a %#v value", b.orig.Type()))
+ }
+
+ if b.orig.IsKnown() {
+ maxVal := NumberIntVal(int64(max))
+ realLen := b.orig.Length()
+ if lt := maxVal.LessThan(realLen); lt.IsKnown() && lt.True() {
+ panic(fmt.Sprintf("refining collection of length %#v with upper bound %#v", realLen, max))
+ }
+ }
+
+ if wip.maxLen < max {
+ return b // Our existing refinement is more constrained
+ }
+
+ wip.maxLen = max
+ wip.assertConsistentLengthBounds()
+
+ return b
+}
+
+// CollectionLength is a shorthand for passing the same length to both
+// [CollectionLengthLowerBound] and [CollectionLengthUpperBound].
+//
+// A collection with a refined length with equal bounds can sometimes collapse
+// to a known value. Refining to length zero always produces a known value.
+// The behavior for other lengths varies by collection type kind.
+//
+// If the unknown value is of a set type, it's only valid to use this method
+// if the caller knows that there will be the given number of _unique_ values
+// in the set. If any values might potentially coalesce together once known,
+// use [CollectionLengthUpperBound] instead.
+func (b *RefinementBuilder) CollectionLength(length int) *RefinementBuilder {
+ return b.CollectionLengthLowerBound(length).CollectionLengthUpperBound(length)
+}
+
+// StringPrefix constrains the prefix of a string value, or panics if this
+// builder is not refining a string value.
+//
+// The given prefix will be Unicode normalized in the same way that a
+// cty.StringVal would be.
+//
+// Due to Unicode normalization and grapheme cluster rules, appending new
+// characters to a string can change the meaning of earlier characters.
+// StringPrefix may discard one or more characters from the end of the given
+// prefix to avoid that problem.
+//
+// Although cty cannot check this automatically, applications should avoid
+// relying on the discarding of the suffix for correctness. For example, if the
+// prefix ends with an emoji base character then StringPrefix will discard it
+// in case subsequent characters include emoji modifiers, but it's still
+// incorrect for the final string to use an entirely different base character.
+//
+// Applications which fully control the final result and can guarantee the
+// subsequent characters will not combine with the prefix may be able to use
+// [RefinementBuilder.StringPrefixFull] instead, after carefully reviewing
+// the constraints described in its documentation.
+func (b *RefinementBuilder) StringPrefix(prefix string) *RefinementBuilder {
+ return b.StringPrefixFull(ctystrings.SafeKnownPrefix(prefix))
+}
+
+// StringPrefixFull is a variant of StringPrefix that will never shorten the
+// given prefix to take into account the possibility of the next character
+// combining with the end of the prefix.
+//
+// Applications which fully control the subsequent characters can use this
+// as long as they guarantee that the characters added later cannot possibly
+// combine with characters at the end of the prefix to form a single grapheme
+// cluster. For example, it would be unsafe to use the full prefix "hello" if
+// there is any chance that the final string will add a combining diacritic
+// character after the "o", because that would then change the final character.
+//
+// Use [RefinementBuilder.StringPrefix] instead if an application cannot fully
+// control the final result to avoid violating this rule.
+func (b *RefinementBuilder) StringPrefixFull(prefix string) *RefinementBuilder {
+ if !b.refineable() {
+ return b
+ }
+
+ wip, ok := b.wip.(*refinementString)
+ if !ok {
+ panic(fmt.Sprintf("cannot refine string prefix for a %#v value", b.orig.Type()))
+ }
+
+ // We must apply the same Unicode processing we'd normally use for a
+ // cty string so that the prefix will be comparable.
+ prefix = NormalizeString(prefix)
+
+ // If we have a known string value then the given prefix must actually
+ // match it.
+ if b.orig.IsKnown() && !b.orig.IsNull() {
+ have := b.orig.AsString()
+ matchLen := len(have)
+ if l := len(prefix); l < matchLen {
+ matchLen = l
+ }
+ have = have[:matchLen]
+ new := prefix[:matchLen]
+ if have != new {
+ panic("refined prefix is inconsistent with known value")
+ }
+ }
+
+ // If we already have a refined prefix then the overlapping parts of that
+ // and the new prefix must match.
+ {
+ matchLen := len(wip.prefix)
+ if l := len(prefix); l < matchLen {
+ matchLen = l
+ }
+
+ have := wip.prefix[:matchLen]
+ new := prefix[:matchLen]
+ if have != new {
+ panic("refined prefix is inconsistent with previous refined prefix")
+ }
+ }
+
+ // We'll only save the new prefix if it's longer than the one we already
+ // had.
+ if len(prefix) > len(wip.prefix) {
+ wip.prefix = prefix
+ }
+
+ return b
+}
+
+// NewValue completes the refinement process by constructing a new value
+// that is guaranteed to meet all of the previously-specified refinements.
+//
+// If the original value being refined was known then the result is exactly
+// that value, because otherwise the previous refinement calls would have
+// panicked reporting the refinements as invalid for the value.
+//
+// If the original value was unknown then the result is typically also unknown
+// but may have additional refinements compared to the original. If the applied
+// refinements have reduced the range to a single exact value then the result
+// might be that known value.
+func (b *RefinementBuilder) NewValue() (ret Value) {
+ defer func() {
+ // Regardless of how we return, the new value should have the same
+ // marks as our original value.
+ ret = ret.WithMarks(b.marks)
+ }()
+
+ if b.orig.IsKnown() || b.orig == DynamicVal {
+ return b.orig
+ }
+
+ // We have a few cases where the value has been refined enough that we now
+ // know exactly what the value is, or at least we can produce a more
+ // detailed approximation of it.
+ switch b.wip.null() {
+ case tristateTrue:
+ // There is only one null value of each type so this is now known.
+ return NullVal(b.orig.Type())
+ case tristateFalse:
+ // If we know it's definitely not null then we might have enough
+ // information to construct a known, non-null value.
+ if rfn, ok := b.wip.(*refinementNumber); ok {
+ // If both bounds are inclusive and equal then our value can
+ // only be the same number as the bounds.
+ if rfn.maxInc && rfn.minInc {
+ if rfn.min != NilVal && rfn.max != NilVal {
+ eq := rfn.min.Equals(rfn.max)
+ if eq.IsKnown() && eq.True() {
+ return rfn.min
+ }
+ }
+ }
+ } else if rfn, ok := b.wip.(*refinementCollection); ok {
+ // If both of the bounds are equal then we know the length is
+ // the same number as the bounds.
+ if rfn.minLen == rfn.maxLen {
+ knownLen := rfn.minLen
+ ty := b.orig.Type()
+ if knownLen == 0 {
+ // If we know the length is zero then we can construct
+ // a known value of any collection kind.
+ switch {
+ case ty.IsListType():
+ return ListValEmpty(ty.ElementType())
+ case ty.IsSetType():
+ return SetValEmpty(ty.ElementType())
+ case ty.IsMapType():
+ return MapValEmpty(ty.ElementType())
+ }
+ } else if ty.IsListType() {
+ // If we know the length of the list then we can
+ // create a known list with unknown elements instead
+ // of a wholly-unknown list.
+ elems := make([]Value, knownLen)
+ unk := UnknownVal(ty.ElementType())
+ for i := range elems {
+ elems[i] = unk
+ }
+ return ListVal(elems)
+ } else if ty.IsSetType() && knownLen == 1 {
+ // If we know we have a one-element set then we
+ // know the one element can't possibly coalesce with
+ // anything else and so we can create a known set with
+ // an unknown element.
+ return SetVal([]Value{UnknownVal(ty.ElementType())})
+ }
+ }
+ }
+ }
+
+ return Value{
+ ty: b.orig.ty,
+ v: &unknownType{refinement: b.wip},
+ }
+}
+
+// unknownValRefinment is an interface pretending to be a sum type representing
+// the different kinds of unknown value refinements we support for different
+// types of value.
+type unknownValRefinement interface {
+ unknownValRefinementSigil()
+ copy() unknownValRefinement
+ null() tristateBool
+ setNull(tristateBool)
+ rawEqual(other unknownValRefinement) bool
+ GoString() string
+}
+
+type refinementString struct {
+ refinementNullable
+ prefix string
+}
+
+func (r *refinementString) unknownValRefinementSigil() {}
+
+func (r *refinementString) copy() unknownValRefinement {
+ ret := *r
+ // Everything in refinementString is immutable, so a shallow copy is sufficient.
+ return &ret
+}
+
+func (r *refinementString) rawEqual(other unknownValRefinement) bool {
+ {
+ other, ok := other.(*refinementString)
+ if !ok {
+ return false
+ }
+ return (r.refinementNullable.rawEqual(&other.refinementNullable) &&
+ r.prefix == other.prefix)
+ }
+}
+
+func (r *refinementString) GoString() string {
+ var b strings.Builder
+ b.WriteString(r.refinementNullable.GoString())
+ if r.prefix != "" {
+ fmt.Fprintf(&b, ".StringPrefixFull(%q)", r.prefix)
+ }
+ return b.String()
+}
+
+type refinementNumber struct {
+ refinementNullable
+ min, max Value
+ minInc, maxInc bool
+}
+
+func (r *refinementNumber) unknownValRefinementSigil() {}
+
+func (r *refinementNumber) copy() unknownValRefinement {
+ ret := *r
+ // Everything in refinementNumber is immutable, so a shallow copy is sufficient.
+ return &ret
+}
+
+func (r *refinementNumber) rawEqual(other unknownValRefinement) bool {
+ {
+ other, ok := other.(*refinementNumber)
+ if !ok {
+ return false
+ }
+ return (r.refinementNullable.rawEqual(&other.refinementNullable) &&
+ r.min.RawEquals(other.min) &&
+ r.max.RawEquals(other.max) &&
+ r.minInc == other.minInc &&
+ r.maxInc == other.maxInc)
+ }
+}
+
+func (r *refinementNumber) GoString() string {
+ var b strings.Builder
+ b.WriteString(r.refinementNullable.GoString())
+ if r.min != NilVal && r.min != NegativeInfinity {
+ fmt.Fprintf(&b, ".NumberLowerBound(%#v, %t)", r.min, r.minInc)
+ }
+ if r.max != NilVal && r.max != PositiveInfinity {
+ fmt.Fprintf(&b, ".NumberUpperBound(%#v, %t)", r.max, r.maxInc)
+ }
+ return b.String()
+}
+
+func (r *refinementNumber) assertConsistentBounds() {
+ if r.min == NilVal || r.max == NilVal {
+ return // If only one bound is constrained then there's nothing to be inconsistent with
+ }
+ var ok Value
+ if r.minInc != r.maxInc {
+ ok = r.min.LessThan(r.max)
+ } else {
+ ok = r.min.LessThanOrEqualTo(r.max)
+ }
+ if ok.IsKnown() && ok.False() {
+ panic(fmt.Sprintf("number lower bound %#v is greater than upper bound %#v", r.min, r.max))
+ }
+}
+
+type refinementCollection struct {
+ refinementNullable
+ minLen, maxLen int
+}
+
+func (r *refinementCollection) unknownValRefinementSigil() {}
+
+func (r *refinementCollection) copy() unknownValRefinement {
+ ret := *r
+ // Everything in refinementCollection is immutable, so a shallow copy is sufficient.
+ return &ret
+}
+
+func (r *refinementCollection) rawEqual(other unknownValRefinement) bool {
+ {
+ other, ok := other.(*refinementCollection)
+ if !ok {
+ return false
+ }
+ return (r.refinementNullable.rawEqual(&other.refinementNullable) &&
+ r.minLen == other.minLen &&
+ r.maxLen == other.maxLen)
+ }
+}
+
+func (r *refinementCollection) GoString() string {
+ var b strings.Builder
+ b.WriteString(r.refinementNullable.GoString())
+ if r.minLen != 0 {
+ fmt.Fprintf(&b, ".CollectionLengthLowerBound(%d)", r.minLen)
+ }
+ if r.maxLen != math.MaxInt {
+ fmt.Fprintf(&b, ".CollectionLengthUpperBound(%d)", r.maxLen)
+ }
+ return b.String()
+}
+
+func (r *refinementCollection) assertConsistentLengthBounds() {
+ if r.maxLen < r.minLen {
+ panic(fmt.Sprintf("collection length upper bound %d is less than lower bound %d", r.maxLen, r.minLen))
+ }
+}
+
+type refinementNullable struct {
+ isNull tristateBool
+}
+
+func (r *refinementNullable) unknownValRefinementSigil() {}
+
+func (r *refinementNullable) copy() unknownValRefinement {
+ ret := *r
+ // Everything in refinementJustNull is immutable, so a shallow copy is sufficient.
+ return &ret
+}
+
+func (r *refinementNullable) null() tristateBool {
+ return r.isNull
+}
+
+func (r *refinementNullable) setNull(v tristateBool) {
+ r.isNull = v
+}
+
+func (r *refinementNullable) rawEqual(other unknownValRefinement) bool {
+ {
+ other, ok := other.(*refinementNullable)
+ if !ok {
+ return false
+ }
+ return r.isNull == other.isNull
+ }
+}
+
+func (r *refinementNullable) GoString() string {
+ switch r.isNull {
+ case tristateFalse:
+ return ".NotNull()"
+ case tristateTrue:
+ return ".Null()"
+ default:
+ return ""
+ }
+}
+
+type tristateBool rune
+
+const tristateTrue tristateBool = 'T'
+const tristateFalse tristateBool = 'F'
+const tristateUnknown tristateBool = 0
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/value.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value.go
new file mode 100644
index 00000000000..e3d0051bb2e
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value.go
@@ -0,0 +1,143 @@
+package cty
+
+// Value represents a value of a particular type, and is the interface by
+// which operations are executed on typed values.
+//
+// Value has two different classes of method. Operation methods stay entirely
+// within the type system (methods accept and return Value instances) and
+// are intended for use in implementing a language in terms of cty, while
+// integration methods either enter or leave the type system, working with
+// native Go values. Operation methods are guaranteed to support all of the
+// expected short-circuit behavior for unknown and dynamic values, while
+// integration methods may not.
+//
+// The philosophy for the operations API is that it's the caller's
+// responsibility to ensure that the given types and values satisfy the
+// specified invariants during a separate type check, so that the caller is
+// able to return errors to its user from the application's own perspective.
+//
+// Consequently the design of these methods assumes such checks have already
+// been done and panics if any invariants turn out not to be satisfied. These
+// panic errors are not intended to be handled, but rather indicate a bug in
+// the calling application that should be fixed with more checks prior to
+// executing operations.
+//
+// A related consequence of this philosophy is that no automatic type
+// conversions are done. If a method specifies that its argument must be
+// number then it's the caller's responsibility to do that conversion before
+// the call, thus allowing the application to have more constrained conversion
+// rules than are offered by the built-in converter where necessary.
+type Value struct {
+ ty Type
+ v any
+}
+
+// Type returns the type of the value.
+func (val Value) Type() Type {
+ return val.ty
+}
+
+// IsKnown returns true if the value is known. That is, if it is not
+// the result of the unknown value constructor Unknown(...), and is not
+// the result of an operation on another unknown value.
+//
+// Unknown values are only produced either directly or as a result of
+// operating on other unknown values, and so an application that never
+// introduces Unknown values can be guaranteed to never receive any either.
+func (val Value) IsKnown() bool {
+ if val.IsMarked() {
+ return val.unmarkForce().IsKnown()
+ }
+ _, unknown := val.v.(*unknownType)
+ return !unknown
+}
+
+// IsNull returns true if the value is null. Values of any type can be
+// null, but any operations on a null value will panic. No operation ever
+// produces null, so an application that never introduces Null values can
+// be guaranteed to never receive any either.
+func (val Value) IsNull() bool {
+ if val.IsMarked() {
+ return val.unmarkForce().IsNull()
+ }
+ return val.v == nil
+}
+
+// NilVal is an invalid Value that can be used as a placeholder when returning
+// with an error from a function that returns (Value, error).
+//
+// NilVal is *not* a valid error and so no operations may be performed on it.
+// Any attempt to use it will result in a panic.
+//
+// This should not be confused with the idea of a Null value, as returned by
+// NullVal. NilVal is a nil within the *Go* type system, and is invalid in
+// the cty type system. Null values *do* exist in the cty type system.
+var NilVal = Value{
+ ty: Type{typeImpl: nil},
+ v: nil,
+}
+
+// IsWhollyKnown is an extension of IsKnown that also recursively checks
+// inside collections and structures to see if there are any nested unknown
+// values.
+func (val Value) IsWhollyKnown() bool {
+ if val.IsMarked() {
+ return val.unmarkForce().IsWhollyKnown()
+ }
+
+ if !val.IsKnown() {
+ return false
+ }
+
+ if val.IsNull() {
+ // Can't recurse into a null, so we're done
+ return true
+ }
+
+ switch {
+ case val.CanIterateElements():
+ for it := val.ElementIterator(); it.Next(); {
+ _, ev := it.Element()
+ if !ev.IsWhollyKnown() {
+ return false
+ }
+ }
+ return true
+ default:
+ return true
+ }
+}
+
+// HasWhollyKnownType checks if the value is dynamic, or contains any nested
+// DynamicVal. This implies that both the value is not known, and the final
+// type may change.
+func (val Value) HasWhollyKnownType() bool {
+ // a null dynamic type is known
+ if val.IsNull() {
+ return true
+ }
+
+ // an unknown DynamicPseudoType is a DynamicVal, but we don't want to
+ // check that value for equality here, since this method is used within the
+ // equality check.
+ if !val.IsKnown() && val.ty == DynamicPseudoType {
+ return false
+ }
+
+ if val.CanIterateElements() {
+ // if the value is not known, then we can look directly at the internal
+ // types
+ if !val.IsKnown() {
+ return !val.ty.HasDynamicTypes()
+ }
+
+ for it := val.ElementIterator(); it.Next(); {
+ _, ev := it.Element()
+ if !ev.HasWhollyKnownType() {
+ return false
+ }
+ }
+ }
+
+ return true
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_init.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_init.go
new file mode 100644
index 00000000000..be20043bb72
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_init.go
@@ -0,0 +1,366 @@
+package cty
+
+import (
+ "fmt"
+ "math/big"
+ "reflect"
+
+ "github.com/zclconf/go-cty/cty/ctystrings"
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// BoolVal returns a Value of type Number whose internal value is the given
+// bool.
+func BoolVal(v bool) Value {
+ return Value{
+ ty: Bool,
+ v: v,
+ }
+}
+
+// NumberVal returns a Value of type Number whose internal value is the given
+// big.Float. The returned value becomes the owner of the big.Float object,
+// and so it's forbidden for the caller to mutate the object after it's
+// wrapped in this way.
+func NumberVal(v *big.Float) Value {
+ return Value{
+ ty: Number,
+ v: v,
+ }
+}
+
+// ParseNumberVal returns a Value of type number produced by parsing the given
+// string as a decimal real number. To ensure that two identical strings will
+// always produce an equal number, always use this function to derive a number
+// from a string; it will ensure that the precision and rounding mode for the
+// internal big decimal is configured in a consistent way.
+//
+// If the given string cannot be parsed as a number, the returned error has
+// the message "a number is required", making it suitable to return to an
+// end-user to signal a type conversion error.
+//
+// If the given string contains a number that becomes a recurring fraction
+// when expressed in binary then it will be truncated to have a 512-bit
+// mantissa. Note that this is a higher precision than that of a float64,
+// so coverting the same decimal number first to float64 and then calling
+// NumberFloatVal will not produce an equal result; the conversion first
+// to float64 will round the mantissa to fewer than 512 bits.
+func ParseNumberVal(s string) (Value, error) {
+ // Base 10, precision 512, and rounding to nearest even is the standard
+ // way to handle numbers arriving as strings.
+ f, _, err := big.ParseFloat(s, 10, 512, big.ToNearestEven)
+ if err != nil {
+ return NilVal, fmt.Errorf("a number is required")
+ }
+ return NumberVal(f), nil
+}
+
+// MustParseNumberVal is like ParseNumberVal but it will panic in case of any
+// error. It can be used during initialization or any other situation where
+// the given string is a constant or otherwise known to be correct by the
+// caller.
+func MustParseNumberVal(s string) Value {
+ ret, err := ParseNumberVal(s)
+ if err != nil {
+ panic(err)
+ }
+ return ret
+}
+
+// NumberIntVal returns a Value of type Number whose internal value is equal
+// to the given integer.
+func NumberIntVal(v int64) Value {
+ return NumberVal(new(big.Float).SetInt64(v))
+}
+
+// NumberUIntVal returns a Value of type Number whose internal value is equal
+// to the given unsigned integer.
+func NumberUIntVal(v uint64) Value {
+ return NumberVal(new(big.Float).SetUint64(v))
+}
+
+// NumberFloatVal returns a Value of type Number whose internal value is
+// equal to the given float.
+func NumberFloatVal(v float64) Value {
+ return NumberVal(new(big.Float).SetFloat64(v))
+}
+
+// StringVal returns a Value of type String whose internal value is the
+// given string.
+//
+// Strings must be UTF-8 encoded sequences of valid unicode codepoints, and
+// they are NFC-normalized on entry into the world of cty values.
+//
+// If the given string is not valid UTF-8 then behavior of string operations
+// is undefined.
+func StringVal(v string) Value {
+ return Value{
+ ty: String,
+ v: NormalizeString(v),
+ }
+}
+
+// NormalizeString applies the same normalization that cty applies when
+// constructing string values.
+//
+// A return value from this function can be meaningfully compared byte-for-byte
+// with a Value.AsString result.
+func NormalizeString(s string) string {
+ return ctystrings.Normalize(s)
+}
+
+// ObjectVal returns a Value of an object type whose structure is defined
+// by the key names and value types in the given map.
+func ObjectVal(attrs map[string]Value) Value {
+ attrTypes := make(map[string]Type, len(attrs))
+ attrVals := make(map[string]any, len(attrs))
+
+ for attr, val := range attrs {
+ attr = NormalizeString(attr)
+ attrTypes[attr] = val.ty
+ attrVals[attr] = val.v
+ }
+
+ return Value{
+ ty: Object(attrTypes),
+ v: attrVals,
+ }
+}
+
+// TupleVal returns a Value of a tuple type whose element types are
+// defined by the value types in the given slice.
+func TupleVal(elems []Value) Value {
+ elemTypes := make([]Type, len(elems))
+ elemVals := make([]any, len(elems))
+
+ for i, val := range elems {
+ elemTypes[i] = val.ty
+ elemVals[i] = val.v
+ }
+
+ return Value{
+ ty: Tuple(elemTypes),
+ v: elemVals,
+ }
+}
+
+// ListVal returns a Value of list type whose element type is defined by
+// the types of the given values, which must be homogenous.
+//
+// If the types are not all consistent (aside from elements that are of the
+// dynamic pseudo-type) then this function will panic. It will panic also
+// if the given list is empty, since then the element type cannot be inferred.
+// (See also ListValEmpty.)
+func ListVal(vals []Value) Value {
+ if len(vals) == 0 {
+ panic("must not call ListVal with empty slice")
+ }
+ elementType := DynamicPseudoType
+ rawList := make([]any, len(vals))
+
+ for i, val := range vals {
+ if elementType == DynamicPseudoType {
+ elementType = val.ty
+ } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
+ panic(fmt.Errorf(
+ "inconsistent list element types (%#v then %#v)",
+ elementType, val.ty,
+ ))
+ }
+
+ rawList[i] = val.v
+ }
+
+ return Value{
+ ty: List(elementType),
+ v: rawList,
+ }
+}
+
+// ListValEmpty returns an empty list of the given element type.
+func ListValEmpty(element Type) Value {
+ return Value{
+ ty: List(element),
+ v: []any{},
+ }
+}
+
+// CanListVal returns false if the given Values can not be coalesced
+// into a single List due to inconsistent element types.
+func CanListVal(vals []Value) bool {
+ elementType := DynamicPseudoType
+ for _, val := range vals {
+ if elementType == DynamicPseudoType {
+ elementType = val.ty
+ } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
+ return false
+ }
+ }
+ return true
+}
+
+// MapVal returns a Value of a map type whose element type is defined by
+// the types of the given values, which must be homogenous.
+//
+// If the types are not all consistent (aside from elements that are of the
+// dynamic pseudo-type) then this function will panic. It will panic also
+// if the given map is empty, since then the element type cannot be inferred.
+// (See also MapValEmpty.)
+func MapVal(vals map[string]Value) Value {
+ if len(vals) == 0 {
+ panic("must not call MapVal with empty map")
+ }
+ elementType := DynamicPseudoType
+ rawMap := make(map[string]any, len(vals))
+
+ for key, val := range vals {
+ if elementType == DynamicPseudoType {
+ elementType = val.ty
+ } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
+ panic(fmt.Errorf(
+ "inconsistent map element types (%#v then %#v)",
+ elementType, val.ty,
+ ))
+ }
+
+ rawMap[NormalizeString(key)] = val.v
+ }
+
+ return Value{
+ ty: Map(elementType),
+ v: rawMap,
+ }
+}
+
+// MapValEmpty returns an empty map of the given element type.
+func MapValEmpty(element Type) Value {
+ return Value{
+ ty: Map(element),
+ v: map[string]any{},
+ }
+}
+
+// CanMapVal returns false if the given Values can not be coalesced into a
+// single Map due to inconsistent element types.
+func CanMapVal(vals map[string]Value) bool {
+ elementType := DynamicPseudoType
+ for _, val := range vals {
+ if elementType == DynamicPseudoType {
+ elementType = val.ty
+ } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
+ return false
+ }
+ }
+ return true
+}
+
+// SetVal returns a Value of set type whose element type is defined by
+// the types of the given values, which must be homogenous.
+//
+// If the types are not all consistent (aside from elements that are of the
+// dynamic pseudo-type) then this function will panic. It will panic also
+// if the given list is empty, since then the element type cannot be inferred.
+// (See also SetValEmpty.)
+func SetVal(vals []Value) Value {
+ if len(vals) == 0 {
+ panic("must not call SetVal with empty slice")
+ }
+ elementType := DynamicPseudoType
+ rawList := make([]any, len(vals))
+ var markSets []ValueMarks
+
+ for i, val := range vals {
+ if unmarkedVal, marks := val.UnmarkDeep(); len(marks) > 0 {
+ val = unmarkedVal
+ markSets = append(markSets, marks)
+ }
+ if elementType == DynamicPseudoType {
+ elementType = val.ty
+ } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
+ panic(fmt.Errorf(
+ "inconsistent set element types (%#v then %#v)",
+ elementType, val.ty,
+ ))
+ }
+
+ rawList[i] = val.v
+ }
+
+ rawVal := set.NewSetFromSlice(set.Rules[any](setRules{elementType}), rawList)
+
+ return Value{
+ ty: Set(elementType),
+ v: rawVal,
+ }.WithMarks(markSets...)
+}
+
+// CanSetVal returns false if the given Values can not be coalesced
+// into a single Set due to inconsistent element types.
+func CanSetVal(vals []Value) bool {
+ elementType := DynamicPseudoType
+ var markSets []ValueMarks
+
+ for _, val := range vals {
+ if unmarkedVal, marks := val.UnmarkDeep(); len(marks) > 0 {
+ val = unmarkedVal
+ markSets = append(markSets, marks)
+ }
+ if elementType == DynamicPseudoType {
+ elementType = val.ty
+ } else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
+ return false
+ }
+ }
+ return true
+}
+
+// SetValFromValueSet returns a Value of set type based on an already-constructed
+// ValueSet.
+//
+// The element type of the returned value is the element type of the given
+// set.
+func SetValFromValueSet(s ValueSet) Value {
+ ety := s.ElementType()
+ rawVal := s.s.Copy() // copy so caller can't mutate what we wrap
+
+ return Value{
+ ty: Set(ety),
+ v: rawVal,
+ }
+}
+
+// SetValEmpty returns an empty set of the given element type.
+func SetValEmpty(element Type) Value {
+ return Value{
+ ty: Set(element),
+ v: set.NewSet(set.Rules[any](setRules{element})),
+ }
+}
+
+// CapsuleVal creates a value of the given capsule type using the given
+// wrapVal, which must be a pointer to a value of the capsule type's native
+// type.
+//
+// This function will panic if the given type is not a capsule type, if
+// the given wrapVal is not compatible with the given capsule type, or if
+// wrapVal is not a pointer.
+func CapsuleVal(ty Type, wrapVal any) Value {
+ if !ty.IsCapsuleType() {
+ panic("not a capsule type")
+ }
+
+ wv := reflect.ValueOf(wrapVal)
+ if wv.Kind() != reflect.Ptr {
+ panic("wrapVal is not a pointer")
+ }
+
+ it := ty.typeImpl.(*capsuleType).GoType
+ if !wv.Type().Elem().AssignableTo(it) {
+ panic("wrapVal target is not compatible with the given capsule type")
+ }
+
+ return Value{
+ ty: ty,
+ v: wrapVal,
+ }
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_ops.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_ops.go
new file mode 100644
index 00000000000..f1d69af8949
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_ops.go
@@ -0,0 +1,1573 @@
+package cty
+
+import (
+ "fmt"
+ "iter"
+ "math/big"
+
+ "github.com/zclconf/go-cty/cty/set"
+)
+
+// GoString is an implementation of fmt.GoStringer that produces concise
+// source-like representations of values suitable for use in debug messages.
+func (val Value) GoString() string {
+ if val.IsMarked() {
+ unVal, marks := val.Unmark()
+ if len(marks) == 1 {
+ var mark any
+ for m := range marks {
+ mark = m
+ }
+ return fmt.Sprintf("%#v.Mark(%#v)", unVal, mark)
+ }
+ return fmt.Sprintf("%#v.WithMarks(%#v)", unVal, marks)
+ }
+
+ if val == NilVal {
+ return "cty.NilVal"
+ }
+
+ if val.IsNull() {
+ return fmt.Sprintf("cty.NullVal(%#v)", val.ty)
+ }
+ if val == DynamicVal { // is unknown, so must be before the IsKnown check below
+ return "cty.DynamicVal"
+ }
+ if !val.IsKnown() {
+ rfn := val.v.(*unknownType).refinement
+ var suffix string
+ if rfn != nil {
+ calls := rfn.GoString()
+ if calls == ".NotNull()" {
+ suffix = ".RefineNotNull()"
+ } else {
+ suffix = ".Refine()" + rfn.GoString() + ".NewValue()"
+ }
+ }
+ return fmt.Sprintf("cty.UnknownVal(%#v)%s", val.ty, suffix)
+ }
+
+ // By the time we reach here we've dealt with all of the exceptions around
+ // unknowns and nulls, so we're guaranteed that the values are the
+ // canonical internal representation of the given type.
+
+ switch val.ty {
+ case Bool:
+ if val.v.(bool) {
+ return "cty.True"
+ }
+ return "cty.False"
+ case Number:
+ if f, ok := val.v.(big.Float); ok {
+ panic(fmt.Sprintf("number value contains big.Float value %s, rather than pointer to big.Float", f.Text('g', -1)))
+ }
+ fv := val.v.(*big.Float)
+ // We'll try to use NumberIntVal or NumberFloatVal if we can, since
+ // the fully-general initializer call is pretty ugly-looking.
+ if fv.IsInt() {
+ return fmt.Sprintf("cty.NumberIntVal(%#v)", fv)
+ }
+ if rfv, accuracy := fv.Float64(); accuracy == big.Exact {
+ return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv)
+ }
+ return fmt.Sprintf("cty.MustParseNumberVal(%q)", fv.Text('f', -1))
+ case String:
+ return fmt.Sprintf("cty.StringVal(%#v)", val.v)
+ }
+
+ switch {
+ case val.ty.IsSetType():
+ vals := val.AsValueSlice()
+ if len(vals) == 0 {
+ return fmt.Sprintf("cty.SetValEmpty(%#v)", val.ty.ElementType())
+ }
+ return fmt.Sprintf("cty.SetVal(%#v)", vals)
+ case val.ty.IsListType():
+ vals := val.AsValueSlice()
+ if len(vals) == 0 {
+ return fmt.Sprintf("cty.ListValEmpty(%#v)", val.ty.ElementType())
+ }
+ return fmt.Sprintf("cty.ListVal(%#v)", vals)
+ case val.ty.IsMapType():
+ vals := val.AsValueMap()
+ if len(vals) == 0 {
+ return fmt.Sprintf("cty.MapValEmpty(%#v)", val.ty.ElementType())
+ }
+ return fmt.Sprintf("cty.MapVal(%#v)", vals)
+ case val.ty.IsTupleType():
+ if val.ty.Equals(EmptyTuple) {
+ return "cty.EmptyTupleVal"
+ }
+ vals := val.AsValueSlice()
+ return fmt.Sprintf("cty.TupleVal(%#v)", vals)
+ case val.ty.IsObjectType():
+ if val.ty.Equals(EmptyObject) {
+ return "cty.EmptyObjectVal"
+ }
+ vals := val.AsValueMap()
+ return fmt.Sprintf("cty.ObjectVal(%#v)", vals)
+ case val.ty.IsCapsuleType():
+ impl := val.ty.CapsuleOps().GoString
+ if impl == nil {
+ return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v)
+ }
+ return impl(val.EncapsulatedValue())
+ }
+
+ // Default exposes implementation details, so should actually cover
+ // all of the cases above for good caller UX.
+ return fmt.Sprintf("cty.Value{ty: %#v, v: %#v}", val.ty, val.v)
+}
+
+// Equals returns True if the receiver and the given other value have the
+// same type and are exactly equal in value.
+//
+// As a special case, two null values are always equal regardless of type.
+//
+// The usual short-circuit rules apply, so the result will be unknown if
+// either of the given values are.
+//
+// Use RawEquals to compare if two values are equal *ignoring* the
+// short-circuit rules and the exception for null values.
+func (val Value) Equals(other Value) Value {
+ if val.ContainsMarked() || other.ContainsMarked() {
+ unmarkedVal, valMarks := val.UnmarkDeep()
+ unmarkedOther, otherMarks := other.UnmarkDeep()
+
+ // As a special case, if we have one null and one non-null value then
+ // we only preserve top-level marks from either value. This is a simplistic
+ // approximation of the idea that nested marks should be preserved only if
+ // they were relevant to the decision, and ideally this would be implemented
+ // more generally so that e.g. comparing an empty list with a one-element
+ // list whose element is marked would not preserve that nested mark either.
+ // Perhaps a future version will improve this, but for now this just deals
+ // with the common case of comparing something with a null value as a more
+ // general alternative to calling [Value.IsNull].
+ nullCount := 0
+ if val.IsNull() {
+ nullCount++
+ }
+ if other.IsNull() {
+ nullCount++
+ }
+ if nullCount == 1 {
+ // The following is an okay simplification because the rest of this
+ // function, which we'll access through the recursive call below,
+ // has early returns for various cases where one operand is null
+ // that all avoid interacting with nested values.
+ _, valMarks = val.Unmark()
+ _, otherMarks = other.Unmark()
+ }
+
+ return unmarkedVal.Equals(unmarkedOther).WithMarks(valMarks, otherMarks)
+ }
+
+ // Some easy cases with comparisons to null.
+ switch {
+ case val.IsNull() && definitelyNotNull(other):
+ return False
+ case other.IsNull() && definitelyNotNull(val):
+ return False
+ }
+ // If we have one known value and one unknown value then we may be
+ // able to quickly disqualify equality based on the range of the unknown
+ // value.
+ if val.IsKnown() && !other.IsKnown() {
+ otherRng := other.Range()
+ if ok := otherRng.Includes(val); ok.IsKnown() && ok.False() {
+ return False
+ }
+ } else if other.IsKnown() && !val.IsKnown() {
+ valRng := val.Range()
+ if ok := valRng.Includes(other); ok.IsKnown() && ok.False() {
+ return False
+ }
+ }
+
+ // We need to deal with unknown values before anything else with nulls
+ // because any unknown value that hasn't yet been refined as non-null
+ // could become null, and nulls of any types are equal to one another.
+ unknownResult := func() Value {
+ return UnknownVal(Bool).Refine().NotNull().NewValue()
+ }
+ switch {
+ case !val.IsKnown() && !other.IsKnown():
+ // both unknown
+ return unknownResult()
+ case val.IsKnown() && !other.IsKnown():
+ switch {
+ case val.IsNull(), other.ty.HasDynamicTypes():
+ // If known is Null, we need to wait for the unknown value since
+ // nulls of any type are equal.
+ // An unknown with a dynamic type compares as unknown, which we need
+ // to check before the type comparison below.
+ return unknownResult()
+ case !val.ty.Equals(other.ty):
+ // There is no null comparison or dynamic types, so unequal types
+ // will never be equal.
+ return False
+ default:
+ return unknownResult()
+ }
+ case other.IsKnown() && !val.IsKnown():
+ switch {
+ case other.IsNull(), val.ty.HasDynamicTypes():
+ // If known is Null, we need to wait for the unknown value since
+ // nulls of any type are equal.
+ // An unknown with a dynamic type compares as unknown, which we need
+ // to check before the type comparison below.
+ return unknownResult()
+ case !other.ty.Equals(val.ty):
+ // There's no null comparison or dynamic types, so unequal types
+ // will never be equal.
+ return False
+ default:
+ return unknownResult()
+ }
+ }
+
+ switch {
+ case val.IsNull() && other.IsNull():
+ // Nulls are always equal, regardless of type
+ return BoolVal(true)
+ case val.IsNull() || other.IsNull():
+ // If only one is null then the result must be false
+ return BoolVal(false)
+ }
+
+ // Check if there are any nested dynamic values making this comparison
+ // unknown.
+ if !val.HasWhollyKnownType() || !other.HasWhollyKnownType() {
+ // Even if we have dynamic values, we can still determine inequality if
+ // there is no way the types could later conform.
+ if val.ty.TestConformance(other.ty) != nil && other.ty.TestConformance(val.ty) != nil {
+ return BoolVal(false)
+ }
+
+ return unknownResult()
+ }
+
+ if !val.ty.Equals(other.ty) {
+ return BoolVal(false)
+ }
+
+ ty := val.ty
+ result := false
+
+ switch {
+ case ty == Number:
+ result = rawNumberEqual(val.v.(*big.Float), other.v.(*big.Float))
+ case ty == Bool:
+ result = val.v.(bool) == other.v.(bool)
+ case ty == String:
+ // Simple equality is safe because we NFC-normalize strings as they
+ // enter our world from StringVal, and so we can assume strings are
+ // always in normal form.
+ result = val.v.(string) == other.v.(string)
+ case ty.IsObjectType():
+ oty := ty.typeImpl.(typeObject)
+ result = true
+ for attr, aty := range oty.AttrTypes {
+ lhs := Value{
+ ty: aty,
+ v: val.v.(map[string]any)[attr],
+ }
+ rhs := Value{
+ ty: aty,
+ v: other.v.(map[string]any)[attr],
+ }
+ eq := lhs.Equals(rhs)
+ if !eq.IsKnown() {
+ return unknownResult()
+ }
+ if eq.False() {
+ result = false
+ break
+ }
+ }
+ case ty.IsTupleType():
+ tty := ty.typeImpl.(typeTuple)
+ result = true
+ for i, ety := range tty.ElemTypes {
+ lhs := Value{
+ ty: ety,
+ v: val.v.([]any)[i],
+ }
+ rhs := Value{
+ ty: ety,
+ v: other.v.([]any)[i],
+ }
+ eq := lhs.Equals(rhs)
+ if !eq.IsKnown() {
+ return unknownResult()
+ }
+ if eq.False() {
+ result = false
+ break
+ }
+ }
+ case ty.IsListType():
+ ety := ty.typeImpl.(typeList).ElementTypeT
+ if len(val.v.([]any)) == len(other.v.([]any)) {
+ result = true
+ for i := range val.v.([]any) {
+ lhs := Value{
+ ty: ety,
+ v: val.v.([]any)[i],
+ }
+ rhs := Value{
+ ty: ety,
+ v: other.v.([]any)[i],
+ }
+ eq := lhs.Equals(rhs)
+ if !eq.IsKnown() {
+ return unknownResult()
+ }
+ if eq.False() {
+ result = false
+ break
+ }
+ }
+ }
+ case ty.IsSetType():
+ s1 := val.v.(set.Set[any])
+ s2 := other.v.(set.Set[any])
+ equal := true
+
+ // Two sets are equal if all of their values are known and all values
+ // in one are also in the other.
+ for it := s1.Iterator(); it.Next(); {
+ rv := it.Value()
+ if _, unknown := rv.(*unknownType); unknown { // "*unknownType" is the internal representation of unknown-ness
+ return unknownResult()
+ }
+ if !s2.Has(rv) {
+ equal = false
+ }
+ }
+ for it := s2.Iterator(); it.Next(); {
+ rv := it.Value()
+ if _, unknown := rv.(*unknownType); unknown { // "*unknownType" is the internal representation of unknown-ness
+ return unknownResult()
+ }
+ if !s1.Has(rv) {
+ equal = false
+ }
+ }
+
+ result = equal
+ case ty.IsMapType():
+ ety := ty.typeImpl.(typeMap).ElementTypeT
+ if len(val.v.(map[string]any)) == len(other.v.(map[string]any)) {
+ result = true
+ for k := range val.v.(map[string]any) {
+ if _, ok := other.v.(map[string]any)[k]; !ok {
+ result = false
+ break
+ }
+ lhs := Value{
+ ty: ety,
+ v: val.v.(map[string]any)[k],
+ }
+ rhs := Value{
+ ty: ety,
+ v: other.v.(map[string]any)[k],
+ }
+ eq := lhs.Equals(rhs)
+ if !eq.IsKnown() {
+ return unknownResult()
+ }
+ if eq.False() {
+ result = false
+ break
+ }
+ }
+ }
+ case ty.IsCapsuleType():
+ impl := val.ty.CapsuleOps().Equals
+ if impl == nil {
+ impl := val.ty.CapsuleOps().RawEquals
+ if impl == nil {
+ // A capsule type's encapsulated value is a pointer to a value of its
+ // native type, so we can just compare these to get the identity test
+ // we need.
+ return BoolVal(val.v == other.v)
+ }
+ return BoolVal(impl(val.v, other.v))
+ }
+ ret := impl(val.v, other.v)
+ if !ret.Type().Equals(Bool) {
+ panic(fmt.Sprintf("Equals for %#v returned %#v, not cty.Bool", ty, ret.Type()))
+ }
+ return ret
+
+ default:
+ // should never happen
+ panic(fmt.Errorf("unsupported value type %#v in Equals", ty))
+ }
+
+ return BoolVal(result)
+}
+
+// NotEqual is a shorthand for Equals followed by Not.
+func (val Value) NotEqual(other Value) Value {
+ return val.Equals(other).Not()
+}
+
+// True returns true if the receiver is True, false if False, and panics if
+// the receiver is not of type Bool.
+//
+// This is a helper function to help write application logic that works with
+// values, rather than a first-class operation. It does not work with unknown
+// or null values. For more robust handling with unknown value
+// short-circuiting, use val.Equals(cty.True).
+func (val Value) True() bool {
+ val.assertUnmarked()
+ if val.ty != Bool {
+ panic("not bool")
+ }
+ return val.Equals(True).v.(bool)
+}
+
+// False is the opposite of True.
+func (val Value) False() bool {
+ return !val.True()
+}
+
+// RawEquals returns true if and only if the two given values have the same
+// type and equal value, ignoring the usual short-circuit rules about
+// unknowns and dynamic types.
+//
+// This method is more appropriate for testing than for real use, since it
+// skips over usual semantics around unknowns but as a consequence allows
+// testing the result of another operation that is expected to return unknown.
+// It returns a primitive Go bool rather than a Value to remind us that it
+// is not a first-class value operation.
+func (val Value) RawEquals(other Value) bool {
+ if !val.ty.Equals(other.ty) {
+ return false
+ }
+ if !val.HasSameMarks(other) {
+ return false
+ }
+ // Since we've now checked the marks, we'll unmark for the rest of this...
+ val = val.unmarkForce()
+ other = other.unmarkForce()
+
+ if (!val.IsKnown()) && (!other.IsKnown()) {
+ // If either unknown value has refinements then they must match.
+ valRfn := val.v.(*unknownType).refinement
+ otherRfn := other.v.(*unknownType).refinement
+ switch {
+ case (valRfn == nil) != (otherRfn == nil):
+ return false
+ case valRfn != nil:
+ return valRfn.rawEqual(otherRfn)
+ default:
+ return true
+ }
+ }
+ if (val.IsKnown() && !other.IsKnown()) || (other.IsKnown() && !val.IsKnown()) {
+ return false
+ }
+ if val.IsNull() && other.IsNull() {
+ return true
+ }
+ if (val.IsNull() && !other.IsNull()) || (other.IsNull() && !val.IsNull()) {
+ return false
+ }
+ if val.ty == DynamicPseudoType && other.ty == DynamicPseudoType {
+ return true
+ }
+
+ ty := val.ty
+ switch {
+ case ty == Number || ty == Bool || ty == String || ty == DynamicPseudoType:
+ return val.Equals(other).True()
+ case ty.IsObjectType():
+ oty := ty.typeImpl.(typeObject)
+ for attr, aty := range oty.AttrTypes {
+ lhs := Value{
+ ty: aty,
+ v: val.v.(map[string]any)[attr],
+ }
+ rhs := Value{
+ ty: aty,
+ v: other.v.(map[string]any)[attr],
+ }
+ eq := lhs.RawEquals(rhs)
+ if !eq {
+ return false
+ }
+ }
+ return true
+ case ty.IsTupleType():
+ tty := ty.typeImpl.(typeTuple)
+ for i, ety := range tty.ElemTypes {
+ lhs := Value{
+ ty: ety,
+ v: val.v.([]any)[i],
+ }
+ rhs := Value{
+ ty: ety,
+ v: other.v.([]any)[i],
+ }
+ eq := lhs.RawEquals(rhs)
+ if !eq {
+ return false
+ }
+ }
+ return true
+ case ty.IsListType():
+ ety := ty.typeImpl.(typeList).ElementTypeT
+ if len(val.v.([]any)) == len(other.v.([]any)) {
+ for i := range val.v.([]any) {
+ lhs := Value{
+ ty: ety,
+ v: val.v.([]any)[i],
+ }
+ rhs := Value{
+ ty: ety,
+ v: other.v.([]any)[i],
+ }
+ eq := lhs.RawEquals(rhs)
+ if !eq {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+
+ case ty.IsSetType():
+ // Convert the set values into a slice so that we can compare each
+ // value. This is safe because the underlying sets are ordered (see
+ // setRules in set_internals.go), and so the results are guaranteed to
+ // be in a consistent order for two equal sets
+ setList1 := val.AsValueSlice()
+ setList2 := other.AsValueSlice()
+
+ // If both physical sets have the same length and they have all of their
+ // _known_ values in common, we know that both sets also have the same
+ // number of unknown values.
+ if len(setList1) != len(setList2) {
+ return false
+ }
+
+ for i := range setList1 {
+ eq := setList1[i].RawEquals(setList2[i])
+ if !eq {
+ return false
+ }
+ }
+
+ // If we got here without returning false already then our sets are
+ // equal enough for RawEquals purposes.
+ return true
+
+ case ty.IsMapType():
+ ety := ty.typeImpl.(typeMap).ElementTypeT
+ if !val.HasSameMarks(other) {
+ return false
+ }
+ valUn, _ := val.Unmark()
+ otherUn, _ := other.Unmark()
+ if len(valUn.v.(map[string]any)) == len(otherUn.v.(map[string]any)) {
+ for k := range valUn.v.(map[string]any) {
+ if _, ok := otherUn.v.(map[string]any)[k]; !ok {
+ return false
+ }
+ lhs := Value{
+ ty: ety,
+ v: valUn.v.(map[string]any)[k],
+ }
+ rhs := Value{
+ ty: ety,
+ v: otherUn.v.(map[string]any)[k],
+ }
+ eq := lhs.RawEquals(rhs)
+ if !eq {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+ case ty.IsCapsuleType():
+ impl := val.ty.CapsuleOps().RawEquals
+ if impl == nil {
+ // A capsule type's encapsulated value is a pointer to a value of its
+ // native type, so we can just compare these to get the identity test
+ // we need.
+ return val.v == other.v
+ }
+ return impl(val.v, other.v)
+
+ default:
+ // should never happen
+ panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty))
+ }
+}
+
+// Add returns the sum of the receiver and the given other value. Both values
+// must be numbers; this method will panic if not.
+func (val Value) Add(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.Add(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ ret := shortCircuit.RefineWith(numericRangeArithmetic(Value.Add, val.Range(), other.Range()))
+ return ret.RefineNotNull()
+ }
+
+ ret := new(big.Float)
+ ret.Add(val.v.(*big.Float), other.v.(*big.Float))
+ return NumberVal(ret)
+}
+
+// Subtract returns receiver minus the given other value. Both values must be
+// numbers; this method will panic if not.
+func (val Value) Subtract(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.Subtract(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ ret := shortCircuit.RefineWith(numericRangeArithmetic(Value.Subtract, val.Range(), other.Range()))
+ return ret.RefineNotNull()
+ }
+
+ return val.Add(other.Negate())
+}
+
+// Negate returns the numeric negative of the receiver, which must be a number.
+// This method will panic when given a value of any other type.
+func (val Value) Negate() Value {
+ if val.IsMarked() {
+ val, valMarks := val.Unmark()
+ return val.Negate().WithMarks(valMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ ret := new(big.Float).Neg(val.v.(*big.Float))
+ return NumberVal(ret)
+}
+
+// Multiply returns the product of the receiver and the given other value.
+// Both values must be numbers; this method will panic if not.
+func (val Value) Multiply(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.Multiply(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
+ // If either value is exactly zero then the result must either be
+ // zero or an error.
+ if val == Zero || other == Zero {
+ return Zero
+ }
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ ret := shortCircuit.RefineWith(numericRangeArithmetic(Value.Multiply, val.Range(), other.Range()))
+ return ret.RefineNotNull()
+ }
+
+ // find the larger precision of the arguments
+ resPrec := val.v.(*big.Float).Prec()
+ otherPrec := other.v.(*big.Float).Prec()
+ if otherPrec > resPrec {
+ resPrec = otherPrec
+ }
+
+ // make sure we have enough precision for the product
+ ret := new(big.Float).SetPrec(512)
+ ret.Mul(val.v.(*big.Float), other.v.(*big.Float))
+
+ // now reduce the precision back to the greater argument, or the minimum
+ // required by the product.
+ minPrec := ret.MinPrec()
+ if minPrec > resPrec {
+ resPrec = minPrec
+ }
+ ret.SetPrec(resPrec)
+
+ return NumberVal(ret)
+}
+
+// Divide returns the quotient of the receiver and the given other value.
+// Both values must be numbers; this method will panic if not.
+//
+// If the "other" value is exactly zero, this operation will return either
+// PositiveInfinity or NegativeInfinity, depending on the sign of the
+// receiver value. For some use-cases the presence of infinities may be
+// undesirable, in which case the caller should check whether the
+// other value equals zero before calling and raise an error instead.
+//
+// If both values are zero or infinity, this function will panic with
+// an instance of big.ErrNaN.
+func (val Value) Divide(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.Divide(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ // TODO: We could potentially refine the range of the result here, but
+ // we don't right now because our division operation is not monotone
+ // if the denominator could potentially be zero.
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ ret := new(big.Float)
+ ret.Quo(val.v.(*big.Float), other.v.(*big.Float))
+ return NumberVal(ret)
+}
+
+// Modulo returns the remainder of an integer division of the receiver and
+// the given other value. Both values must be numbers; this method will panic
+// if not.
+//
+// If the "other" value is exactly zero, this operation will return either
+// PositiveInfinity or NegativeInfinity, depending on the sign of the
+// receiver value. For some use-cases the presence of infinities may be
+// undesirable, in which case the caller should check whether the
+// other value equals zero before calling and raise an error instead.
+//
+// This operation is primarily here for use with nonzero natural numbers.
+// Modulo with "other" as a non-natural number gets somewhat philosophical,
+// and this function takes a position on what that should mean, but callers
+// may wish to disallow such things outright or implement their own modulo
+// if they disagree with the interpretation used here.
+func (val Value) Modulo(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.Modulo(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ // We cheat a bit here with infinities, just abusing the Multiply operation
+ // to get an infinite result of the correct sign.
+ if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity {
+ return val.Multiply(other)
+ }
+
+ if other.RawEquals(Zero) {
+ return val
+ }
+
+ // FIXME: This is a bit clumsy. Should come back later and see if there's a
+ // more straightforward way to do this.
+ rat := val.Divide(other)
+ ratFloorInt, _ := rat.v.(*big.Float).Int(nil)
+
+ // start with a copy of the original larger value so that we do not lose
+ // precision.
+ v := val.v.(*big.Float)
+ work := new(big.Float).Copy(v).SetInt(ratFloorInt)
+ work.Mul(other.v.(*big.Float), work)
+ work.Sub(v, work)
+
+ return NumberVal(work)
+}
+
+// Absolute returns the absolute (signless) value of the receiver, which must
+// be a number or this method will panic.
+func (val Value) Absolute() Value {
+ if val.IsMarked() {
+ val, valMarks := val.Unmark()
+ return val.Absolute().WithMarks(valMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Number)
+ return (*shortCircuit).Refine().NotNull().NumberRangeInclusive(Zero, UnknownVal(Number)).NewValue()
+ }
+
+ ret := (&big.Float{}).Abs(val.v.(*big.Float))
+ return NumberVal(ret)
+}
+
+// GetAttr returns the value of the given attribute of the receiver, which
+// must be of an object type that has an attribute of the given name.
+// This method will panic if the receiver type is not compatible.
+//
+// The method will also panic if the given attribute name is not defined
+// for the value's type. Use the attribute-related methods on Type to
+// check for the validity of an attribute before trying to use it.
+//
+// This method may be called on a value whose type is DynamicPseudoType,
+// in which case the result will also be DynamicVal.
+func (val Value) GetAttr(name string) Value {
+ if val.IsMarked() {
+ val, valMarks := val.Unmark()
+ return val.GetAttr(name).WithMarks(valMarks)
+ }
+
+ if val.ty == DynamicPseudoType {
+ return DynamicVal
+ }
+
+ if !val.ty.IsObjectType() {
+ panic("value is not an object")
+ }
+
+ name = NormalizeString(name)
+ if !val.ty.HasAttribute(name) {
+ panic("value has no attribute of that name")
+ }
+
+ attrType := val.ty.AttributeType(name)
+
+ if !val.IsKnown() {
+ return UnknownVal(attrType)
+ }
+
+ return Value{
+ ty: attrType,
+ v: val.v.(map[string]any)[name],
+ }
+}
+
+// Index returns the value of an element of the receiver, which must have
+// either a list, map or tuple type. This method will panic if the receiver
+// type is not compatible.
+//
+// The key value must be the correct type for the receving collection: a
+// number if the collection is a list or tuple, or a string if it is a map.
+// In the case of a list or tuple, the given number must be convertable to int
+// or this method will panic. The key may alternatively be of
+// DynamicPseudoType, in which case the result itself is an unknown of the
+// collection's element type.
+//
+// The result is of the receiver collection's element type, or in the case
+// of a tuple the type of the specific element index requested.
+//
+// This method may be called on a value whose type is DynamicPseudoType,
+// in which case the result will also be the DynamicValue.
+func (val Value) Index(key Value) Value {
+ if val.IsMarked() || key.IsMarked() {
+ val, valMarks := val.Unmark()
+ key, keyMarks := key.Unmark()
+ return val.Index(key).WithMarks(valMarks, keyMarks)
+ }
+
+ if val.ty == DynamicPseudoType {
+ return DynamicVal
+ }
+
+ switch {
+ case val.Type().IsListType():
+ elty := val.Type().ElementType()
+ if key.Type() == DynamicPseudoType {
+ return UnknownVal(elty)
+ }
+
+ if key.Type() != Number {
+ panic("element key for list must be number")
+ }
+ if !key.IsKnown() {
+ return UnknownVal(elty)
+ }
+
+ if !val.IsKnown() {
+ return UnknownVal(elty)
+ }
+
+ index, accuracy := key.v.(*big.Float).Int64()
+ if accuracy != big.Exact || index < 0 {
+ panic("element key for list must be non-negative integer")
+ }
+
+ return Value{
+ ty: elty,
+ v: val.v.([]any)[index],
+ }
+ case val.Type().IsMapType():
+ elty := val.Type().ElementType()
+ if key.Type() == DynamicPseudoType {
+ return UnknownVal(elty)
+ }
+
+ if key.Type() != String {
+ panic("element key for map must be string")
+ }
+ if !key.IsKnown() {
+ return UnknownVal(elty)
+ }
+
+ if !val.IsKnown() {
+ return UnknownVal(elty)
+ }
+
+ keyStr := key.v.(string)
+
+ return Value{
+ ty: elty,
+ v: val.v.(map[string]any)[keyStr],
+ }
+ case val.Type().IsTupleType():
+ if key.Type() == DynamicPseudoType {
+ return DynamicVal
+ }
+
+ if key.Type() != Number {
+ panic("element key for tuple must be number")
+ }
+ if !key.IsKnown() {
+ return DynamicVal
+ }
+
+ index, accuracy := key.v.(*big.Float).Int64()
+ if accuracy != big.Exact || index < 0 {
+ panic("element key for list must be non-negative integer")
+ }
+
+ eltys := val.Type().TupleElementTypes()
+
+ if !val.IsKnown() {
+ return UnknownVal(eltys[index])
+ }
+
+ return Value{
+ ty: eltys[index],
+ v: val.v.([]any)[index],
+ }
+ default:
+ panic("not a list, map, or tuple type")
+ }
+}
+
+// HasIndex returns True if the receiver (which must be supported for Index)
+// has an element with the given index key, or False if it does not.
+//
+// The result will be UnknownVal(Bool) if either the collection or the
+// key value are unknown.
+//
+// This method will panic if the receiver is not indexable, but does not
+// impose any panic-causing type constraints on the key.
+func (val Value) HasIndex(key Value) Value {
+ if val.IsMarked() || key.IsMarked() {
+ val, valMarks := val.Unmark()
+ key, keyMarks := key.Unmark()
+ return val.HasIndex(key).WithMarks(valMarks, keyMarks)
+ }
+
+ if val.ty == DynamicPseudoType {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ switch {
+ case val.Type().IsListType():
+ if key.Type() == DynamicPseudoType {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ if key.Type() != Number {
+ return False
+ }
+ if !key.IsKnown() {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+ if !val.IsKnown() {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ index, accuracy := key.v.(*big.Float).Int64()
+ if accuracy != big.Exact || index < 0 {
+ return False
+ }
+
+ return BoolVal(int(index) < len(val.v.([]any)) && index >= 0)
+ case val.Type().IsMapType():
+ if key.Type() == DynamicPseudoType {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ if key.Type() != String {
+ return False
+ }
+ if !key.IsKnown() {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+ if !val.IsKnown() {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ keyStr := key.v.(string)
+ _, exists := val.v.(map[string]any)[keyStr]
+
+ return BoolVal(exists)
+ case val.Type().IsTupleType():
+ if key.Type() == DynamicPseudoType {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ if key.Type() != Number {
+ return False
+ }
+ if !key.IsKnown() {
+ return UnknownVal(Bool).RefineNotNull()
+ }
+
+ index, accuracy := key.v.(*big.Float).Int64()
+ if accuracy != big.Exact || index < 0 {
+ return False
+ }
+
+ length := val.Type().Length()
+ return BoolVal(int(index) < length && index >= 0)
+ default:
+ panic("not a list, map, or tuple type")
+ }
+}
+
+// HasElement returns True if the receiver (which must be of a set type)
+// has the given value as an element, or False if it does not.
+//
+// The result will be UnknownVal(Bool) if either the set or the
+// given value are unknown.
+//
+// This method will panic if the receiver is not a set, or if it is a null set.
+func (val Value) HasElement(elem Value) Value {
+ if val.IsMarked() || elem.IsMarked() {
+ val, valMarks := val.Unmark()
+ elem, elemMarks := elem.Unmark()
+ return val.HasElement(elem).WithMarks(valMarks, elemMarks)
+ }
+
+ ty := val.Type()
+ unknownResult := UnknownVal(Bool).RefineNotNull()
+
+ if val.IsNull() {
+ panic("cannot HasElement on null value")
+ }
+ if !val.IsKnown() {
+ return unknownResult
+ }
+ if elem.Type() != DynamicPseudoType && val.Type().IsSetType() && val.Type().ElementType() != DynamicPseudoType {
+ // If we know the type of the given element and the element type of
+ // the set then they must match for the element to be present, because
+ // a set can't contain elements of any other type than its element type.
+ if !elem.Type().Equals(val.ty.ElementType()) {
+ return False
+ }
+ }
+ if !ty.IsSetType() {
+ panic("not a set type")
+ }
+ if !elem.IsKnown() {
+ return unknownResult
+ }
+ noMatchResult := False
+ if !val.IsWhollyKnown() {
+ // If the set has any unknown elements then a failure to find a
+ // known-value elem in it means that we don't know whether the
+ // element is present, rather than that it definitely isn't.
+ noMatchResult = unknownResult
+ }
+ if !ty.ElementType().Equals(elem.Type()) {
+ // A set can only contain an element of its own element type
+ return False
+ }
+
+ s := val.v.(set.Set[any])
+ if !s.Has(elem.v) {
+ return noMatchResult
+ }
+ return True
+}
+
+// Length returns the length of the receiver, which must be a collection type
+// or tuple type, as a number value. If the receiver is not a compatible type
+// then this method will panic.
+//
+// If the receiver is unknown then the result is also unknown.
+//
+// If the receiver is null then this function will panic.
+//
+// Note that Length is not supported for strings. To determine the length
+// of a string, use the Length function in funcs/stdlib.
+func (val Value) Length() Value {
+ if val.IsMarked() {
+ val, valMarks := val.Unmark()
+ return val.Length().WithMarks(valMarks)
+ }
+
+ if val.Type().IsTupleType() {
+ // For tuples, we can return the length even if the value is not known.
+ return NumberIntVal(int64(val.Type().Length()))
+ }
+
+ if !val.IsKnown() {
+ // If the whole collection isn't known then the length isn't known
+ // either, but we can still put some bounds on the range of the result.
+ rng := val.Range()
+ return UnknownVal(Number).RefineWith(valueRefineLengthResult(rng))
+ }
+ if val.Type().IsSetType() {
+ // The Length rules are a little different for sets because if any
+ // unknown values are present then the values they are standing in for
+ // may or may not be equal to other elements in the set, and thus they
+ // may or may not coalesce with other elements and produce fewer
+ // items in the resulting set.
+ storeLength := int64(val.v.(set.Set[any]).Length())
+ if storeLength == 1 || val.IsWhollyKnown() {
+ // If our set is wholly known then we know its length.
+ //
+ // We also know the length if the physical store has only one
+ // element, even if that element is unknown, because there's
+ // nothing else in the set for it to coalesce with and a single
+ // unknown value cannot represent more than one known value.
+ return NumberIntVal(storeLength)
+ }
+ // Otherwise, we cannot predict the length exactly but we can at
+ // least constrain both bounds of its range, because value coalescing
+ // can only ever reduce the number of elements in the set.
+ return UnknownVal(Number).Refine().NotNull().NumberRangeInclusive(NumberIntVal(1), NumberIntVal(storeLength)).NewValue()
+ }
+
+ return NumberIntVal(int64(val.LengthInt()))
+}
+
+func valueRefineLengthResult(collRng ValueRange) func(*RefinementBuilder) *RefinementBuilder {
+ return func(b *RefinementBuilder) *RefinementBuilder {
+ return b.
+ NotNull().
+ NumberRangeInclusive(
+ NumberIntVal(int64(collRng.LengthLowerBound())),
+ NumberIntVal(int64(collRng.LengthUpperBound())),
+ )
+ }
+}
+
+// LengthInt is like Length except it returns an int. It has the same behavior
+// as Length except that it will panic if the receiver is unknown.
+//
+// This is an integration method provided for the convenience of code bridging
+// into Go's type system.
+//
+// For backward compatibility with an earlier implementation error, LengthInt's
+// result can disagree with Length's result for any set containing unknown
+// values. Length can potentially indicate the set's length is unknown in that
+// case, whereas LengthInt will return the maximum possible length as if the
+// unknown values were each a placeholder for a value not equal to any other
+// value in the set.
+func (val Value) LengthInt() int {
+ val.assertUnmarked()
+ if val.Type().IsTupleType() {
+ // For tuples, we can return the length even if the value is not known.
+ return val.Type().Length()
+ }
+ if val.Type().IsObjectType() {
+ // For objects, the length is the number of attributes associated with the type.
+ return len(val.Type().AttributeTypes())
+ }
+ if !val.IsKnown() {
+ panic("value is not known")
+ }
+ if val.IsNull() {
+ panic("value is null")
+ }
+
+ switch {
+
+ case val.ty.IsListType():
+ return len(val.v.([]any))
+
+ case val.ty.IsSetType():
+ // NOTE: This is technically not correct in cases where the set
+ // contains unknown values, because in that case we can't know how
+ // many known values those unknown values are standing in for -- they
+ // might coalesce with other values once known.
+ //
+ // However, this incorrect behavior is preserved for backward
+ // compatibility with callers that were relying on LengthInt rather
+ // than calling Length. Instead of panicking when a set contains an
+ // unknown value, LengthInt returns the largest possible length.
+ return val.v.(set.Set[any]).Length()
+
+ case val.ty.IsMapType():
+ return len(val.v.(map[string]any))
+
+ default:
+ panic("value is not a collection")
+ }
+}
+
+// Elements returns an iterable sequence over the elements of the reciever,
+// which must be a collection type, a tuple type, or an object type.
+// If called on a value of any other type, this method will panic.
+// The value must also be known, non-null, and unmarked, or this method will
+// panic.
+//
+// Use [Value.CanIterateElements] to check dynamically if a particular value
+// can support this method without panicking.
+//
+// The two values in each iteration represent a key and a value respectively.
+//
+// If the receiver is of list type then the key is guaranteed to be of type
+// [Number] and the values are of the list's element type.
+//
+// The the reciever is of a map type then the key is guaranteed to be of type
+// [String] and the values are of the map's element type. Elements are
+// produced in ascending lexicographical order by key.
+//
+// If the receiver is of a set type then each element is returned as both the
+// key and the value, because set member values are their own identity.
+//
+// If the reciever is of a tuple type then the key is guaranteed to be of type
+// [Number] and the and the value types match the corresponding element types.
+//
+// If the reciever is of an object type then the key is guaranteed to be of
+// type [String] and the value types match the corresponding attribute types.
+func (val Value) Elements() iter.Seq2[Value, Value] {
+ return func(yield func(Value, Value) bool) {
+ for it := val.ElementIterator(); it.Next(); {
+ if !yield(it.Element()) {
+ break
+ }
+ }
+ }
+}
+
+// ElementIterator returns an ElementIterator for iterating the elements
+// of the receiver, which must be a collection type, a tuple type, or an object
+// type. If called on a method of any other type, this method will panic.
+// The value must be known and non-null, or this method will panic.
+//
+// The element iterator produces keys and values matching what's described
+// for [Value.Elements]. New code should prefer to use [Value.Elements].
+func (val Value) ElementIterator() ElementIterator {
+ val.assertUnmarked()
+ if !val.IsKnown() {
+ panic("can't use ElementIterator on unknown value")
+ }
+ if val.IsNull() {
+ panic("can't use ElementIterator on null value")
+ }
+ return elementIterator(val)
+}
+
+// CanIterateElements returns true if the receiver can support the
+// Elements, ElementIterator, and ForEachElement methods without panic.
+func (val Value) CanIterateElements() bool {
+ return canElementIterator(val)
+}
+
+// ForEachElement executes a given callback function for each element of
+// the receiver, which must be a collection type or tuple type, or this method
+// will panic.
+//
+// ForEachElement uses ElementIterator internally, and so the values passed
+// to the callback are as described for [Value.Elements]. New code should
+// prefer to use [Value.Elements] in a normal for loop instead of using this
+// method.
+//
+// Returns true if the iteration exited early due to the callback function
+// returning true, or false if the loop ran to completion.
+//
+// ForEachElement is an integration method, so it cannot handle Unknown
+// values. This method will panic if the receiver is Unknown.
+func (val Value) ForEachElement(cb ElementCallback) bool {
+ val.assertUnmarked()
+ it := val.ElementIterator()
+ for it.Next() {
+ key, val := it.Element()
+ stop := cb(key, val)
+ if stop {
+ return true
+ }
+ }
+ return false
+}
+
+// Not returns the logical inverse of the receiver, which must be of type
+// Bool or this method will panic.
+func (val Value) Not() Value {
+ if val.IsMarked() {
+ val, valMarks := val.Unmark()
+ return val.Not().WithMarks(valMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil {
+ shortCircuit = forceShortCircuitType(shortCircuit, Bool)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ return BoolVal(!val.v.(bool))
+}
+
+// And returns the result of logical AND with the receiver and the other given
+// value, which must both be of type Bool or this method will panic.
+func (val Value) And(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.And(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
+ // If either value is known to be exactly False then it doesn't
+ // matter what the other value is, because the final result must
+ // either be False or an error.
+ if val == False || other == False {
+ return False
+ }
+ shortCircuit = forceShortCircuitType(shortCircuit, Bool)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ return BoolVal(val.v.(bool) && other.v.(bool))
+}
+
+// Or returns the result of logical OR with the receiver and the other given
+// value, which must both be of type Bool or this method will panic.
+func (val Value) Or(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.Or(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
+ // If either value is known to be exactly True then it doesn't
+ // matter what the other value is, because the final result must
+ // either be True or an error.
+ if val == True || other == True {
+ return True
+ }
+ shortCircuit = forceShortCircuitType(shortCircuit, Bool)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ return BoolVal(val.v.(bool) || other.v.(bool))
+}
+
+// LessThan returns True if the receiver is less than the other given value,
+// which must both be numbers or this method will panic.
+func (val Value) LessThan(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.LessThan(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
+ // We might be able to return a known answer even with unknown inputs.
+ // FIXME: This is more conservative than it needs to be, because it
+ // treats all bounds as exclusive bounds.
+ valRng := val.Range()
+ otherRng := other.Range()
+ if valRng.TypeConstraint() == Number && other.Range().TypeConstraint() == Number {
+ valMax, _ := valRng.NumberUpperBound()
+ otherMin, _ := otherRng.NumberLowerBound()
+ if valMax.IsKnown() && otherMin.IsKnown() {
+ if r := valMax.LessThan(otherMin); r.True() {
+ return True
+ }
+ }
+ valMin, _ := valRng.NumberLowerBound()
+ otherMax, _ := otherRng.NumberUpperBound()
+ if valMin.IsKnown() && otherMax.IsKnown() {
+ if r := valMin.GreaterThan(otherMax); r.True() {
+ return False
+ }
+ }
+ }
+
+ shortCircuit = forceShortCircuitType(shortCircuit, Bool)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0)
+}
+
+// GreaterThan returns True if the receiver is greater than the other given
+// value, which must both be numbers or this method will panic.
+func (val Value) GreaterThan(other Value) Value {
+ if val.IsMarked() || other.IsMarked() {
+ val, valMarks := val.Unmark()
+ other, otherMarks := other.Unmark()
+ return val.GreaterThan(other).WithMarks(valMarks, otherMarks)
+ }
+
+ if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
+ // We might be able to return a known answer even with unknown inputs.
+ // FIXME: This is more conservative than it needs to be, because it
+ // treats all bounds as exclusive bounds.
+ valRng := val.Range()
+ otherRng := other.Range()
+ if valRng.TypeConstraint() == Number && other.Range().TypeConstraint() == Number {
+ valMin, _ := valRng.NumberLowerBound()
+ otherMax, _ := otherRng.NumberUpperBound()
+ if valMin.IsKnown() && otherMax.IsKnown() {
+ if r := valMin.GreaterThan(otherMax); r.True() {
+ return True
+ }
+ }
+ valMax, _ := valRng.NumberUpperBound()
+ otherMin, _ := otherRng.NumberLowerBound()
+ if valMax.IsKnown() && otherMin.IsKnown() {
+ if r := valMax.LessThan(otherMin); r.True() {
+ return False
+ }
+ }
+ }
+
+ shortCircuit = forceShortCircuitType(shortCircuit, Bool)
+ return (*shortCircuit).RefineNotNull()
+ }
+
+ return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0)
+}
+
+// LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or.
+func (val Value) LessThanOrEqualTo(other Value) Value {
+ return val.LessThan(other).Or(val.Equals(other))
+}
+
+// GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or.
+func (val Value) GreaterThanOrEqualTo(other Value) Value {
+ return val.GreaterThan(other).Or(val.Equals(other))
+}
+
+// AsString returns the native string from a non-null, non-unknown cty.String
+// value, or panics if called on any other value.
+func (val Value) AsString() string {
+ val.assertUnmarked()
+ if val.ty != String {
+ panic("not a string")
+ }
+ if val.IsNull() {
+ panic("value is null")
+ }
+ if !val.IsKnown() {
+ panic("value is unknown")
+ }
+
+ return val.v.(string)
+}
+
+// AsBigFloat returns a big.Float representation of a non-null, non-unknown
+// cty.Number value, or panics if called on any other value.
+//
+// For more convenient conversions to other native numeric types, use the
+// "gocty" package.
+func (val Value) AsBigFloat() *big.Float {
+ val.assertUnmarked()
+ if val.ty != Number {
+ panic("not a number")
+ }
+ if val.IsNull() {
+ panic("value is null")
+ }
+ if !val.IsKnown() {
+ panic("value is unknown")
+ }
+
+ // Copy the float so that callers can't mutate our internal state
+ return new(big.Float).Copy(val.v.(*big.Float))
+}
+
+// AsValueSlice returns a []cty.Value representation of a non-null, non-unknown
+// value of any type that CanIterateElements, or panics if called on
+// any other value.
+//
+// For more convenient conversions to slices of more specific types, use
+// the "gocty" package.
+func (val Value) AsValueSlice() []Value {
+ val.assertUnmarked()
+ l := val.LengthInt()
+ if l == 0 {
+ return nil
+ }
+
+ ret := make([]Value, 0, l)
+ for it := val.ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ ret = append(ret, v)
+ }
+ return ret
+}
+
+// AsValueMap returns a map[string]cty.Value representation of a non-null,
+// non-unknown value of any type that CanIterateElements, or panics if called
+// on any other value.
+//
+// For more convenient conversions to maps of more specific types, use
+// the "gocty" package.
+func (val Value) AsValueMap() map[string]Value {
+ val.assertUnmarked()
+ l := val.LengthInt()
+ if l == 0 {
+ return nil
+ }
+
+ ret := make(map[string]Value, l)
+ for it := val.ElementIterator(); it.Next(); {
+ k, v := it.Element()
+ ret[k.AsString()] = v
+ }
+ return ret
+}
+
+// AsValueSet returns a ValueSet representation of a non-null,
+// non-unknown value of any collection type, or panics if called
+// on any other value.
+//
+// Unlike AsValueSlice and AsValueMap, this method requires specifically a
+// collection type (list, set or map) and does not allow structural types
+// (tuple or object), because the ValueSet type requires homogenous
+// element types.
+//
+// The returned ValueSet can store only values of the receiver's element type.
+func (val Value) AsValueSet() ValueSet {
+ val.assertUnmarked()
+ if !val.Type().IsCollectionType() {
+ panic("not a collection type")
+ }
+
+ // We don't give the caller our own set.Set (assuming we're a cty.Set value)
+ // because then the caller could mutate our internals, which is forbidden.
+ // Instead, we will construct a new set and append our elements into it.
+ ret := NewValueSet(val.Type().ElementType())
+ for it := val.ElementIterator(); it.Next(); {
+ _, v := it.Element()
+ ret.Add(v)
+ }
+ return ret
+}
+
+// EncapsulatedValue returns the native value encapsulated in a non-null,
+// non-unknown capsule-typed value, or panics if called on any other value.
+//
+// The result is the same pointer that was passed to CapsuleVal to create
+// the value. Since cty considers values to be immutable, it is strongly
+// recommended to treat the encapsulated value itself as immutable too.
+func (val Value) EncapsulatedValue() any {
+ val.assertUnmarked()
+ if !val.Type().IsCapsuleType() {
+ panic("not a capsule-typed value")
+ }
+
+ return val.v
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_range.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_range.go
new file mode 100644
index 00000000000..d7d15353936
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/value_range.go
@@ -0,0 +1,412 @@
+package cty
+
+import (
+ "fmt"
+ "math"
+ "strings"
+)
+
+// Range returns an object that offers partial information about the range
+// of the receiver.
+//
+// This is most relevant for unknown values, because it gives access to any
+// optional additional constraints on the final value (specified by the source
+// of the value using "refinements") beyond what we can assume from the value's
+// type.
+//
+// Calling Range for a known value is a little strange, but it's supported by
+// returning a [ValueRange] object that describes the exact value as closely
+// as possible. Typically a caller should work directly with the exact value
+// in that case, but some purposes might only need the level of detail
+// offered by ranges and so can share code between both known and unknown
+// values.
+func (v Value) Range() ValueRange {
+ if v.IsMarked() {
+ panic("Value.Range on marked value; must be unmarked first")
+ }
+
+ // For an unknown value we just use its own refinements.
+ if unk, isUnk := v.v.(*unknownType); isUnk {
+ refinement := unk.refinement
+ if refinement == nil {
+ // We'll generate an unconstrained refinement, just to
+ // simplify the code in ValueRange methods which can
+ // therefore assume that there's always a refinement.
+ refinement = &refinementNullable{isNull: tristateUnknown}
+ }
+ return ValueRange{v.Type(), refinement}
+ }
+
+ if v.IsNull() {
+ // If we know a value is null then we'll just report that,
+ // since no other refinements make sense for a definitely-null value.
+ return ValueRange{
+ v.Type(),
+ &refinementNullable{isNull: tristateTrue},
+ }
+ }
+
+ // For a known value we construct synthetic refinements that match
+ // the value, just as a convenience for callers that want to share
+ // codepaths between both known and unknown values.
+ ty := v.Type()
+ var synth unknownValRefinement
+ switch {
+ case ty == String:
+ synth = &refinementString{
+ prefix: v.AsString(),
+ }
+ case ty == Number:
+ synth = &refinementNumber{
+ min: v,
+ max: v,
+ minInc: true,
+ maxInc: true,
+ }
+ case ty.IsCollectionType():
+ if lenVal := v.Length(); lenVal.IsKnown() {
+ l, _ := lenVal.AsBigFloat().Int64()
+ synth = &refinementCollection{
+ minLen: int(l),
+ maxLen: int(l),
+ }
+ } else {
+ synth = &refinementCollection{
+ minLen: 0,
+ maxLen: math.MaxInt,
+ }
+ }
+
+ default:
+ // If we don't have anything else to say then we can at least
+ // guarantee that the value isn't null.
+ synth = &refinementNullable{}
+ }
+
+ // If we get down here then the value is definitely not null
+ synth.setNull(tristateFalse)
+
+ return ValueRange{ty, synth}
+}
+
+// ValueRange offers partial information about the range of a value.
+//
+// This is primarily interesting for unknown values, because it provides access
+// to any additional known constraints (specified using "refinements") on the
+// range of the value beyond what is represented by the value's type.
+type ValueRange struct {
+ ty Type
+ raw unknownValRefinement
+}
+
+// TypeConstraint returns a type constraint describing the value's type as
+// precisely as possible with the available information.
+func (r ValueRange) TypeConstraint() Type {
+ return r.ty
+}
+
+// CouldBeNull returns true unless the value being described is definitely
+// known to represent a non-null value.
+func (r ValueRange) CouldBeNull() bool {
+ if r.raw == nil {
+ // A totally-unconstrained unknown value could be null
+ return true
+ }
+ return r.raw.null() != tristateFalse
+}
+
+// DefinitelyNotNull returns true if there are no null values in the range.
+func (r ValueRange) DefinitelyNotNull() bool {
+ if r.raw == nil {
+ // A totally-unconstrained unknown value could be null
+ return false
+ }
+ return r.raw.null() == tristateFalse
+}
+
+// NumberLowerBound returns information about the lower bound of the range of
+// a number value, or panics if the value is definitely not a number.
+//
+// If the value is nullable then the result represents the range of the number
+// only if it turns out not to be null.
+//
+// The resulting value might itself be an unknown number if there is no
+// known lower bound. In that case the "inclusive" flag is meaningless.
+func (r ValueRange) NumberLowerBound() (min Value, inclusive bool) {
+ if r.ty == DynamicPseudoType {
+ // We don't even know if this is a number yet.
+ return UnknownVal(Number), false
+ }
+ if r.ty != Number {
+ panic(fmt.Sprintf("NumberLowerBound for %#v", r.ty))
+ }
+ if rfn, ok := r.raw.(*refinementNumber); ok && rfn.min != NilVal {
+ if !rfn.min.IsKnown() {
+ return NegativeInfinity, true
+ }
+ return rfn.min, rfn.minInc
+ }
+ return NegativeInfinity, false
+}
+
+// NumberUpperBound returns information about the upper bound of the range of
+// a number value, or panics if the value is definitely not a number.
+//
+// If the value is nullable then the result represents the range of the number
+// only if it turns out not to be null.
+//
+// The resulting value might itself be an unknown number if there is no
+// known upper bound. In that case the "inclusive" flag is meaningless.
+func (r ValueRange) NumberUpperBound() (max Value, inclusive bool) {
+ if r.ty == DynamicPseudoType {
+ // We don't even know if this is a number yet.
+ return UnknownVal(Number), false
+ }
+ if r.ty != Number {
+ panic(fmt.Sprintf("NumberUpperBound for %#v", r.ty))
+ }
+ if rfn, ok := r.raw.(*refinementNumber); ok && rfn.max != NilVal {
+ if !rfn.max.IsKnown() {
+ return PositiveInfinity, true
+ }
+ return rfn.max, rfn.maxInc
+ }
+ return PositiveInfinity, false
+}
+
+// StringPrefix returns a string that is guaranteed to be the prefix of
+// the string value being described, or panics if the value is definitely not
+// a string.
+//
+// If the value is nullable then the result represents the prefix of the string
+// only if it turns out to not be null.
+//
+// If the resulting value is zero-length then the value could potentially be
+// a string but it has no known prefix.
+//
+// cty.String values always contain normalized UTF-8 sequences; the result is
+// also guaranteed to be a normalized UTF-8 sequence so the result also
+// represents the exact bytes of the string value's prefix.
+func (r ValueRange) StringPrefix() string {
+ if r.ty == DynamicPseudoType {
+ // We don't even know if this is a string yet.
+ return ""
+ }
+ if r.ty != String {
+ panic(fmt.Sprintf("StringPrefix for %#v", r.ty))
+ }
+ if rfn, ok := r.raw.(*refinementString); ok {
+ return rfn.prefix
+ }
+ return ""
+}
+
+// LengthLowerBound returns information about the lower bound of the length of
+// a collection-typed value, or panics if the value is definitely not a
+// collection.
+//
+// If the value is nullable then the result represents the range of the length
+// only if the value turns out not to be null.
+func (r ValueRange) LengthLowerBound() int {
+ if r.ty == DynamicPseudoType {
+ // We don't even know if this is a collection yet.
+ return 0
+ }
+ if !r.ty.IsCollectionType() {
+ panic(fmt.Sprintf("LengthLowerBound for %#v", r.ty))
+ }
+ if rfn, ok := r.raw.(*refinementCollection); ok {
+ return rfn.minLen
+ }
+ return 0
+}
+
+// LengthUpperBound returns information about the upper bound of the length of
+// a collection-typed value, or panics if the value is definitely not a
+// collection.
+//
+// If the value is nullable then the result represents the range of the length
+// only if the value turns out not to be null.
+//
+// The resulting value might itself be an unknown number if there is no
+// known upper bound. In that case the "inclusive" flag is meaningless.
+func (r ValueRange) LengthUpperBound() int {
+ if r.ty == DynamicPseudoType {
+ // We don't even know if this is a collection yet.
+ return math.MaxInt
+ }
+ if !r.ty.IsCollectionType() {
+ panic(fmt.Sprintf("LengthUpperBound for %#v", r.ty))
+ }
+ if rfn, ok := r.raw.(*refinementCollection); ok {
+ return rfn.maxLen
+ }
+ return math.MaxInt
+}
+
+// Includes determines whether the given value is in the receiving range.
+//
+// It can return only three possible values:
+// - [cty.True] if the range definitely includes the value
+// - [cty.False] if the range definitely does not include the value
+// - An unknown value of [cty.Bool] if there isn't enough information to decide.
+//
+// This function is not fully comprehensive: it may return an unknown value
+// in some cases where a definitive value could be computed in principle, and
+// those same situations may begin returning known values in later releases as
+// the rules are refined to be more complete. Currently the rules focus mainly
+// on answering [cty.False], because disproving membership tends to be more
+// useful than proving membership.
+func (r ValueRange) Includes(v Value) Value {
+ unknownResult := UnknownVal(Bool).RefineNotNull()
+
+ if r.raw.null() == tristateTrue {
+ if v.IsNull() {
+ return True
+ } else {
+ return False
+ }
+ }
+ if r.raw.null() == tristateFalse {
+ if v.IsNull() {
+ return False
+ }
+ // A definitely-not-null value could potentially match
+ // but we won't know until we do some more checks below.
+ }
+ // If our range includes both null and non-null values and the value is
+ // null then it's definitely in range.
+ if v.IsNull() {
+ return True
+ }
+ if len(v.Type().TestConformance(r.TypeConstraint())) != 0 {
+ // If the value doesn't conform to the type constraint then it's
+ // definitely not in the range.
+ return False
+ }
+ if v.Type() == DynamicPseudoType {
+ // If it's an unknown value of an unknown type then there's no
+ // further tests we can make.
+ return unknownResult
+ }
+
+ switch r.raw.(type) {
+ case *refinementString:
+ if v.IsKnown() {
+ prefix := r.StringPrefix()
+ got := v.AsString()
+
+ if !strings.HasPrefix(got, prefix) {
+ return False
+ }
+ }
+ case *refinementCollection:
+ lenVal := v.Length()
+ minLen := NumberIntVal(int64(r.LengthLowerBound()))
+ maxLen := NumberIntVal(int64(r.LengthUpperBound()))
+ if minOk := lenVal.GreaterThanOrEqualTo(minLen); minOk.IsKnown() && minOk.False() {
+ return False
+ }
+ if maxOk := lenVal.LessThanOrEqualTo(maxLen); maxOk.IsKnown() && maxOk.False() {
+ return False
+ }
+ case *refinementNumber:
+ minVal, minInc := r.NumberLowerBound()
+ maxVal, maxInc := r.NumberUpperBound()
+ var minOk, maxOk Value
+ if minInc {
+ minOk = v.GreaterThanOrEqualTo(minVal)
+ } else {
+ minOk = v.GreaterThan(minVal)
+ }
+ if maxInc {
+ maxOk = v.LessThanOrEqualTo(maxVal)
+ } else {
+ maxOk = v.LessThan(maxVal)
+ }
+ if minOk.IsKnown() && minOk.False() {
+ return False
+ }
+ if maxOk.IsKnown() && maxOk.False() {
+ return False
+ }
+ }
+
+ // If we fall out here then we don't have enough information to decide.
+ return unknownResult
+}
+
+// numericRangeArithmetic is a helper we use to calculate derived numeric ranges
+// for arithmetic on refined numeric values.
+//
+// op must be a monotone operation. numericRangeArithmetic adapts that operation
+// into the equivalent interval arithmetic operation.
+//
+// The result is a superset of the range of the given operation against the
+// given input ranges, if it's possible to calculate that without encountering
+// an invalid operation. Currently the result is inexact due to ignoring
+// the inclusiveness of the input bounds and just always returning inclusive
+// bounds.
+func numericRangeArithmetic(op func(a, b Value) Value, a, b ValueRange) func(*RefinementBuilder) *RefinementBuilder {
+ wrapOp := func(a, b Value) (ret Value) {
+ // Our functions have various panicking edge cases involving incompatible
+ // uses of infinities. To keep things simple here we'll catch those
+ // and just return an unconstrained number.
+ defer func() {
+ if v := recover(); v != nil {
+ ret = UnknownVal(Number)
+ }
+ }()
+ return op(a, b)
+ }
+
+ return func(builder *RefinementBuilder) *RefinementBuilder {
+ aMin, _ := a.NumberLowerBound()
+ aMax, _ := a.NumberUpperBound()
+ bMin, _ := b.NumberLowerBound()
+ bMax, _ := b.NumberUpperBound()
+
+ v1 := wrapOp(aMin, bMin)
+ v2 := wrapOp(aMin, bMax)
+ v3 := wrapOp(aMax, bMin)
+ v4 := wrapOp(aMax, bMax)
+
+ newMin := mostNumberValue(Value.LessThan, v1, v2, v3, v4)
+ newMax := mostNumberValue(Value.GreaterThan, v1, v2, v3, v4)
+
+ if isInf := newMin.Equals(NegativeInfinity); isInf.IsKnown() && isInf.False() {
+ builder = builder.NumberRangeLowerBound(newMin, true)
+ }
+ if isInf := newMax.Equals(PositiveInfinity); isInf.IsKnown() && isInf.False() {
+ builder = builder.NumberRangeUpperBound(newMax, true)
+ }
+ return builder
+ }
+}
+
+func mostNumberValue(op func(i, j Value) Value, v1 Value, vN ...Value) Value {
+ r := v1
+ for _, v := range vN {
+ more := op(v, r)
+ if !more.IsKnown() {
+ return UnknownVal(Number)
+ }
+ if more.True() {
+ r = v
+ }
+ }
+ return r
+}
+
+// definitelyNotNull is a convenient helper for the common situation of checking
+// whether a value could possibly be null.
+//
+// Returns true if the given value is either a known value that isn't null
+// or an unknown value that has been refined to exclude null values from its
+// range.
+func definitelyNotNull(v Value) bool {
+ if v.IsKnown() {
+ return !v.IsNull()
+ }
+ return v.Range().DefinitelyNotNull()
+}
diff --git a/hack/tools/vendor/github.com/zclconf/go-cty/cty/walk.go b/hack/tools/vendor/github.com/zclconf/go-cty/cty/walk.go
new file mode 100644
index 00000000000..e7025e487aa
--- /dev/null
+++ b/hack/tools/vendor/github.com/zclconf/go-cty/cty/walk.go
@@ -0,0 +1,266 @@
+package cty
+
+import (
+ "io"
+ "iter"
+)
+
+// Walk visits all of the values in a possibly-complex structure, calling
+// a given function for each value.
+//
+// For example, given a list of strings the callback would first be called
+// with the whole list and then called once for each element of the list.
+//
+// New callers may prefer to use [DeepValues] instead, because that returns
+// a result usable with a normal for loop.
+//
+// The callback function may prevent recursive visits to child values by
+// returning false. The callback function my halt the walk altogether by
+// returning a non-nil error. If the returned error is about the element
+// currently being visited, it is recommended to use the provided path
+// value to produce a PathError describing that context.
+//
+// The path passed to the given function may not be used after that function
+// returns, since its backing array is re-used for other calls.
+func Walk(val Value, cb func(Path, Value) (bool, error)) error {
+ var path Path
+ return walk(path, val, cb)
+}
+
+// DeepValues returns an iterable sequence containing at least the given
+// value but also, if it is of a collection or structural type, the other values
+// nested within it recursively.
+//
+// The [Path] values in different elements of the sequence may share a backing
+// array to reduce garbage generated during iteration, so if a caller wishes to
+// preserve a path outside of a single loop iteration the caller must copy it to
+// a separate Path value with its own separate backing array, such as by calling
+// [Path.Copy].
+func DeepValues(val Value) iter.Seq2[Path, Value] {
+ return func(yield func(Path, Value) bool) {
+ Walk(val, func(p Path, v Value) (bool, error) {
+ if !yield(p, v) {
+ return false, io.EOF // arbitrary error just to get Walk to stop
+ }
+ return true, nil
+ })
+ }
+}
+
+func walk(path Path, val Value, cb func(Path, Value) (bool, error)) error {
+ deeper, err := cb(path, val)
+ if err != nil {
+ return err
+ }
+ if !deeper {
+ return nil
+ }
+
+ if val.IsNull() || !val.IsKnown() {
+ // Can't recurse into null or unknown values, regardless of type
+ return nil
+ }
+
+ // The callback already got a chance to see the mark in our
+ // call above, so can safely strip it off here in order to
+ // visit the child elements, which might still have their own marks.
+ rawVal, _ := val.Unmark()
+
+ ty := val.Type()
+ switch {
+ case ty.IsObjectType():
+ for it := rawVal.ElementIterator(); it.Next(); {
+ nameVal, av := it.Element()
+ path := append(path, GetAttrStep{
+ Name: nameVal.AsString(),
+ })
+ err := walk(path, av, cb)
+ if err != nil {
+ return err
+ }
+ }
+ case rawVal.CanIterateElements():
+ for it := rawVal.ElementIterator(); it.Next(); {
+ kv, ev := it.Element()
+ path := append(path, IndexStep{
+ Key: kv,
+ })
+ err := walk(path, ev, cb)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// Transformer is the interface used to optionally transform values in a
+// possibly-complex structure. The Enter method is called before traversing
+// through a given path, and the Exit method is called when traversal of a
+// path is complete.
+//
+// Use Enter when you want to transform a complex value before traversal
+// (preorder), and Exit when you want to transform a value after traversal
+// (postorder).
+//
+// The path passed to the given function may not be used after that function
+// returns, since its backing array is re-used for other calls.
+type Transformer interface {
+ Enter(Path, Value) (Value, error)
+ Exit(Path, Value) (Value, error)
+}
+
+type postorderTransformer struct {
+ callback func(Path, Value) (Value, error)
+}
+
+func (t *postorderTransformer) Enter(p Path, v Value) (Value, error) {
+ return v, nil
+}
+
+func (t *postorderTransformer) Exit(p Path, v Value) (Value, error) {
+ return t.callback(p, v)
+}
+
+// Transform visits all of the values in a possibly-complex structure,
+// calling a given function for each value which has an opportunity to
+// replace that value.
+//
+// Unlike Walk, Transform visits child nodes first, so for a list of strings
+// it would first visit the strings and then the _new_ list constructed
+// from the transformed values of the list items.
+//
+// This is useful for creating the effect of being able to make deep mutations
+// to a value even though values are immutable. However, it's the responsibility
+// of the given function to preserve expected invariants, such as homogenity of
+// element types in collections; this function can panic if such invariants
+// are violated, just as if new values were constructed directly using the
+// value constructor functions. An easy way to preserve invariants is to
+// ensure that the transform function never changes the value type.
+//
+// The callback function may halt the walk altogether by
+// returning a non-nil error. If the returned error is about the element
+// currently being visited, it is recommended to use the provided path
+// value to produce a PathError describing that context.
+//
+// The path passed to the given function may not be used after that function
+// returns, since its backing array is re-used for other calls.
+func Transform(val Value, cb func(Path, Value) (Value, error)) (Value, error) {
+ var path Path
+ return transform(path, val, &postorderTransformer{cb})
+}
+
+// TransformWithTransformer allows the caller to more closely control the
+// traversal used for transformation. See the documentation for Transformer for
+// more details.
+func TransformWithTransformer(val Value, t Transformer) (Value, error) {
+ var path Path
+ return transform(path, val, t)
+}
+
+func transform(path Path, val Value, t Transformer) (Value, error) {
+ val, err := t.Enter(path, val)
+ if err != nil {
+ return DynamicVal, err
+ }
+
+ ty := val.Type()
+ var newVal Value
+
+ // We need to peel off any marks here so that we can dig around
+ // inside any collection values. We'll reapply these to any
+ // new collections we construct, but the transformer's Exit
+ // method gets the final say on what to do with those.
+ rawVal, marks := val.Unmark()
+
+ switch {
+
+ case val.IsNull() || !val.IsKnown():
+ // Can't recurse into null or unknown values, regardless of type
+ newVal = val
+
+ case ty.IsListType() || ty.IsSetType() || ty.IsTupleType():
+ l := rawVal.LengthInt()
+ switch l {
+ case 0:
+ // No deep transform for an empty sequence
+ newVal = val
+ default:
+ elems := make([]Value, 0, l)
+ for it := rawVal.ElementIterator(); it.Next(); {
+ kv, ev := it.Element()
+ path := append(path, IndexStep{
+ Key: kv,
+ })
+ newEv, err := transform(path, ev, t)
+ if err != nil {
+ return DynamicVal, err
+ }
+ elems = append(elems, newEv)
+ }
+ switch {
+ case ty.IsListType():
+ newVal = ListVal(elems).WithMarks(marks)
+ case ty.IsSetType():
+ newVal = SetVal(elems).WithMarks(marks)
+ case ty.IsTupleType():
+ newVal = TupleVal(elems).WithMarks(marks)
+ default:
+ panic("unknown sequence type") // should never happen because of the case we are in
+ }
+ }
+
+ case ty.IsMapType():
+ l := rawVal.LengthInt()
+ switch l {
+ case 0:
+ // No deep transform for an empty map
+ newVal = val
+ default:
+ elems := make(map[string]Value)
+ for it := rawVal.ElementIterator(); it.Next(); {
+ kv, ev := it.Element()
+ path := append(path, IndexStep{
+ Key: kv,
+ })
+ newEv, err := transform(path, ev, t)
+ if err != nil {
+ return DynamicVal, err
+ }
+ elems[kv.AsString()] = newEv
+ }
+ newVal = MapVal(elems).WithMarks(marks)
+ }
+
+ case ty.IsObjectType():
+ switch {
+ case ty.Equals(EmptyObject):
+ // No deep transform for an empty object
+ newVal = val
+ default:
+ atys := ty.AttributeTypes()
+ newAVs := make(map[string]Value)
+ for name := range atys {
+ av := rawVal.GetAttr(name)
+ path := append(path, GetAttrStep{
+ Name: name,
+ })
+ newAV, err := transform(path, av, t)
+ if err != nil {
+ return DynamicVal, err
+ }
+ newAVs[name] = newAV
+ }
+ newVal = ObjectVal(newAVs).WithMarks(marks)
+ }
+
+ default:
+ newVal = val
+ }
+
+ newVal, err = t.Exit(path, newVal)
+ if err != nil {
+ return DynamicVal, err
+ }
+ return newVal, err
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/.golangci.yaml b/hack/tools/vendor/go-simpler.org/sloglint/.golangci.yaml
index cbac91508e7..526e368d468 100644
--- a/hack/tools/vendor/go-simpler.org/sloglint/.golangci.yaml
+++ b/hack/tools/vendor/go-simpler.org/sloglint/.golangci.yaml
@@ -1,10 +1,10 @@
-# https://golangci-lint.run/usage/configuration
+# https://golangci-lint.run/docs/configuration/file
version: "2"
linters:
- default: standard
enable:
- gocritic
+ - modernize
settings:
gocritic:
enable-all: true
@@ -16,3 +16,6 @@ formatters:
enable:
- gofumpt
- goimports
+ settings:
+ gofumpt:
+ extra-rules: true
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/.goreleaser.yaml b/hack/tools/vendor/go-simpler.org/sloglint/.goreleaser.yaml
new file mode 100644
index 00000000000..a8fa6bbfdc4
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/.goreleaser.yaml
@@ -0,0 +1,12 @@
+# https://goreleaser.com/customization/builds/go
+
+builds:
+ - main: ./cmd/{{.ProjectName}}
+ flags:
+ - -trimpath
+ ldflags:
+ - -s -w -X main.version={{.Version}}
+ env:
+ - CGO_ENABLED=0
+ targets:
+ - go_first_class # https://go.dev/wiki/PortingPolicy#first-class-ports
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/.goreleaser.yml b/hack/tools/vendor/go-simpler.org/sloglint/.goreleaser.yml
deleted file mode 100644
index d31ea11d390..00000000000
--- a/hack/tools/vendor/go-simpler.org/sloglint/.goreleaser.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-builds:
- - main: ./cmd/sloglint
- env:
- - CGO_ENABLED=0
- flags:
- - -trimpath
- ldflags:
- - -s -w -X main.version={{.Version}}
- targets:
- - darwin_amd64
- - darwin_arm64
- - linux_amd64
- - windows_amd64
-
-archives:
- - format_overrides:
- - goos: windows
- format: zip
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/Makefile b/hack/tools/vendor/go-simpler.org/sloglint/Makefile
index 6165b16f474..cf5eb9d10c0 100644
--- a/hack/tools/vendor/go-simpler.org/sloglint/Makefile
+++ b/hack/tools/vendor/go-simpler.org/sloglint/Makefile
@@ -1,28 +1,25 @@
.POSIX:
.SUFFIXES:
-all: test lint
+help:
+ @echo 'Available commands:'
+ @echo ' build Build the project'
+ @echo ' fmt Run formatters'
+ @echo ' lint Run linters'
+ @echo ' test Run tests'
+ @echo ' test/cover Run tests and open coverage report'
-test:
- go test -race -shuffle=on -cover ./...
+build:
+ @go build -o /dev/null ./...
-test/cover:
- go test -race -shuffle=on -coverprofile=coverage.out ./...
- go tool cover -html=coverage.out
+fmt:
+ @golangci-lint fmt
lint:
- golangci-lint run
-
-tidy:
- go mod tidy
+ @golangci-lint run --fix
-generate:
- go generate ./...
-
-# run `make pre-commit` once to install the hook.
-pre-commit: .git/hooks/pre-commit test lint tidy generate
- git diff --exit-code
+test:
+ @go test -race -shuffle=on -coverprofile=coverage.out ./...
-.git/hooks/pre-commit:
- echo "make pre-commit" > .git/hooks/pre-commit
- chmod +x .git/hooks/pre-commit
+test/cover: test
+ @go tool cover -html=coverage.out
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/README.md b/hack/tools/vendor/go-simpler.org/sloglint/README.md
index e75fd02155d..9653bd15453 100644
--- a/hack/tools/vendor/go-simpler.org/sloglint/README.md
+++ b/hack/tools/vendor/go-simpler.org/sloglint/README.md
@@ -1,205 +1,296 @@
# sloglint
-[](https://github.com/go-simpler/sloglint/actions/workflows/checks.yml)
-[](https://pkg.go.dev/go-simpler.org/sloglint)
-[](https://goreportcard.com/report/go-simpler.org/sloglint)
+[](https://github.com/go-simpler/sloglint/actions/workflows/checks.yaml)
+[](https://pkg.go.dev/go-simpler.org/sloglint)
[](https://codecov.io/gh/go-simpler/sloglint)
A Go linter that ensures consistent code style when using `log/slog`.
-## 📌 About
+## Install
-The `log/slog` API allows two different types of arguments: key-value pairs and attributes.
-While people may have different opinions about which one is better, most seem to agree on one thing: it should be consistent.
-With `sloglint` you can enforce various rules for `log/slog` based on your preferred code style.
-
-## 🚀 Features
-
-* Enforce not mixing key-value pairs and attributes (default)
-* Enforce using either key-value pairs only or attributes only (optional)
-* Enforce not using global loggers (optional)
-* Enforce using methods that accept a context (optional)
-* Enforce using static messages (optional)
-* Enforce message style (optional)
-* Enforce using constants instead of raw keys (optional)
-* Enforce key naming convention (optional)
-* Enforce not using specific keys (optional)
-* Enforce putting arguments on separate lines (optional)
-
-## 📦 Install
-
-`sloglint` is integrated into [`golangci-lint`][1], and this is the recommended way to use it.
-
-To enable the linter, add the following lines to `.golangci.yml`:
+`sloglint` is part of [golangci-lint](https://golangci-lint.run), and this is the recommended way to use it.
```yaml
+# .golangci.yaml
linters:
enable:
- sloglint
```
-Alternatively, you can download a prebuilt binary from the [Releases][2] page to use `sloglint` standalone.
+Alternatively, you can download a prebuilt binary from the [Releases](https://github.com/go-simpler/sloglint/releases) page to use `sloglint` standalone.
-## 📋 Usage
+## Supported checks
-Run `golangci-lint` with `sloglint` enabled.
-See the list of [available options][3] to configure the linter.
+For `log/slog` functions:
+- [No global logger](#no-global-logger)
+- [Context only](#context-only)
+- [Discard handler](#discard-handler)
-When using `sloglint` standalone, pass the options as flags of the same name.
+For log messages:
+- [Static message](#static-message)
+- [Message style](#message-style)
-### No mixed arguments
+For log arguments:
+- [No mixed arguments](#no-mixed-arguments)
+- [Key-value pairs only](#key-value-pairs-only)
+- [Attributes only](#attributes-only)
+- [Arguments on separate lines](#arguments-on-separate-lines)
-The `no-mixed-args` option causes `sloglint` to report mixing key-values pairs and attributes within a single function call:
+For log keys:
+- [Constant keys](#constant-keys)
+- [Allowed keys](#allowed-keys)
+- [Forbidden keys](#forbidden-keys)
+- [Key naming case](#key-naming-case)
-```go
-slog.Info("a user has logged in", "user_id", 42, slog.String("ip_address", "192.0.2.0")) // sloglint: key-value pairs and attributes should not be mixed
-```
+The checks for log messages, arguments, and keys can also be used to analyze [custom functions](#custom-function-analysis).
-It is enabled by default.
-
-### Key-value pairs only
+### No global logger
-The `kv-only` option causes `sloglint` to report any use of attributes:
+Report the use of global loggers.
+Alternatively, only report the use of the `slog.Default()` logger.
```go
-slog.Info("a user has logged in", slog.Int("user_id", 42)) // sloglint: attributes should not be used
+slog.Info("a user has logged in")
+// sloglint: global logger should not be used
```
-### Attributes only
-
-In contrast, the `attr-only` option causes `sloglint` to report any use of key-value pairs:
-
-```go
-slog.Info("a user has logged in", "user_id", 42) // sloglint: key-value pairs should not be used
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ no-global: "all" # Or "default".
```
-### No global
+### Context only
-Some projects prefer to pass loggers as explicit dependencies.
-The `no-global` option causes `sloglint` to report the use of global loggers.
+Report the use of functions without a `context.Context`.
+Alternatively, only report their use if a context exists within the scope of the outermost function.
```go
-slog.Info("a user has logged in", "user_id", 42) // sloglint: global logger should not be used
+slog.Info("a user has logged in")
+// sloglint: InfoContext should be used instead
+```
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ context: "all" # Or "scope".
```
-Possible values are `all` (report all global loggers) and `default` (report only the default `slog` logger).
+This check partially supports autofix.
-### Context only
+### Discard handler
-Some `slog.Handler` implementations make use of the given `context.Context` (e.g. to access context values).
-For them to work properly, you need to pass a context to all logger calls.
-The `context-only` option causes `sloglint` to report the use of methods without a context:
+Suggest using `slog.DiscardHandler` when possible.
```go
-slog.Info("a user has logged in") // sloglint: InfoContext should be used instead
+slog.NewJSONHandler(io.Discard, nil)
+// sloglint: use slog.DiscardHandler instead
```
-Possible values are `all` (report all contextless calls) and `scope` (report only if a context exists in the scope of the outermost function).
+This check is enabled by default and supports autofix.
-### Static messages
+### Static message
-To get the most out of structured logging, you may want to require log messages to be static.
-The `static-msg` option causes `sloglint` to report non-static messages:
+Report dynamic log messages, such as those that are built with `fmt.Sprintf`.
```go
-slog.Info(fmt.Sprintf("a user with id %d has logged in", 42)) // sloglint: message should be a string literal or a constant
+slog.Info(fmt.Sprintf("a user with id %d has logged in", 42))
+// sloglint: message should be a string literal or a constant
+```
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ static-msg: true
```
-The report can be fixed by moving dynamic values to arguments:
+### Message style
+
+Report log messages that do not match a particular style.
+The supported styles are `lowercased` (the first letter is lowercase) and `capitalized` (the first letter is uppercase).
```go
-slog.Info("a user has logged in", "user_id", 42)
+slog.Info("A user has logged in")
+// sloglint: message should be lowercased
```
-### Message style
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ msg-style: "lowercased" # Or "capitalized".
+```
-The `msg-style` option causes `sloglint` to check log messages for a particular style.
+### No mixed arguments
-Possible values are `lowercased` (report messages that begin with an uppercase letter)...
+Report the use of both key-value pairs and attributes within a single function call.
```go
-slog.Info("Msg") // sloglint: message should be lowercased
+slog.Info("a user has logged in", "user_id", 42, slog.String("ip_address", "192.0.2.0"))
+// sloglint: key-value pairs and attributes should not be mixed
```
-...and `capitalized` (report messages that begin with a lowercase letter):
+This check is enabled by default.
+
+### Key-value pairs only
+
+Report any use of attributes as function call arguments.
```go
-slog.Info("msg") // sloglint: message should be capitalized
+slog.Info("a user has logged in", slog.Int("user_id", 42))
+// sloglint: attributes should not be used
```
-Special cases such as acronyms (e.g. `HTTP`, `U.S.`) are ignored.
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ kv-only: true
+```
-### No raw keys
+### Attributes only
-To prevent typos, you may want to forbid the use of raw keys altogether.
-The `no-raw-keys` option causes `sloglint` to report the use of strings as keys
-(including `slog.Attr` calls, e.g. `slog.Int("user_id", 42)`):
+Report any use of key-value pairs as function call arguments.
```go
-slog.Info("a user has logged in", "user_id", 42) // sloglint: raw keys should not be used
+slog.Info("a user has logged in", "user_id", 42)
+// sloglint: key-value pairs should not be used
+```
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ attr-only: true
```
-This report can be fixed by using either constants...
+### Arguments on separate lines
+
+Report two or more arguments on the same line.
+A key-value pair is considered a single argument.
```go
-const UserId = "user_id"
+slog.Info("a user has logged in", "user_id", 42, "ip_address", "192.0.2.0")
+// sloglint: arguments should be put on separate lines
+```
-slog.Info("a user has logged in", UserId, 42)
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ args-on-sep-lines: true
```
-...or custom `slog.Attr` constructors:
+### Constant keys
-```go
-func UserId(value int) slog.Attr { return slog.Int("user_id", value) }
+Report the use of string literals as log keys.
-slog.Info("a user has logged in", UserId(42))
+```go
+slog.Info("a user has logged in", "user_id", 42)
+// sloglint: the "user_id" key should be a constant
```
-> [!TIP]
-> Such helpers can be automatically generated for you by the [`sloggen`][4] tool. Give it a try too!
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ no-raw-keys: true
+```
-### Key naming convention
+### Allowed keys
-To ensure consistency in logs, you may want to enforce a single key naming convention.
-The `key-naming-case` option causes `sloglint` to report keys written in a case other than the given one:
+Report the use of log keys that are not explicitly allowed.
```go
-slog.Info("a user has logged in", "user-id", 42) // sloglint: keys should be written in snake_case
+slog.Info("a user has logged in", "id", 42)
+// sloglint: the "id" key is not allowed and should not be used
```
-Possible values are `snake`, `kebab`, `camel`, or `pascal`.
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ allowed-keys:
+ - user_id
+```
### Forbidden keys
-To prevent accidental use of reserved log keys, you may want to forbid specific keys altogether.
-The `forbidden-keys` option causes `sloglint` to report the use of forbidden keys:
+Report the use of forbidden log keys.
+When using the standard `slog.JSONHandler` or `slog.TextHandler`,
+you may want to forbid the `time`, `level`, `msg`, and `source` keys,
+as these will be written by the handler.
```go
-slog.Info("a user has logged in", "reserved", 42) // sloglint: "reserved" key is forbidden and should not be used
+slog.Info("a user has logged in", "time", time.Now())
+// sloglint: the "time" key is forbidden and should not be used
```
-For example, when using the standard `slog.JSONHandler` and `slog.TextHandler`,
-you may want to forbid the `time`, `level`, `msg`, and `source` keys, as these are used by the handlers.
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ forbidden-keys:
+ - time
+ - level
+ - msg
+ - source
+```
-### Arguments on separate lines
+### Key naming case
-To improve code readability, you may want to put arguments on separate lines, especially when using key-value pairs.
-The `args-on-sep-lines` option causes `sloglint` to report 2+ arguments on the same line:
+Report log keys that do not match a particular naming case.
+The supported cases are `snake_case`, `kebab-case`, `camelCase`, and `PascalCase`.
```go
-slog.Info("a user has logged in", "user_id", 42, "ip_address", "192.0.2.0") // sloglint: arguments should be put on separate lines
+slog.Info("a user has logged in", "user-id", 42)
+// sloglint: keys should be written in snake_case
```
-This report can be fixed by reformatting the code:
-
-```go
-slog.Info("a user has logged in",
- "user_id", 42,
- "ip_address", "192.0.2.0",
-)
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ key-naming-case: "snake" # Or "kebab", "camel", "pascal".
```
-[1]: https://golangci-lint.run
-[2]: https://github.com/go-simpler/sloglint/releases
-[3]: https://golangci-lint.run/usage/linters/#sloglint
-[4]: https://github.com/go-simpler/sloggen
+This check supports autofix.
+
+## Custom function analysis
+
+Analyze custom functions in addition to the standard `log/slog` functions.
+
+The following function properties must be specified:
+1. The full name of the function, including the package, e.g. `log/slog.Info`.
+If the function is a method, the receiver type must be wrapped in parentheses, e.g. `(*log/slog.Logger).Info`.
+2. The position of the `msg string` argument in the function signature, starting from 0.
+If there is no message in the function, a negative value must be passed.
+3. The position of the `args ...any` argument in the function signature, starting from 0.
+If there are no arguments in the function, a negative value must be passed.
+
+Here's an example for the [exp/slog](https://pkg.go.dev/golang.org/x/exp/slog) package, the predecessor of `log/slog`.
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ custom-funcs:
+ - name: "(*golang.org/x/exp/slog.Logger).InfoContext"
+ msg-pos: 1
+ args-pos: 2
+```
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/analyzer.go b/hack/tools/vendor/go-simpler.org/sloglint/analyzer.go
new file mode 100644
index 00000000000..03e43e02c3d
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/analyzer.go
@@ -0,0 +1,209 @@
+// Package sloglint implements the sloglint analyzer.
+package sloglint
+
+import (
+ "go/ast"
+ "go/version"
+ "slices"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/go/types/typeutil"
+)
+
+// New creates a new sloglint analyzer.
+func New(opts *Options) *analysis.Analyzer {
+ if opts == nil {
+ opts = &Options{NoMixedArguments: true}
+ }
+
+ return &analysis.Analyzer{
+ Name: "sloglint",
+ Doc: "Ensures consistent code style when using log/slog.",
+ URL: "https://go-simpler.org/sloglint",
+ Flags: flags(opts),
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ Run: func(pass *analysis.Pass) (any, error) {
+ if err := opts.validate(); err != nil {
+ return nil, err
+ }
+
+ root := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Root()
+ for cursor := range root.Preorder(new(ast.CallExpr), new(ast.CompositeLit)) {
+ analyzeNode(pass, opts, cursor)
+ }
+
+ return nil, nil
+ },
+ }
+}
+
+var slogFuncs = []Func{
+ {"log/slog.Log", 2, 3},
+ {"log/slog.LogAttrs", 2, 3},
+ {"log/slog.Debug", 0, 1},
+ {"log/slog.Info", 0, 1},
+ {"log/slog.Warn", 0, 1},
+ {"log/slog.Error", 0, 1},
+ {"log/slog.DebugContext", 1, 2},
+ {"log/slog.InfoContext", 1, 2},
+ {"log/slog.WarnContext", 1, 2},
+ {"log/slog.ErrorContext", 1, 2},
+ {"log/slog.With", -1, 0},
+ {"log/slog.Group", -1, 1},
+ {"log/slog.NewTextHandler", -1, -1},
+ {"log/slog.NewJSONHandler", -1, -1},
+ {"(*log/slog.Logger).Log", 2, 3},
+ {"(*log/slog.Logger).LogAttrs", 2, 3},
+ {"(*log/slog.Logger).Debug", 0, 1},
+ {"(*log/slog.Logger).Info", 0, 1},
+ {"(*log/slog.Logger).Warn", 0, 1},
+ {"(*log/slog.Logger).Error", 0, 1},
+ {"(*log/slog.Logger).DebugContext", 1, 2},
+ {"(*log/slog.Logger).InfoContext", 1, 2},
+ {"(*log/slog.Logger).WarnContext", 1, 2},
+ {"(*log/slog.Logger).ErrorContext", 1, 2},
+ {"(*log/slog.Logger).With", -1, 0},
+}
+
+func analyzeNode(pass *analysis.Pass, opts *Options, cursor inspector.Cursor) {
+ node := cursor.Node()
+ if cl, ok := node.(*ast.CompositeLit); ok && typeName(pass.TypesInfo, cl) == "log/slog.Attr" {
+ analyzeAttrKey(pass, opts, cl)
+ return
+ }
+
+ call, ok := node.(*ast.CallExpr)
+ if !ok {
+ return
+ }
+
+ fn := typeutil.StaticCallee(pass.TypesInfo, call)
+ if fn == nil {
+ return
+ }
+
+ switch fn.FullName() {
+ case "log/slog.Int",
+ "log/slog.Int64",
+ "log/slog.Uint64",
+ "log/slog.Float64",
+ "log/slog.String",
+ "log/slog.Bool",
+ "log/slog.Time",
+ "log/slog.Duration",
+ "log/slog.Any":
+ analyzeKey(pass, opts, call.Args[0])
+ return
+ case "log/slog.Group":
+ analyzeKey(pass, opts, call.Args[0])
+ // Special case: don't return here, we also need to analyze the group's arguments.
+ }
+
+ funcs := slices.Concat(slogFuncs, opts.CustomFuncs)
+ idx := slices.IndexFunc(funcs, func(f Func) bool {
+ return f.FullName == fn.FullName()
+ })
+ if idx == -1 {
+ return
+ }
+
+ if idx < len(slogFuncs) {
+ analyzeFunction(pass, opts, call, cursor)
+ }
+ if pos := funcs[idx].MessagePos; pos >= 0 && len(call.Args) > pos {
+ analyzeMessage(pass, opts, call.Args[pos])
+ }
+ if pos := funcs[idx].ArgumentsPos; pos >= 0 && len(call.Args) > pos {
+ analyzeArguments(pass, opts, call.Args[pos:])
+ }
+}
+
+func analyzeFunction(pass *analysis.Pass, opts *Options, call *ast.CallExpr, cursor inspector.Cursor) {
+ if opts.NoGlobalLogger != "" {
+ noGlobalLogger(pass, call, opts.NoGlobalLogger == noGlobalLoggerDefault)
+ }
+ if opts.ContextOnly != "" {
+ contextOnly(pass, call, cursor, opts.ContextOnly == contextOnlyScope)
+ }
+ v := pass.Module.GoVersion // Empty in test runs.
+ if v == "" || version.Compare("go"+v, "go1.24") >= 0 {
+ discardHandler(pass, call)
+ }
+}
+
+func analyzeMessage(pass *analysis.Pass, opts *Options, msg ast.Expr) {
+ if opts.StaticMessage {
+ staticMessage(pass, msg)
+ }
+ if opts.MessageStyle != "" {
+ messageStyle(pass, msg, opts.MessageStyle)
+ }
+}
+
+func analyzeArguments(pass *analysis.Pass, opts *Options, args []ast.Expr) {
+ var keys, attrs []ast.Expr
+
+ for i := 0; i < len(args); i++ {
+ typ := pass.TypesInfo.TypeOf(args[i])
+ if typ == nil {
+ continue
+ }
+ switch typ.String() {
+ case "string":
+ keys = append(keys, args[i])
+ analyzeKey(pass, opts, args[i])
+ i++ // Skip the value.
+ case "log/slog.Attr":
+ attrs = append(attrs, args[i])
+ case "[]any", "[]log/slog.Attr":
+ continue // The last argument may be an unpacked slice, skip it.
+ }
+ }
+
+ if opts.NoMixedArguments {
+ noMixedArguments(pass, keys, attrs)
+ }
+ if opts.KeyValuePairsOnly {
+ keyValuePairsOnly(pass, attrs)
+ }
+ if opts.AttributesOnly {
+ attributesOnly(pass, keys)
+ }
+ if opts.ArgumentsOnSeparateLines {
+ argumentsOnSeparateLines(pass, keys, attrs)
+ }
+}
+
+func analyzeKey(pass *analysis.Pass, opts *Options, key ast.Expr) {
+ if opts.ConstantKeys {
+ constantKeys(pass, key)
+ }
+ if opts.KeyNamingCase != "" {
+ keyNamingCase(pass, key, opts.KeyNamingCase)
+ }
+ if len(opts.AllowedKeys) > 0 {
+ allowedKeys(pass, key, opts.AllowedKeys)
+ }
+ if len(opts.ForbiddenKeys) > 0 {
+ forbiddenKeys(pass, key, opts.ForbiddenKeys)
+ }
+}
+
+func analyzeAttrKey(pass *analysis.Pass, opts *Options, attr *ast.CompositeLit) {
+ switch len(attr.Elts) {
+ case 1:
+ if kv := attr.Elts[0].(*ast.KeyValueExpr); kv.Key.(*ast.Ident).Name == "Key" {
+ analyzeKey(pass, opts, kv.Value) // slog.Attr{Key: ...}
+ }
+ case 2:
+ if kv, ok := attr.Elts[0].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
+ analyzeKey(pass, opts, kv.Value) // slog.Attr{Key: ..., Value: ...}
+ } else if kv, ok := attr.Elts[1].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
+ analyzeKey(pass, opts, kv.Value) // slog.Attr{Value: ..., Key: ...}
+ } else {
+ analyzeKey(pass, opts, attr.Elts[0]) // slog.Attr{..., ...}
+ }
+ }
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/argument_checks.go b/hack/tools/vendor/go-simpler.org/sloglint/argument_checks.go
new file mode 100644
index 00000000000..17590d7e7f2
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/argument_checks.go
@@ -0,0 +1,55 @@
+package sloglint
+
+import (
+ "go/ast"
+ "slices"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+func noMixedArguments(pass *analysis.Pass, keys, attrs []ast.Expr) {
+ if len(keys) == 0 {
+ return
+ }
+ for _, attr := range attrs {
+ if call, ok := attr.(*ast.CallExpr); ok && funcName(pass.TypesInfo, call) == "log/slog.Group" {
+ continue // Special case: slog.Group() should always be allowed.
+ }
+ pass.ReportRangef(attr, "key-value pairs and attributes should not be mixed")
+ return
+ }
+}
+
+func keyValuePairsOnly(pass *analysis.Pass, attrs []ast.Expr) {
+ for _, attr := range attrs {
+ if call, ok := attr.(*ast.CallExpr); ok && funcName(pass.TypesInfo, call) == "log/slog.Group" {
+ continue // Special case: slog.Group() should always be allowed.
+ }
+ pass.ReportRangef(attr, "attributes should not be used")
+ return
+ }
+}
+
+func attributesOnly(pass *analysis.Pass, keys []ast.Expr) {
+ for _, key := range keys {
+ pass.ReportRangef(key, "key-value pairs should not be used")
+ return
+ }
+}
+
+func argumentsOnSeparateLines(pass *analysis.Pass, keys, attrs []ast.Expr) {
+ args := slices.Concat(keys, attrs)
+ if len(args) <= 1 {
+ return // Special case: slog.Info("msg", "key", "value") is fine.
+ }
+
+ prevLine := pass.Fset.Position(args[0].Pos()).Line
+ for _, arg := range args[1:] {
+ currLine := pass.Fset.Position(arg.Pos()).Line
+ if currLine == prevLine {
+ pass.Reportf(arg.Pos(), "arguments should be put on separate lines")
+ return
+ }
+ prevLine = currLine
+ }
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/function_checks.go b/hack/tools/vendor/go-simpler.org/sloglint/function_checks.go
new file mode 100644
index 00000000000..7781aba6aa7
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/function_checks.go
@@ -0,0 +1,144 @@
+package sloglint
+
+import (
+ "fmt"
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/go/types/typeutil"
+)
+
+func noGlobalLogger(pass *analysis.Pass, call *ast.CallExpr, defaultOnly bool) {
+ fn := typeutil.StaticCallee(pass.TypesInfo, call)
+
+ switch fn.Name() {
+ case "Log", "LogAttrs",
+ "Debug", "Info", "Warn", "Error",
+ "DebugContext", "InfoContext", "WarnContext", "ErrorContext",
+ "With":
+ default:
+ return
+ }
+
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ ident, ok := sel.X.(*ast.Ident)
+ if !ok {
+ return
+ }
+
+ if ident.Name == "slog" {
+ pass.ReportRangef(sel.X, "default logger should not be used")
+ return
+ }
+
+ if defaultOnly {
+ return
+ }
+
+ if obj := pass.TypesInfo.ObjectOf(ident); obj != nil && obj.Parent() == obj.Pkg().Scope() {
+ pass.ReportRangef(sel.X, "global logger should not be used")
+ }
+}
+
+func contextOnly(pass *analysis.Pass, call *ast.CallExpr, cursor inspector.Cursor, scopeOnly bool) {
+ fn := typeutil.StaticCallee(pass.TypesInfo, call)
+
+ switch fn.Name() {
+ case "Debug", "Info", "Warn", "Error":
+ default:
+ return
+ }
+
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ if !scopeOnly {
+ // Don't suggest fixes here, we don't know whether there is a context in the scope.
+ pass.ReportRangef(sel.Sel, "%sContext should be used instead", fn.Name())
+ return
+ }
+
+ for cursor := range cursor.Enclosing(new(ast.FuncDecl), new(ast.FuncLit)) {
+ var params []*ast.Field
+ switch fn := cursor.Node().(type) {
+ case *ast.FuncDecl:
+ params = fn.Type.Params.List
+ case *ast.FuncLit:
+ params = fn.Type.Params.List
+ }
+
+ if len(params) == 0 {
+ continue
+ }
+
+ for _, param := range params {
+ if len(param.Names) == 0 {
+ continue
+ }
+
+ var ctxArg string
+ switch name := param.Names[0]; typeName(pass.TypesInfo, name) {
+ case "context.Context":
+ ctxArg = name.Name
+ case "*net/http.Request":
+ ctxArg = name.Name + ".Context()"
+ default:
+ continue
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: sel.Sel.Pos(),
+ End: sel.Sel.End(),
+ Message: fmt.Sprintf("%sContext should be used instead", fn.Name()),
+ SuggestedFixes: []analysis.SuggestedFix{{
+ TextEdits: []analysis.TextEdit{{
+ Pos: sel.Sel.Pos(),
+ End: call.Lparen + 1,
+ NewText: fmt.Appendf(nil, "%sContext(%s, ", fn.Name(), ctxArg),
+ }},
+ }},
+ })
+ return
+ }
+ }
+}
+
+func discardHandler(pass *analysis.Pass, call *ast.CallExpr) {
+ if len(call.Args) == 0 {
+ return
+ }
+
+ sel, ok := call.Args[0].(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ obj := pass.TypesInfo.ObjectOf(sel.Sel)
+ if obj == nil {
+ return
+ }
+
+ if obj.Pkg().Name() != "io" || obj.Name() != "Discard" {
+ return
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: call.Pos(),
+ End: call.Pos(),
+ Message: "use slog.DiscardHandler instead",
+ SuggestedFixes: []analysis.SuggestedFix{{
+ TextEdits: []analysis.TextEdit{{
+ Pos: call.Pos(),
+ End: call.End(),
+ NewText: []byte("slog.DiscardHandler"),
+ }},
+ }},
+ })
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/key_checks.go b/hack/tools/vendor/go-simpler.org/sloglint/key_checks.go
new file mode 100644
index 00000000000..c664a842458
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/key_checks.go
@@ -0,0 +1,73 @@
+package sloglint
+
+import (
+ "fmt"
+ "go/ast"
+ "go/types"
+ "slices"
+ "strconv"
+
+ "github.com/ettle/strcase"
+ "golang.org/x/tools/go/analysis"
+)
+
+func constantKeys(pass *analysis.Pass, key ast.Expr) {
+ if sel, ok := key.(*ast.SelectorExpr); ok {
+ key = sel.Sel // The key is defined in another package, e.g. pkg.ConstKey.
+ }
+ if ident, ok := key.(*ast.Ident); ok {
+ if _, ok := pass.TypesInfo.ObjectOf(ident).(*types.Const); ok {
+ return
+ }
+ }
+ name, _ := keyName(key)
+ pass.ReportRangef(key, "the %q key should be a constant", name)
+}
+
+func allowedKeys(pass *analysis.Pass, key ast.Expr, allowed []string) {
+ if name, ok := keyName(key); ok && !slices.Contains(allowed, name) {
+ pass.ReportRangef(key, "the %q key is not allowed and should not be used", name)
+ }
+}
+
+func forbiddenKeys(pass *analysis.Pass, key ast.Expr, forbidden []string) {
+ if name, ok := keyName(key); ok && slices.Contains(forbidden, name) {
+ pass.ReportRangef(key, "the %q key is forbidden and should not be used", name)
+ }
+}
+
+func keyNamingCase(pass *analysis.Pass, key ast.Expr, caseName string) {
+ name, ok := keyName(key)
+ if !ok {
+ return
+ }
+
+ var caseFn func(string) string
+ switch caseName {
+ case keyNamingCaseSnake:
+ caseFn = strcase.ToSnake
+ case keyNamingCaseKebab:
+ caseFn = strcase.ToKebab
+ case keyNamingCaseCamel:
+ caseFn = strcase.ToCamel
+ case keyNamingCasePascal:
+ caseFn = strcase.ToPascal
+ }
+
+ if name == caseFn(name) {
+ return
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: key.Pos(),
+ End: key.End(),
+ Message: fmt.Sprintf("keys should be written in %s", caseFn(caseName+" case")),
+ SuggestedFixes: []analysis.SuggestedFix{{
+ TextEdits: []analysis.TextEdit{{
+ Pos: key.Pos(),
+ End: key.End(),
+ NewText: strconv.AppendQuote(nil, caseFn(name)),
+ }},
+ }},
+ })
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/message_checks.go b/hack/tools/vendor/go-simpler.org/sloglint/message_checks.go
new file mode 100644
index 00000000000..746745f0f75
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/message_checks.go
@@ -0,0 +1,81 @@
+package sloglint
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+ "strconv"
+ "strings"
+ "unicode"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+func staticMessage(pass *analysis.Pass, msg ast.Expr) {
+ var isStatic func(msg ast.Expr) bool
+ isStatic = func(msg ast.Expr) bool {
+ switch msg := msg.(type) {
+ case *ast.BasicLit: // e.g. slog.Info("msg")
+ return msg.Kind == token.STRING
+ case *ast.Ident: // e.g. slog.Info(constMsg)
+ _, isConst := pass.TypesInfo.ObjectOf(msg).(*types.Const)
+ return isConst
+ case *ast.BinaryExpr: // e.g. slog.Info("x" + "y")
+ if msg.Op != token.ADD {
+ panic("unreachable") // Only "+" can be applied to strings.
+ }
+ return isStatic(msg.X) && isStatic(msg.Y)
+ default:
+ return false
+ }
+ }
+
+ if !isStatic(msg) {
+ pass.ReportRangef(msg, "message should be a string literal or a constant")
+ }
+}
+
+func messageStyle(pass *analysis.Pass, msg ast.Expr, style string) {
+ lit, ok := msg.(*ast.BasicLit)
+ if !ok || lit.Kind != token.STRING {
+ return
+ }
+
+ s, err := strconv.Unquote(lit.Value)
+ if err != nil {
+ panic("unreachable") // String literals are always quoted.
+ }
+
+ runes := []rune(strings.TrimSpace(s))
+ if len(runes) < 2 {
+ return
+ }
+
+ first, second := runes[0], runes[1]
+
+ if !unicode.IsLetter(first) {
+ return // e.g. "200 OK"
+ }
+
+ switch style {
+ case messageStyleLowercased:
+ if unicode.IsLower(first) {
+ return
+ }
+ if unicode.IsPunct(second) {
+ return // e.g. "U.S."
+ }
+ if unicode.IsUpper(second) {
+ return // e.g. "HTTP"
+ }
+ case messageStyleCapitalized:
+ if unicode.IsUpper(first) {
+ return
+ }
+ if unicode.IsUpper(second) {
+ return // e.g. "iPhone"
+ }
+ }
+
+ pass.ReportRangef(msg, "message should be %s", style)
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/options.go b/hack/tools/vendor/go-simpler.org/sloglint/options.go
new file mode 100644
index 00000000000..361eb59330e
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/options.go
@@ -0,0 +1,152 @@
+package sloglint
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "strings"
+)
+
+// Func describes a function to analyze, e.g. [slog.Info].
+type Func struct {
+ // The full name of the function, including the package, e.g. "log/slog.Info".
+ // If the function is a method, the receiver type must be wrapped in parentheses, e.g. "(*log/slog.Logger).Info".
+ FullName string
+ // The position of the "msg string" argument in the function signature, starting from 0.
+ // If there is no message in the function, a negative value must be passed.
+ MessagePos int
+ // The position of the "args ...any" argument in the function signature, starting from 0.
+ // If there are no arguments in the function, a negative value must be passed.
+ ArgumentsPos int
+}
+
+// Options contains options for the sloglint analyzer.
+type Options struct {
+ // Report the use of global loggers ("all" or "default").
+ NoGlobalLogger string
+ // Report the use of functions without a [context.Context] ("all" or "scope").
+ ContextOnly string
+
+ // Report dynamic log messages, such as those that are built with [fmt.Sprintf].
+ StaticMessage bool
+ // Report log messages that do not match a particular style ("lowercased" or "capitalized").
+ MessageStyle string
+
+ // Report the use of both key-value pairs and attributes within a single function call (default true).
+ NoMixedArguments bool
+ // Report any use of attributes as function call arguments.
+ KeyValuePairsOnly bool
+ // Report any use of key-value pairs as function call arguments.
+ AttributesOnly bool
+ // Report two or more arguments on the same line.
+ ArgumentsOnSeparateLines bool
+
+ // Report the use of string literals as log keys.
+ ConstantKeys bool
+ // Report the use of log keys that are not explicitly allowed.
+ AllowedKeys []string
+ // Report the use of forbidden log keys.
+ ForbiddenKeys []string
+ // Report log keys that do not match a particular naming case ("snake", "kebab", "camel", or "pascal").
+ KeyNamingCase string
+
+ // Analyze custom functions in addition to the standard [log/slog] functions.
+ CustomFuncs []Func
+}
+
+// Possible values for [Options.NoGlobalLogger].
+const (
+ noGlobalLoggerAll = "all"
+ noGlobalLoggerDefault = "default"
+)
+
+// Possible values for [Options.ContextOnly].
+const (
+ contextOnlyAll = "all"
+ contextOnlyScope = "scope"
+)
+
+// Possible values for [Options.MessageStyle].
+const (
+ messageStyleLowercased = "lowercased"
+ messageStyleCapitalized = "capitalized"
+)
+
+// Possible values for [Options.KeyNamingCase].
+const (
+ keyNamingCaseSnake = "snake"
+ keyNamingCaseKebab = "kebab"
+ keyNamingCaseCamel = "camel"
+ keyNamingCasePascal = "pascal"
+)
+
+var (
+ errIncompatible = errors.New("incompatible")
+ errInvalidValue = errors.New("invalid value")
+)
+
+func (opts *Options) validate() error {
+ switch opts.NoGlobalLogger {
+ case "", noGlobalLoggerAll, noGlobalLoggerDefault:
+ default:
+ return fmt.Errorf("sloglint: Options.NoGlobalLogger has an %w %q", errInvalidValue, opts.NoGlobalLogger)
+ }
+
+ switch opts.ContextOnly {
+ case "", contextOnlyAll, contextOnlyScope:
+ default:
+ return fmt.Errorf("sloglint: Options.ContextOnly has an %w %q", errInvalidValue, opts.ContextOnly)
+ }
+
+ switch opts.MessageStyle {
+ case "", messageStyleLowercased, messageStyleCapitalized:
+ default:
+ return fmt.Errorf("sloglint: Options.MessageStyle has an %w %q", errInvalidValue, opts.MessageStyle)
+ }
+
+ if opts.KeyValuePairsOnly && opts.AttributesOnly {
+ return fmt.Errorf("sloglint: Options.KeyValuePairsOnly and Options.AttributesOnly are %w", errIncompatible)
+ }
+
+ switch opts.KeyNamingCase {
+ case "", keyNamingCaseSnake, keyNamingCaseKebab, keyNamingCaseCamel, keyNamingCasePascal:
+ default:
+ return fmt.Errorf("sloglint: Options.KeyNamingCase has an %w %q", errInvalidValue, opts.KeyNamingCase)
+ }
+
+ return nil
+}
+
+func flags(opts *Options) flag.FlagSet {
+ fs := flag.NewFlagSet("sloglint", flag.ContinueOnError)
+
+ listVar := func(p *[]string, name, usage string) {
+ fs.Func(name, usage+" (comma-separated)", func(s string) error {
+ *p = append(*p, strings.Split(s, ",")...)
+ return nil
+ })
+ }
+
+ fs.StringVar(&opts.NoGlobalLogger, "no-global", opts.NoGlobalLogger, `report the use of global loggers ("all" or "default")`)
+ fs.StringVar(&opts.ContextOnly, "ctx-only", opts.ContextOnly, `report the use of functions without a context.Context ("all" or "scope")`)
+ fs.BoolVar(&opts.StaticMessage, "static-msg", opts.StaticMessage, `report dynamic log messages, such as those that are built with fmt.Sprintf`)
+ fs.StringVar(&opts.MessageStyle, "msg-style", opts.MessageStyle, `report log messages that do not match a particular style ("lowercased" or "capitalized")`)
+ fs.BoolVar(&opts.NoMixedArguments, "no-mixed-args", opts.NoMixedArguments, `report the use of both key-value pairs and attributes within a single function call (default true)`)
+ fs.BoolVar(&opts.KeyValuePairsOnly, "kv-only", opts.KeyValuePairsOnly, `report any use of attributes as function call arguments`)
+ fs.BoolVar(&opts.AttributesOnly, "attr-only", opts.AttributesOnly, `report any use of key-value pairs as function call arguments`)
+ fs.BoolVar(&opts.ArgumentsOnSeparateLines, "args-on-sep-lines", opts.ArgumentsOnSeparateLines, `report two or more arguments on the same line`)
+ fs.BoolVar(&opts.ConstantKeys, "const-keys", opts.ConstantKeys, `report the use of string literal as log keys`)
+ listVar(&opts.AllowedKeys, "allowed-keys", `report the use of log keys that are not explicitly allowed`)
+ listVar(&opts.ForbiddenKeys, "forbidden-keys", `report the use of forbidden log keys`)
+ fs.StringVar(&opts.KeyNamingCase, "key-naming-case", opts.KeyNamingCase, `report log keys that do not match a particular naming case ("snake", "kebab", "camel", or "pascal")`)
+
+ fs.Func("fn", `analyze a custom function (format: "full-name:msg-pos:args-pos")`, func(s string) error {
+ name, rest, _ := strings.Cut(s, ":")
+ fn := Func{FullName: name}
+ _, err := fmt.Sscanf(rest, "%d:%d", &fn.MessagePos, &fn.ArgumentsPos)
+ opts.CustomFuncs = append(opts.CustomFuncs, fn)
+ return err
+ })
+
+ return *fs
+}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/sloglint.go b/hack/tools/vendor/go-simpler.org/sloglint/sloglint.go
deleted file mode 100644
index ff5d1f80cc3..00000000000
--- a/hack/tools/vendor/go-simpler.org/sloglint/sloglint.go
+++ /dev/null
@@ -1,576 +0,0 @@
-// Package sloglint implements the sloglint analyzer.
-package sloglint
-
-import (
- "errors"
- "flag"
- "fmt"
- "go/ast"
- "go/token"
- "go/types"
- "go/version"
- "iter"
- "slices"
- "strconv"
- "strings"
- "unicode"
-
- "github.com/ettle/strcase"
- "golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/passes/inspect"
- "golang.org/x/tools/go/ast/inspector"
- "golang.org/x/tools/go/types/typeutil"
-)
-
-// Options are options for the sloglint analyzer.
-type Options struct {
- NoMixedArgs bool // Enforce not mixing key-value pairs and attributes (default true).
- KVOnly bool // Enforce using key-value pairs only (overrides NoMixedArgs, incompatible with AttrOnly).
- AttrOnly bool // Enforce using attributes only (overrides NoMixedArgs, incompatible with KVOnly).
- NoGlobal string // Enforce not using global loggers ("all" or "default").
- ContextOnly string // Enforce using methods that accept a context ("all" or "scope").
- StaticMsg bool // Enforce using static messages.
- MsgStyle string // Enforce message style ("lowercased" or "capitalized").
- NoRawKeys bool // Enforce using constants instead of raw keys.
- KeyNamingCase string // Enforce key naming convention ("snake", "kebab", "camel", or "pascal").
- ForbiddenKeys []string // Enforce not using specific keys.
- ArgsOnSepLines bool // Enforce putting arguments on separate lines.
-
- go124 bool
-}
-
-// New creates a new sloglint analyzer.
-func New(opts *Options) *analysis.Analyzer {
- if opts == nil {
- opts = &Options{NoMixedArgs: true}
- }
-
- return &analysis.Analyzer{
- Name: "sloglint",
- Doc: "ensure consistent code style when using log/slog",
- Flags: flags(opts),
- Requires: []*analysis.Analyzer{inspect.Analyzer},
- Run: func(pass *analysis.Pass) (any, error) {
- if opts.KVOnly && opts.AttrOnly {
- return nil, fmt.Errorf("sloglint: Options.KVOnly and Options.AttrOnly: %w", errIncompatible)
- }
-
- switch opts.NoGlobal {
- case "", "all", "default":
- default:
- return nil, fmt.Errorf("sloglint: Options.NoGlobal=%s: %w", opts.NoGlobal, errInvalidValue)
- }
-
- switch opts.ContextOnly {
- case "", "all", "scope":
- default:
- return nil, fmt.Errorf("sloglint: Options.ContextOnly=%s: %w", opts.ContextOnly, errInvalidValue)
- }
-
- switch opts.MsgStyle {
- case "", styleLowercased, styleCapitalized:
- default:
- return nil, fmt.Errorf("sloglint: Options.MsgStyle=%s: %w", opts.MsgStyle, errInvalidValue)
- }
-
- switch opts.KeyNamingCase {
- case "", snakeCase, kebabCase, camelCase, pascalCase:
- default:
- return nil, fmt.Errorf("sloglint: Options.KeyNamingCase=%s: %w", opts.KeyNamingCase, errInvalidValue)
- }
-
- if version.Compare("go"+pass.Module.GoVersion, "go1.24") >= 0 {
- opts.go124 = true
- }
-
- run(pass, opts)
- return nil, nil
- },
- }
-}
-
-var (
- errIncompatible = errors.New("incompatible options")
- errInvalidValue = errors.New("invalid value")
-)
-
-func flags(opts *Options) flag.FlagSet {
- fset := flag.NewFlagSet("sloglint", flag.ContinueOnError)
-
- boolVar := func(value *bool, name, usage string) {
- fset.Func(name, usage, func(s string) error {
- v, err := strconv.ParseBool(s)
- *value = v
- return err
- })
- }
-
- strVar := func(value *string, name, usage string) {
- fset.Func(name, usage, func(s string) error {
- *value = s
- return nil
- })
- }
-
- boolVar(&opts.NoMixedArgs, "no-mixed-args", "enforce not mixing key-value pairs and attributes (default true)")
- boolVar(&opts.KVOnly, "kv-only", "enforce using key-value pairs only (overrides -no-mixed-args, incompatible with -attr-only)")
- boolVar(&opts.AttrOnly, "attr-only", "enforce using attributes only (overrides -no-mixed-args, incompatible with -kv-only)")
- strVar(&opts.NoGlobal, "no-global", "enforce not using global loggers (all|default)")
- strVar(&opts.ContextOnly, "context-only", "enforce using methods that accept a context (all|scope)")
- boolVar(&opts.StaticMsg, "static-msg", "enforce using static messages")
- strVar(&opts.MsgStyle, "msg-style", "enforce message style (lowercased|capitalized)")
- boolVar(&opts.NoRawKeys, "no-raw-keys", "enforce using constants instead of raw keys")
- strVar(&opts.KeyNamingCase, "key-naming-case", "enforce key naming convention (snake|kebab|camel|pascal)")
- boolVar(&opts.ArgsOnSepLines, "args-on-sep-lines", "enforce putting arguments on separate lines")
-
- fset.Func("forbidden-keys", "enforce not using specific keys (comma-separated)", func(s string) error {
- opts.ForbiddenKeys = append(opts.ForbiddenKeys, strings.Split(s, ",")...)
- return nil
- })
-
- return *fset
-}
-
-var slogFuncs = map[string]struct {
- argsPos int
- skipContextCheck bool
-}{
- "log/slog.With": {argsPos: 0, skipContextCheck: true},
- "log/slog.Log": {argsPos: 3},
- "log/slog.LogAttrs": {argsPos: 3},
- "log/slog.Debug": {argsPos: 1},
- "log/slog.Info": {argsPos: 1},
- "log/slog.Warn": {argsPos: 1},
- "log/slog.Error": {argsPos: 1},
- "log/slog.DebugContext": {argsPos: 2},
- "log/slog.InfoContext": {argsPos: 2},
- "log/slog.WarnContext": {argsPos: 2},
- "log/slog.ErrorContext": {argsPos: 2},
- "(*log/slog.Logger).With": {argsPos: 0, skipContextCheck: true},
- "(*log/slog.Logger).Log": {argsPos: 3},
- "(*log/slog.Logger).LogAttrs": {argsPos: 3},
- "(*log/slog.Logger).Debug": {argsPos: 1},
- "(*log/slog.Logger).Info": {argsPos: 1},
- "(*log/slog.Logger).Warn": {argsPos: 1},
- "(*log/slog.Logger).Error": {argsPos: 1},
- "(*log/slog.Logger).DebugContext": {argsPos: 2},
- "(*log/slog.Logger).InfoContext": {argsPos: 2},
- "(*log/slog.Logger).WarnContext": {argsPos: 2},
- "(*log/slog.Logger).ErrorContext": {argsPos: 2},
-}
-
-var attrFuncs = map[string]struct{}{
- "log/slog.String": {},
- "log/slog.Int64": {},
- "log/slog.Int": {},
- "log/slog.Uint64": {},
- "log/slog.Float64": {},
- "log/slog.Bool": {},
- "log/slog.Time": {},
- "log/slog.Duration": {},
- "log/slog.Group": {},
- "log/slog.Any": {},
-}
-
-// message styles.
-const (
- styleLowercased = "lowercased"
- styleCapitalized = "capitalized"
-)
-
-// key naming conventions.
-const (
- snakeCase = "snake"
- kebabCase = "kebab"
- camelCase = "camel"
- pascalCase = "pascal"
-)
-
-func run(pass *analysis.Pass, opts *Options) {
- visitor := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- filter := []ast.Node{(*ast.CallExpr)(nil)}
-
- // WithStack is ~2x slower than Preorder, use it only when stack is needed.
- if opts.ContextOnly == "scope" {
- visitor.WithStack(filter, func(node ast.Node, _ bool, stack []ast.Node) bool {
- visit(pass, opts, node, stack)
- return false
- })
- return
- }
-
- visitor.Preorder(filter, func(node ast.Node) {
- visit(pass, opts, node, nil)
- })
-}
-
-// NOTE: stack is nil if Preorder is used.
-func visit(pass *analysis.Pass, opts *Options, node ast.Node, stack []ast.Node) {
- call := node.(*ast.CallExpr)
-
- fn := typeutil.StaticCallee(pass.TypesInfo, call)
- if fn == nil {
- return
- }
-
- name := fn.FullName()
-
- checkDiscardHandler(opts, pass, name, call)
-
- funcInfo, ok := slogFuncs[name]
- if !ok {
- return
- }
-
- switch opts.NoGlobal {
- case "all":
- if strings.HasPrefix(name, "log/slog.") || isGlobalLoggerUsed(pass.TypesInfo, call.Fun) {
- pass.Reportf(call.Pos(), "global logger should not be used")
- }
- case "default":
- if strings.HasPrefix(name, "log/slog.") {
- pass.Reportf(call.Pos(), "default logger should not be used")
- }
- }
-
- // NOTE: "With" functions are not checked for context.Context.
- if !funcInfo.skipContextCheck {
- switch opts.ContextOnly {
- case "all":
- typ := pass.TypesInfo.TypeOf(call.Args[0])
- if typ != nil && typ.String() != "context.Context" {
- pass.Reportf(call.Pos(), "%sContext should be used instead", fn.Name())
- }
- case "scope":
- typ := pass.TypesInfo.TypeOf(call.Args[0])
- if typ != nil && typ.String() != "context.Context" && isContextInScope(pass.TypesInfo, stack) {
- pass.Reportf(call.Pos(), "%sContext should be used instead", fn.Name())
- }
- }
- }
-
- msgPos := funcInfo.argsPos - 1
-
- // NOTE: "With" functions have no message argument and must be skipped.
- if opts.StaticMsg && msgPos >= 0 && !isStaticMsg(pass.TypesInfo, call.Args[msgPos]) {
- pass.Reportf(call.Args[msgPos].Pos(), "message should be a string literal or a constant")
- }
-
- if opts.MsgStyle != "" && msgPos >= 0 {
- if lit, ok := call.Args[msgPos].(*ast.BasicLit); ok && lit.Kind == token.STRING {
- value, err := strconv.Unquote(lit.Value)
- if err != nil {
- panic("unreachable") // string literals are always quoted.
- }
- if ok := isValidMsgStyle(value, opts.MsgStyle); !ok {
- pass.Reportf(call.Args[msgPos].Pos(), "message should be %s", opts.MsgStyle)
- }
- }
- }
-
- // NOTE: we assume that the arguments have already been validated by govet.
- args := call.Args[funcInfo.argsPos:]
- if len(args) == 0 {
- return
- }
-
- var keys []ast.Expr
- var attrs []ast.Expr
-
- for i := 0; i < len(args); i++ {
- typ := pass.TypesInfo.TypeOf(args[i])
- if typ == nil {
- continue
- }
- switch typ.String() {
- case "string":
- keys = append(keys, args[i])
- i++ // skip the value.
- case "log/slog.Attr":
- attrs = append(attrs, args[i])
- case "[]any", "[]log/slog.Attr":
- continue // the last argument may be an unpacked slice, skip it.
- }
- }
-
- switch {
- case opts.KVOnly && len(attrs) > 0:
- pass.Reportf(call.Pos(), "attributes should not be used")
- case opts.AttrOnly && len(keys) > 0:
- pass.Reportf(call.Pos(), "key-value pairs should not be used")
- case opts.NoMixedArgs && len(attrs) > 0 && len(keys) > 0:
- pass.Reportf(call.Pos(), "key-value pairs and attributes should not be mixed")
- }
-
- if opts.NoRawKeys {
- for key := range AllKeys(pass.TypesInfo, keys, attrs) {
- if sel, ok := key.(*ast.SelectorExpr); ok {
- key = sel.Sel // the key is defined in another package, e.g. pkg.ConstKey.
- }
-
- isConst := false
-
- if ident, ok := key.(*ast.Ident); ok {
- if obj := pass.TypesInfo.ObjectOf(ident); obj != nil {
- if _, ok := obj.(*types.Const); ok {
- isConst = true
- }
- }
- }
-
- if !isConst {
- pass.Reportf(key.Pos(), "raw keys should not be used")
- }
- }
- }
-
- checkKeysNaming(opts, pass, keys, attrs)
-
- if len(opts.ForbiddenKeys) > 0 {
- for key := range AllKeys(pass.TypesInfo, keys, attrs) {
- if name, ok := getKeyName(key); ok && slices.Contains(opts.ForbiddenKeys, name) {
- pass.Reportf(key.Pos(), "%q key is forbidden and should not be used", name)
- }
- }
- }
-
- if opts.ArgsOnSepLines && areArgsOnSameLine(pass.Fset, call, keys, attrs) {
- pass.Reportf(call.Pos(), "arguments should be put on separate lines")
- }
-}
-
-func checkKeysNaming(opts *Options, pass *analysis.Pass, keys, attrs []ast.Expr) {
- checkKeyNamingCase := func(caseFn func(string) string, caseName string) {
- for key := range AllKeys(pass.TypesInfo, keys, attrs) {
- name, ok := getKeyName(key)
- if !ok || name == caseFn(name) {
- return
- }
-
- pass.Report(analysis.Diagnostic{
- Pos: key.Pos(),
- Message: fmt.Sprintf("keys should be written in %s", caseName),
- SuggestedFixes: []analysis.SuggestedFix{{
- TextEdits: []analysis.TextEdit{{
- Pos: key.Pos(),
- End: key.End(),
- NewText: []byte(strconv.Quote(caseFn(name))),
- }},
- }},
- })
- }
- }
-
- switch opts.KeyNamingCase {
- case snakeCase:
- checkKeyNamingCase(strcase.ToSnake, "snake_case")
- case kebabCase:
- checkKeyNamingCase(strcase.ToKebab, "kebab-case")
- case camelCase:
- checkKeyNamingCase(strcase.ToCamel, "camelCase")
- case pascalCase:
- checkKeyNamingCase(strcase.ToPascal, "PascalCase")
- }
-}
-
-func checkDiscardHandler(opts *Options, pass *analysis.Pass, name string, call *ast.CallExpr) {
- if !opts.go124 {
- return
- }
-
- if name != "log/slog.NewTextHandler" && name != "log/slog.NewJSONHandler" {
- return
- }
-
- sel, ok := call.Args[0].(*ast.SelectorExpr)
- if !ok {
- return
- }
-
- obj := pass.TypesInfo.ObjectOf(sel.Sel)
- if obj == nil {
- return
- }
-
- if obj.Pkg().Name() != "io" || obj.Name() != "Discard" {
- return
- }
-
- pass.Report(analysis.Diagnostic{
- Pos: call.Pos(),
- Message: "use slog.DiscardHandler instead",
- SuggestedFixes: []analysis.SuggestedFix{{
- TextEdits: []analysis.TextEdit{{
- Pos: call.Pos(),
- End: call.End(),
- NewText: []byte("slog.DiscardHandler"),
- }},
- }},
- })
-}
-
-func isGlobalLoggerUsed(info *types.Info, call ast.Expr) bool {
- sel, ok := call.(*ast.SelectorExpr)
- if !ok {
- return false
- }
- ident, ok := sel.X.(*ast.Ident)
- if !ok {
- return false
- }
- obj := info.ObjectOf(ident)
- return obj.Parent() == obj.Pkg().Scope()
-}
-
-func isContextInScope(info *types.Info, stack []ast.Node) bool {
- for i := len(stack) - 1; i >= 0; i-- {
- decl, ok := stack[i].(*ast.FuncDecl)
- if !ok {
- continue
- }
- params := decl.Type.Params
- if len(params.List) == 0 || len(params.List[0].Names) == 0 {
- continue
- }
- typ := info.TypeOf(params.List[0].Names[0])
- if typ != nil && typ.String() == "context.Context" {
- return true
- }
- }
- return false
-}
-
-func isStaticMsg(info *types.Info, msg ast.Expr) bool {
- switch msg := msg.(type) {
- case *ast.BasicLit: // e.g. slog.Info("msg")
- return msg.Kind == token.STRING
- case *ast.Ident: // e.g. const msg = "msg"; slog.Info(msg)
- _, isConst := info.ObjectOf(msg).(*types.Const)
- return isConst
- case *ast.BinaryExpr: // e.g. slog.Info("x" + "y")
- if msg.Op != token.ADD {
- panic("unreachable") // only + can be applied to strings.
- }
- return isStaticMsg(info, msg.X) && isStaticMsg(info, msg.Y)
- default:
- return false
- }
-}
-
-func isValidMsgStyle(msg, style string) bool {
- runes := []rune(msg)
- if len(runes) < 2 {
- return true
- }
-
- first, second := runes[0], runes[1]
-
- switch style {
- case styleLowercased:
- if unicode.IsLower(first) {
- return true
- }
- if unicode.IsPunct(second) {
- return true // e.g. "U.S.A."
- }
- return unicode.IsUpper(second) // e.g. "HTTP"
- case styleCapitalized:
- if unicode.IsUpper(first) {
- return true
- }
- return unicode.IsUpper(second) // e.g. "iPhone"
- default:
- panic("unreachable")
- }
-}
-
-func AllKeys(info *types.Info, keys, attrs []ast.Expr) iter.Seq[ast.Expr] {
- return func(yield func(key ast.Expr) bool) {
- for _, key := range keys {
- if !yield(key) {
- return
- }
- }
-
- for _, attr := range attrs {
- switch attr := attr.(type) {
- case *ast.CallExpr: // e.g. slog.Int()
- callee := typeutil.StaticCallee(info, attr)
- if callee == nil {
- continue
- }
- if _, ok := attrFuncs[callee.FullName()]; !ok {
- continue
- }
-
- if !yield(attr.Args[0]) {
- return
- }
-
- case *ast.CompositeLit: // slog.Attr{}
- switch len(attr.Elts) {
- case 1: // slog.Attr{Key: ...} | slog.Attr{Value: ...}
- if kv := attr.Elts[0].(*ast.KeyValueExpr); kv.Key.(*ast.Ident).Name == "Key" {
- if !yield(kv.Value) {
- return
- }
- }
-
- case 2: // slog.Attr{Key: ..., Value: ...} | slog.Attr{Value: ..., Key: ...} | slog.Attr{..., ...}
- if kv, ok := attr.Elts[0].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
- if !yield(kv.Value) {
- return
- }
- } else if kv, ok := attr.Elts[1].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
- if !yield(kv.Value) {
- return
- }
- } else {
- if !yield(attr.Elts[0]) {
- return
- }
- }
- }
- }
- }
- }
-}
-
-func getKeyName(key ast.Expr) (string, bool) {
- if ident, ok := key.(*ast.Ident); ok {
- if ident.Obj == nil || ident.Obj.Decl == nil || ident.Obj.Kind != ast.Con {
- return "", false
- }
- if spec, ok := ident.Obj.Decl.(*ast.ValueSpec); ok && len(spec.Values) > 0 {
- // TODO: support len(spec.Values) > 1; e.g. const foo, bar = 1, 2
- key = spec.Values[0]
- }
- }
- if lit, ok := key.(*ast.BasicLit); ok && lit.Kind == token.STRING {
- value, err := strconv.Unquote(lit.Value)
- if err != nil {
- panic("unreachable") // string literals are always quoted.
- }
- return value, true
- }
- return "", false
-}
-
-func areArgsOnSameLine(fset *token.FileSet, call ast.Expr, keys, attrs []ast.Expr) bool {
- if len(keys)+len(attrs) <= 1 {
- return false // special case: slog.Info("msg", "key", "value") is ok.
- }
-
- args := slices.Concat([]ast.Expr{call}, keys, attrs)
-
- lines := make(map[int]struct{}, len(args))
- for _, arg := range args {
- line := fset.Position(arg.Pos()).Line
- if _, ok := lines[line]; ok {
- return true
- }
- lines[line] = struct{}{}
- }
-
- return false
-}
diff --git a/hack/tools/vendor/go-simpler.org/sloglint/utils.go b/hack/tools/vendor/go-simpler.org/sloglint/utils.go
new file mode 100644
index 00000000000..7e86e77266f
--- /dev/null
+++ b/hack/tools/vendor/go-simpler.org/sloglint/utils.go
@@ -0,0 +1,47 @@
+package sloglint
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+ "strconv"
+
+ "golang.org/x/tools/go/types/typeutil"
+)
+
+func typeName(info *types.Info, expr ast.Expr) string {
+ if typ := info.TypeOf(expr); typ != nil {
+ return typ.String()
+ }
+ return ""
+}
+
+func funcName(info *types.Info, call *ast.CallExpr) string {
+ if fn := typeutil.StaticCallee(info, call); fn != nil {
+ return fn.FullName()
+ }
+ return ""
+}
+
+func keyName(key ast.Expr) (string, bool) {
+ if ident, ok := key.(*ast.Ident); ok {
+ if ident.Obj == nil || ident.Obj.Decl == nil || ident.Obj.Kind != ast.Con {
+ return "", false
+ }
+ if spec, ok := ident.Obj.Decl.(*ast.ValueSpec); ok && len(spec.Values) > 0 {
+ key = spec.Values[0] // TODO: Support len(spec.Values) > 1; e.g. const foo, bar = 1, 2.
+ }
+ }
+
+ lit, ok := key.(*ast.BasicLit)
+ if !ok || lit.Kind != token.STRING {
+ return "", false
+ }
+
+ name, err := strconv.Unquote(lit.Value)
+ if err != nil {
+ panic("unreachable") // String literals are always quoted.
+ }
+
+ return name, true
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/.gitignore b/hack/tools/vendor/go.yaml.in/yaml/v4/.gitignore
new file mode 100644
index 00000000000..ae2880f5f24
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/.gitignore
@@ -0,0 +1,10 @@
+# Copyright 2025 The go-yaml Project Contributors
+# SPDX-License-Identifier: Apache-2.0
+
+/.cache/
+/.claude/
+/CLAUDE.md
+/yts/testdata/
+/go-yaml
+/note/
+/*.yaml
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/.typos.toml b/hack/tools/vendor/go.yaml.in/yaml/v4/.typos.toml
new file mode 100644
index 00000000000..59f93311583
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/.typos.toml
@@ -0,0 +1,33 @@
+# Copyright 2025 The go-yaml Project Contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This is the configuration file of typos (spell checker)
+# https://github.com/crate-ci/typos
+
+[files]
+# excluded file
+extend-exclude = [
+ "yts/testdata", # third-party test data
+]
+
+# setting for Go files configuration
+[type.go]
+extend-ignore-re = [
+ 'ba-dum-tss\W+', # this one can be found in test files
+ '"yYnNtTfFoO', # this one can be found in test files
+ 'ba\?r', # this one can be found in test files
+]
+
+[type.go.extend-words]
+# Here is a list of words we want to ignore in Go files
+typ = "typ" # commonly used abbreviation for "type" in Go as "type" is a reserved identifier
+
+# setting for YAML files configuration
+[type.yaml]
+extend-ignore-re = [
+ 'ba\?r', # this one can be found in test files
+]
+
+[default.extend-words]
+caf = "caf" # part of "café" shown as "caf\u00e9" in Unicode escape examples
+deprecat = "deprecat" # Used as part of a command in a docs/ file
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/CONTRIBUTING.md b/hack/tools/vendor/go.yaml.in/yaml/v4/CONTRIBUTING.md
new file mode 100644
index 00000000000..6aae23b5764
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/CONTRIBUTING.md
@@ -0,0 +1,210 @@
+Contributing to go-yaml
+=======================
+
+Thank you for your interest in contributing to go-yaml!
+
+This document provides guidelines and instructions for contributing to this
+project.
+
+
+## Code of Conduct
+
+By participating in this project, you agree to follow our Code of Conduct.
+
+We expect all contributors to:
+
+- Be respectful and inclusive
+- Use welcoming and inclusive language
+- Be collaborative and constructive
+- Focus on what is best for both the Go and YAML communities
+
+
+## How to Contribute
+
+
+### Reporting Issues
+
+Before submitting an issue, please:
+
+- Check if the issue already exists in our issue tracker
+- Use a clear and descriptive title
+- Provide detailed steps to reproduce the issue
+- Include relevant code samples and error messages
+- Specify your Go version and operating system
+- Use the `go-yaml` CLI tool described below
+
+
+### Using the `go-yaml` CLI Tool
+
+This tool can be used to inspect both the internal stages and final results of
+YAML processing with the go-yaml library.
+It should be used when reporting most bugs.
+
+The `go-yaml` CLI tool uses the `go.yaml.in/yaml/v4` library to decode and
+encode YAML.
+Decoding YAML is a multi-stage process that involves tokens, events, and nodes.
+The `go-yaml` CLI tool lets you see all of these intermediate stages of the
+decoding process.
+This is crucial for understanding what go-yaml is doing internally.
+
+The `go-yaml` CLI tool can be built with the `make go-yaml` command or installed
+with the `go install go.yaml.in/yaml/v4/cmd/go-yaml@latest` command.
+
+You can learn about all of its options with the `go-yaml -h` command.
+
+Here is an example of using it on a small piece of YAML:
+
+```bash
+./go-yaml -t <<< '
+foo: &a1 bar
+*a1: baz
+```
+
+
+### Coding Conventions
+
+- Follow standard Go coding conventions
+- Use `make fmt` to format your code
+- Write descriptive comments for non-obvious code
+- Add tests for your work
+- Keep line length to 80 characters
+- Use meaningful variable and function names
+- Start doc and comment sentences on a new line
+- Test your changes with the `go-yaml` CLI tool when working on parsing logic
+
+
+### Commit Conventions
+
+- No merge commits
+- Commit subject line should:
+ - Start with a capital letter
+ - Not end with a period
+ - Be no more than 50 characters
+
+
+### Pull Requests
+
+1. Fork the repository
+1. Create a new branch for your changes
+1. Make your changes following our coding conventions
+ - If you are not sure about the coding conventions, please ask
+ - Look at the existing code for examples
+1. Write clear commit messages
+1. Update tests and documentation
+1. Submit a pull request
+
+
+### Testing
+
+- Ensure all tests pass with `make test`
+- Add new tests for new functionality
+- Update existing tests when modifying functionality
+
+
+## Development Process
+
+- This project makes use of a GNU makefile (`GNUmakefile`) for many dev tasks
+- The makefile doesn't use your locally installed Go commands; it auto-installs
+ them, so that all results are deterministic
+- Fork and clone the repository
+- Make your changes
+- Run tests, linters and formatters
+ - `make fmt`
+ - `make tidy`
+ - `make lint`
+ - `make test`
+ - You can use `make check` to run all of the above
+- Submit a [Pull Request](https://github.com/yaml/go-yaml/pulls)
+
+
+### Using Your Own Go with the Makefile
+
+We ask that you always test with the makefile installed Go before committing,
+since it is deterministic and uses the exact same flow as the go-yaml CI.
+
+We also realize that many Go devs need to run their locally installed Go
+commands for their development environment, and might want to use them with
+the go-yaml makefile.
+
+If you need to use your own Go utils with the makefile, set `GO_YAML_PATH` to
+the directory(s) containing them (either by exporting it or passing it to
+`make`).
+
+Something like this:
+
+```bash
+export GO_YAML_PATH=$(dirname "$(command -v go)")
+make test
+# or
+make test GO_YAML_PATH=$(dirname "$(command -v go)")
+```
+
+**Note:** `GO-VERSION` and `GO_YAML_PATH` are mutually exclusive.
+When `GO_YAML_PATH` is set, the makefile uses your own Go environment and
+ignores any `GO-VERSION` setting.
+
+
+### Using the Makefile Environment as a Shell
+
+Sometimes you might want to run your own shell commands using the same binaries
+that the makefile installs.
+
+To get a subshell with this environment, run one of:
+
+```bash
+make shell
+make bash
+make zsh
+make shell GO-VERSION=1.23.4
+```
+
+
+
+## Makefile Targets
+
+The repository's makefile (`GNUmakefile`) provides a number of useful targets:
+
+- `make test` runs all tests including yaml-test-suite tests
+- `make test-unit` runs just the unit tests
+- `make test-internal` runs just the internal tests
+- `make test-yts` runs just the yaml-test-suite tests
+- `make test v=1 count=3` runs the tests with options
+- `make test GO-VERSION=1.23.4` runs the tests with a specific Go version
+- `make test GO_YAML_PATH=/path/to/go/bin` uses your own Go installation
+- `make shell` opens a shell with the project's dependencies set up
+- `make shell GO-VERSION=1.23.4` opens a shell with a specific Go version
+- `make fmt` runs `golangci-lint fmt ./...`
+- `make lint` runs `golangci-lint run`
+- `make tidy` runs `go mod tidy`
+- `make distclean` cleans the project completely
+
+
+## Getting Help
+
+If you need help, you can:
+- Open an [issue](https://github.com/yaml/go-yaml/issues) with your question
+- Start a [discussion](https://github.com/yaml/go-yaml/discussions)
+- Read through our [documentation](https://pkg.go.dev/go.yaml.in/yaml/v4)
+- Check the [migration guide](docs/v3-to-v4-migration.md) if upgrading from v3
+- Join our [Slack channel](https://cloud-native.slack.com/archives/C08PPAT8PS7)
+
+
+## We are a Work in Progress
+
+This project is very much a team effort.
+We are just getting things rolling and trying to get the foundations in place.
+There are lots of opinions and ideas about how to do things, even within the
+core team.
+
+Once our process is more mature, we will likely change the rules here.
+We'll make the new rules as a team.
+For now, please stick to the rules as they are.
+
+This project is focused on serving the needs of both the Go and YAML
+communities.
+Sometimes those needs can be in conflict, but we'll try to find common ground.
+
+
+## Thank You
+
+Thank you for contributing to go-yaml!
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/GNUmakefile b/hack/tools/vendor/go.yaml.in/yaml/v4/GNUmakefile
new file mode 100644
index 00000000000..fb46f814c73
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/GNUmakefile
@@ -0,0 +1,191 @@
+# Copyright 2025 The go-yaml Project Contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# Auto-install https://github.com/makeplus/makes at specific commit:
+MAKES := .cache/makes
+MAKES-LOCAL := .cache/local
+MAKES-COMMIT ?= 4e48a743c3652b88adc4a257398d895a801e6d11
+$(shell [ -d $(MAKES) ] || ( \
+ git clone -q https://github.com/makeplus/makes $(MAKES) && \
+ git -C $(MAKES) reset -q --hard $(MAKES-COMMIT)))
+ifneq ($(shell git -C $(MAKES) rev-parse HEAD), \
+ $(shell git -C $(MAKES) rev-parse $(MAKES-COMMIT)))
+$(error $(MAKES) is not at the correct commit: $(MAKES-COMMIT). \
+ Remove $(MAKES) and try again.)
+endif
+
+include $(MAKES)/init.mk
+include $(MAKES)/shellcheck.mk
+
+# Auto-install go unless GO_YAML_PATH is set:
+ifdef GO_YAML_PATH
+override export PATH := $(GO_YAML_PATH):$(PATH)
+else
+GO-VERSION ?= 1.25.5
+endif
+GO-VERSION-NEEDED := $(GO-VERSION)
+
+# yaml-test-suite info:
+YTS-URL ?= https://github.com/yaml/yaml-test-suite
+YTS-TAG ?= data-2022-01-17
+YTS-DIR := yts/testdata/$(YTS-TAG)
+
+CLI-BINARY := go-yaml
+
+# Pager for viewing documentation:
+PAGER ?= less -FRX
+
+# Setup and include go.mk and shell.mk:
+
+# We need to limit `find` to avoid dirs like `.cache/` and any git worktrees,
+# as this makes `make` operations very slow:
+REPO-DIRS := $(shell find * -maxdepth 0 -type d \
+ ! -exec test -f {}/.git \; -print)
+GO-FILES := $(shell find $(REPO-DIRS) -name '*.go')
+
+ifndef GO-VERSION-NEEDED
+GO-NO-DEP-GO := true
+endif
+
+include $(MAKES)/go.mk
+
+# Set this from the `make` command to override:
+GOLANGCI-LINT-VERSION ?= v2.8.0
+GOLANGCI-LINT-INSTALLER := \
+ https://github.com/golangci/golangci-lint/raw/main/install.sh
+GOLANGCI-LINT := $(LOCAL-BIN)/golangci-lint
+GOLANGCI-LINT-VERSIONED := $(GOLANGCI-LINT)-$(GOLANGCI-LINT-VERSION)
+
+SHELL-DEPS += $(GOLANGCI-LINT-VERSIONED)
+
+ifdef GO-VERSION-NEEDED
+GO-DEPS += $(GO)
+else
+SHELL-DEPS := $(filter-out $(GO),$(SHELL-DEPS))
+endif
+
+SHELL-NAME := makes go-yaml
+include $(MAKES)/clean.mk
+include $(MAKES)/shell.mk
+
+MAKES-CLEAN := $(CLI-BINARY) $(GOLANGCI-LINT)
+MAKES-REALCLEAN := $(dir $(YTS-DIR))
+
+SHELL-SCRIPTS = \
+ util/common.bash \
+ $(shell grep -rl '^.!/usr/bin/env bash' util | \
+ grep -v '\.sw')
+
+COVER-TESTS := \
+ . \
+ ./cmd/... \
+ ./internal/... \
+
+# v=1 for verbose
+MAKE := $(MAKE) --no-print-directory
+
+v ?=
+cover ?=
+fuzz ?=
+time ?= 60s
+opts ?=
+
+TEST-OPTS := \
+$(if $v, -v)\
+$(if $(cover), --cover)\
+$(if $(fuzz), --fuzz=FuzzEncodeFromJSON --fuzztime=$(time))\
+$(if $(opts), $(opts))\
+
+# Test rules:
+test: test-main test-internal test-cmd test-yts-all test-shell
+ @echo 'ALL TESTS PASS'
+
+check:
+ $(MAKE) fmt
+ $(MAKE) tidy
+ $(MAKE) lint
+ $(MAKE) test
+
+test-main: $(GO-DEPS)
+ go test .$(TEST-OPTS)
+ @echo 'ALL MAIN FILES PASS'
+
+test-cmd: $(GO-DEPS)
+ go test ./cmd/...$(TEST-OPTS)
+ @echo 'ALL CMD FILES PASS'
+
+test-internal: $(GO-DEPS)
+ go test ./internal/...$(TEST-OPTS)
+ @echo 'ALL INTERNAL FILES PASS'
+
+test-cover: $(GO-DEPS)
+ go test . $(COVER-TESTS) -vet=off --cover$(TEST-OPTS)
+
+test-yts: $(GO-DEPS) $(YTS-DIR)
+ go test ./yts$(TEST-OPTS)
+
+test-yts-all: $(GO-DEPS) $(YTS-DIR)
+ @echo 'Testing yaml-test-suite'
+ util/yaml-test-suite all
+
+test-yts-fail: $(GO-DEPS) $(YTS-DIR)
+ @echo 'Testing yaml-test-suite failures'
+ util/yaml-test-suite fail
+
+test-shell: $(SHELLCHECK)
+ shellcheck $(SHELL-SCRIPTS)
+ @echo 'ALL SHELL FILES PASS'
+
+test-count: $(GO-DEPS)
+ util/test-count
+
+yts-dir: $(YTS-DIR)
+
+get-test-data: $(YTS-DIR)
+
+# Install golangci-lint for GitHub Actions:
+golangci-lint-install: $(GOLANGCI-LINT)
+
+fmt: $(GOLANGCI-LINT-VERSIONED)
+ $< fmt ./...
+
+lint: $(GOLANGCI-LINT-VERSIONED)
+ $< run ./...
+
+tidy: $(GO-DEPS)
+ go mod tidy
+
+cli: $(CLI-BINARY)
+
+$(CLI-BINARY): $(GO)
+ go build -o $@ ./cmd/$@
+
+run-examples: $(GO)
+ @for dir in example/*/; do \
+ (set -x; go run "$${dir}main.go") || \
+ { echo "$$dir failed"; break; }; \
+ done
+
+# CLI documentation (go doc) - view in terminal:
+doc: $(GO-DEPS)
+ @go doc -all . | $(PAGER)
+
+# HTTP documentation server - opens browser:
+doc-http: $(GO-DEPS)
+ go doc -http -all
+
+# Setup rules:
+$(YTS-DIR):
+ git clone -q $(YTS-URL) $@
+ git -C $@ checkout -q $(YTS-TAG)
+
+# Downloads golangci-lint binary and moves to versioned path
+# (.cache/local/bin/golangci-lint-).
+$(GOLANGCI-LINT-VERSIONED): $(GO-DEPS)
+ curl -sSfL $(GOLANGCI-LINT-INSTALLER) | \
+ bash -s -- -b $(LOCAL-BIN) $(GOLANGCI-LINT-VERSION)
+ mv $(GOLANGCI-LINT) $@
+
+# Moves golangci-lint- to golangci-lint for CI requirement
+$(GOLANGCI-LINT): $(GOLANGCI-LINT-VERSIONED)
+ cp $< $@
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/LICENSE b/hack/tools/vendor/go.yaml.in/yaml/v4/LICENSE
new file mode 100644
index 00000000000..b0fa97112a6
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2025 - The go-yaml Project Contributors
+
+ 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.
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/NOTICE b/hack/tools/vendor/go.yaml.in/yaml/v4/NOTICE
new file mode 100644
index 00000000000..15093073b93
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/NOTICE
@@ -0,0 +1,21 @@
+The following files were ported to Go from C files of libyaml, and thus are
+still covered by their original MIT license, with the additional copyright
+starting in 2011 when the project was ported over:
+
+- internal/libyaml/api.go
+- internal/libyaml/emitter.go
+- internal/libyaml/parser.go
+- internal/libyaml/reader.go
+- internal/libyaml/scanner.go
+- internal/libyaml/writer.go
+- internal/libyaml/yaml.go
+- internal/libyaml/yamlprivate.go
+
+Copyright 2006-2010 Kirill Simonov
+https://opensource.org/license/mit
+
+All the remaining project files are covered by the Apache license:
+
+Copyright 2011-2019 Canonical Ltd
+Copyright 2025 The go-yaml Project Contributors
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/README.md b/hack/tools/vendor/go.yaml.in/yaml/v4/README.md
new file mode 100644
index 00000000000..aef27985a52
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/README.md
@@ -0,0 +1,266 @@
+go.yaml.in/yaml
+===============
+
+YAML Support for the Go Language
+
+
+## Introduction
+
+The `yaml` package enables [Go](https://go.dev/) programs to comfortably encode
+and decode [YAML](https://yaml.org/) values.
+
+It was originally developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a pure Go
+port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) C library to
+parse and generate YAML data quickly and reliably.
+
+
+## Project Status
+
+This project started as a fork of the extremely popular [go-yaml](
+https://github.com/go-yaml/yaml/)
+project, and is being maintained by the official [YAML organization](
+https://github.com/yaml/).
+
+The YAML team took over ongoing maintenance and development of the project after
+discussion with go-yaml's author, @niemeyer, following his decision to
+[label the project repository as "unmaintained"](
+https://github.com/go-yaml/yaml/blob/944c86a7d2/README.md) in April 2025.
+
+We have put together a team of dedicated maintainers including representatives
+of go-yaml's most important downstream projects.
+
+We will strive to earn the trust of the various go-yaml forks to switch back to
+this repository as their upstream.
+
+Please [contact us](https://cloud-native.slack.com/archives/C08PPAT8PS7) if you
+would like to contribute or be involved.
+
+
+### Version Intentions
+
+Versions `v1`, `v2`, and `v3` will remain as **frozen legacy**.
+They will receive **security-fixes only** so that existing consumers keep
+working without breaking changes.
+
+All ongoing work, including new features and routine bug-fixes, will happen in
+**`v4`**.
+If you’re starting a new project or upgrading an existing one, please use the
+`go.yaml.in/yaml/v4` import path.
+
+
+## Compatibility
+
+The `yaml` package supports most of YAML 1.2, but preserves some behavior from
+1.1 for backwards compatibility.
+
+Specifically, v3 of the `yaml` package:
+
+* Supports YAML 1.1 bools (`yes`/`no`, `on`/`off`) as long as they are being
+ decoded into a typed bool value.
+ Otherwise they behave as a string.
+ Booleans in YAML 1.2 are `true`/`false` only.
+* Supports octals encoded and decoded as `0777` per YAML 1.1, rather than
+ `0o777` as specified in YAML 1.2, because most parsers still use the old
+ format.
+ Octals in the `0o777` format are supported though, so new files work.
+* Does not support base-60 floats.
+ These are gone from YAML 1.2, and were actually never supported by this
+ package as it's clearly a poor choice.
+
+
+## Installation and Usage
+
+The import path for the package is *go.yaml.in/yaml/v4*.
+
+To install it, run:
+
+```bash
+go get go.yaml.in/yaml/v4
+```
+
+
+## API Documentation
+
+See:
+
+
+## API Stability
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](
+https://gopkg.in).
+
+
+## Example
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "go.yaml.in/yaml/v4"
+)
+
+var data = `
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+ A string
+ B struct {
+ RenamedC int `yaml:"c"`
+ D []int `yaml:",flow"`
+ }
+}
+
+func main() {
+ t := T{}
+
+ err := yaml.Unmarshal([]byte(data), &t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t:\n%v\n\n", t)
+
+ d, err := yaml.Marshal(&t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+ m := make(map[any]any)
+
+ err = yaml.Unmarshal([]byte(data), &m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m:\n%v\n\n", m)
+
+ d, err = yaml.Marshal(&m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+ c: 2
+ d:
+ - 3
+ - 4
+```
+
+
+## Development and Testing with `make`
+
+This project's makefile (`GNUmakefile`) is set up to support all of the
+project's testing, automation and development tasks in a completely
+deterministic way.
+
+Some `make` commands are:
+
+* `make test`
+* `make lint tidy`
+* `make test-shell`
+* `make test v=1`
+* `make test o='-foo --bar=baz'` # Add extra CLI options
+* `make test GO-VERSION=1.2.34`
+* `make test GO_YAML_PATH=/usr/local/go/bin`
+* `make shell` # Start a shell with the local `go` environment
+* `make shell GO-VERSION=1.2.34`
+* `make distclean` # Remove all generated files including `.cache/`
+
+
+### Dependency Auto-install
+
+By default, this makefile will not use your system's Go installation, or any
+other system tools that it needs.
+
+The only things from your system that it relies on are:
+* Linux or macOS
+* GNU `make` (3.81+)
+* `git`
+* `bash`
+* `curl`
+
+Everything else, including Go and Go utils, are installed and cached as they
+are needed by the makefile (under `.cache/`).
+
+> **Note**: Use `make shell` to get a subshell with the same environment that
+> the makefile set up for its commands.
+
+
+### Using your own Go
+
+If you want to use your own Go installation and utils, export `GO_YAML_PATH` to
+the directory containing the `go` binary.
+
+Use something like this:
+
+```
+export GO_YAML_PATH=$(dirname "$(command -v go)")
+make
+# or:
+make GO_YAML_PATH=$(dirname "$(command -v go)")
+```
+
+> **Note:** `GO-VERSION` and `GO_YAML_PATH` are mutually exclusive.
+> When `GO_YAML_PATH` is set, the Makefile uses your own Go installation and
+> ignores any `GO-VERSION` setting.
+
+
+## The `go-yaml` CLI Tool
+
+This repository includes a `go-yaml` CLI tool which can be used to understand
+the internal stages and final results of YAML processing with the go-yaml
+library.
+
+We strongly encourage you to show pertinent output from this command when
+reporting and discussing issues.
+
+```bash
+make go-yaml
+./go-yaml --help
+./go-yaml <<< '
+foo: &a1 bar
+*a1: baz
+' -n # Show value on decoded Node structs (formatted in YAML)
+```
+
+You can also install it with:
+
+```bash
+go install go.yaml.in/yaml/v4/cmd/go-yaml@latest
+```
+
+
+## License
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/doc.go b/hack/tools/vendor/go.yaml.in/yaml/v4/doc.go
new file mode 100644
index 00000000000..9e9ac7283bc
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/doc.go
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// Package yaml implements YAML 1.1/1.2 encoding and decoding for Go programs.
+//
+// # Quick Start
+//
+// For simple encoding and decoding, use [Unmarshal] and [Marshal]:
+//
+// type Config struct {
+// Name string `yaml:"name"`
+// Version string `yaml:"version"`
+// }
+//
+// // Decode YAML to Go struct
+// var config Config
+// err := yaml.Unmarshal(yamlData, &config)
+//
+// // Encode Go struct to YAML
+// data, err := yaml.Marshal(&config)
+//
+// For encoding/decoding with options, use [Load] and [Dump]:
+//
+// // Decode with strict field checking
+// err := yaml.Load(data, &config, yaml.WithKnownFields())
+//
+// // Encode with custom indent
+// data, err := yaml.Dump(&config, yaml.WithIndent(2))
+//
+// // Decode all documents from multi-document stream
+// var docs []Config
+// err := yaml.Load(multiDocYAML, &docs, yaml.WithAllDocuments())
+//
+// // Encode multiple documents as multi-document stream
+// docs := []Config{config1, config2}
+// data, err := yaml.Dump(docs, yaml.WithAllDocuments())
+//
+// # Streaming with Loader and Dumper
+//
+// For multi-document streams or when you need custom options, use [Loader] and [Dumper]:
+//
+// // Load multiple documents from a stream
+// loader, err := yaml.NewLoader(reader)
+// if err != nil {
+// log.Fatal(err)
+// }
+// for {
+// var doc any
+// if err := loader.Load(&doc); err == io.EOF {
+// break
+// } else if err != nil {
+// log.Fatal(err)
+// }
+// // Process document...
+// }
+//
+// // Dump multiple documents to a stream
+// dumper, err := yaml.NewDumper(writer, yaml.WithIndent(2))
+// if err != nil {
+// log.Fatal(err)
+// }
+// dumper.Dump(&doc1)
+// dumper.Dump(&doc2)
+// dumper.Close()
+//
+// # Options System
+//
+// Configure YAML processing behavior with functional options:
+//
+// yaml.NewDumper(w,
+// yaml.WithIndent(2), // Indentation spacing
+// yaml.WithCompactSeqIndent(), // Compact sequences (defaults to true)
+// yaml.WithLineWidth(80), // Line wrapping width
+// yaml.WithUnicode(false), // Escape non-ASCII (override default true)
+// yaml.WithKnownFields(), // Strict field checking (defaults to true)
+// yaml.WithUniqueKeys(), // Prevent duplicate keys (defaults to true)
+// yaml.WithSingleDocument(), // Single document mode
+// )
+//
+// Or use version-specific option presets for consistent formatting:
+//
+// yaml.NewDumper(w, yaml.V3)
+//
+// Options can be combined and later options override earlier ones:
+//
+// // Start with v3 defaults, then override indent
+// yaml.NewDumper(w,
+// yaml.V3,
+// yaml.WithIndent(4),
+// )
+//
+// Load options from YAML configuration files:
+//
+// opts, err := yaml.OptsYAML(configYAML)
+// dumper, err := yaml.NewDumper(w, opts)
+//
+// # YAML Compatibility
+//
+// This package supports most of YAML 1.2, but preserves some YAML 1.1
+// behavior for backward compatibility:
+//
+// - YAML 1.1 booleans (yes/no, on/off) are supported when decoding into
+// typed bool values, otherwise treated as strings
+// - Octals can use 0777 format (YAML 1.1) or 0o777 format (YAML 1.2)
+// - Base-60 floats are not supported (removed in YAML 1.2)
+//
+// # Version Defaults
+//
+// [NewLoader] and [NewDumper] use v4 defaults (2-space indentation, compact
+// sequences). The older [Marshal] and [Unmarshal] functions use v3 defaults
+// for backward compatibility. Use the options system to select different
+// version defaults if needed.
+package yaml
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/dumper.go b/hack/tools/vendor/go.yaml.in/yaml/v4/dumper.go
new file mode 100644
index 00000000000..3182892792f
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/dumper.go
@@ -0,0 +1,118 @@
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// This file contains the Dumper API for writing YAML documents.
+//
+// Primary functions:
+// - Dump: Encode value(s) to YAML (use WithAll for multi-doc)
+// - NewDumper: Create a streaming dumper to io.Writer
+
+package yaml
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "reflect"
+
+ "go.yaml.in/yaml/v4/internal/libyaml"
+)
+
+// Dump encodes a value to YAML with the given options.
+//
+// By default, Dump encodes a single value as a single YAML document.
+//
+// Use WithAllDocuments() to encode multiple values as a multi-document stream:
+//
+// docs := []Config{config1, config2, config3}
+// yaml.Dump(docs, yaml.WithAllDocuments())
+//
+// When WithAllDocuments is used, in must be a slice.
+// Each element is encoded as a separate YAML document with "---" separators.
+//
+// See [Marshal] for details about the conversion of Go values to YAML.
+func Dump(in any, opts ...Option) (out []byte, err error) {
+ defer handleErr(&err)
+
+ o, err := libyaml.ApplyOptions(opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ var buf bytes.Buffer
+ d, err := NewDumper(&buf, func(opts *libyaml.Options) error {
+ *opts = *o // Copy options
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ if o.AllDocuments {
+ // Multi-document mode: in must be a slice
+ inVal := reflect.ValueOf(in)
+ if inVal.Kind() != reflect.Slice {
+ return nil, &LoadErrors{Errors: []*libyaml.ConstructError{{
+ Err: errors.New("yaml: WithAllDocuments requires a slice input"),
+ }}}
+ }
+
+ // Dump each element as a separate document
+ for i := 0; i < inVal.Len(); i++ {
+ if err := d.Dump(inVal.Index(i).Interface()); err != nil {
+ return nil, err
+ }
+ }
+ } else {
+ // Single-document mode
+ if err := d.Dump(in); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := d.Close(); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// A Dumper writes YAML values to an output stream with configurable options.
+type Dumper struct {
+ encoder *libyaml.Representer
+ opts *libyaml.Options
+}
+
+// NewDumper returns a new Dumper that writes to w with the given options.
+//
+// The Dumper should be closed after use to flush all data to w.
+func NewDumper(w io.Writer, opts ...Option) (*Dumper, error) {
+ o, err := libyaml.ApplyOptions(opts...)
+ if err != nil {
+ return nil, err
+ }
+ return &Dumper{
+ encoder: libyaml.NewRepresenter(w, o),
+ opts: o,
+ }, nil
+}
+
+// Dump writes the YAML encoding of v to the stream.
+//
+// If multiple values are dumped to the stream, the second and subsequent
+// documents will be preceded with a "---" document separator.
+//
+// See the documentation for [Marshal] for details about the conversion of Go
+// values to YAML.
+func (d *Dumper) Dump(v any) (err error) {
+ defer handleErr(&err)
+ d.encoder.MarshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// Close closes the Dumper by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (d *Dumper) Close() (err error) {
+ defer handleErr(&err)
+ d.encoder.Finish()
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/README.md b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/README.md
new file mode 100644
index 00000000000..62dbeac3e44
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/README.md
@@ -0,0 +1,533 @@
+# internal/libyaml
+
+This package provides low-level YAML processing functionality through a 3-stage
+pipeline: Scanner → Parser → Emitter.
+It implements the libyaml C library functionality in Go.
+
+## Directory Overview
+
+The `internal/libyaml` package implements the core YAML processing stages:
+
+1. **Scanner** - Tokenizes YAML text into tokens
+2. **Parser** - Converts tokens into events following YAML grammar rules
+3. **Emitter** - Serializes events back into YAML text
+
+## File Organization
+
+### Main Source Files
+
+- **scanner.go** - YAML scanner/tokenizer implementation
+- **parser.go** - YAML parser (tokens → events)
+- **emitter.go** - YAML emitter (events → YAML output)
+- **api.go** - Public API for Parser and Emitter types
+- **yaml.go** - Core types and constants (Event, Token, enums)
+- **reader.go** - Input handling and encoding detection
+- **writer.go** - Output handling
+- **yamlprivate.go** - Internal types and helper functions
+
+### Test Files
+
+- **scanner_test.go** - Scanner tests
+- **parser_test.go** - Parser tests
+- **emitter_test.go** - Emitter tests
+- **api_test.go** - API tests
+- **yaml_test.go** - Utility function tests
+- **reader_test.go** - Reader tests
+- **writer_test.go** - Writer tests
+- **yamlprivate_test.go** - Character classification tests
+- **loader_test.go** - Data loader scalar resolution tests
+- **yamldatatest_test.go** - YAML test data loading framework
+- **yamldatatest_loader.go** - YAML test data loader with scalar type resolution (exported for reuse)
+
+### Test Data Files (in `testdata/`)
+
+- **scanner.yaml** - Scanner test cases
+- **parser.yaml** - Parser test cases
+- **emitter.yaml** - Emitter test cases
+- **api.yaml** - API test cases
+- **yaml.yaml** - Utility function test cases
+- **reader.yaml** - Reader test cases
+- **writer.yaml** - Writer test cases
+- **yamlprivate.yaml** - Character classification test cases
+- **loader.yaml** - Data loader scalar resolution test cases
+
+## Processing Pipeline
+
+### 1. Scanner (scanner.go)
+
+The scanner converts YAML text into tokens.
+
+**Input**: Raw YAML text (string or []byte)
+**Output**: Stream of tokens
+
+**Token types include**:
+- `SCALAR_TOKEN` - Plain, quoted, or block scalar values
+- `KEY_TOKEN`, `VALUE_TOKEN` - Mapping key/value indicators
+- `BLOCK_MAPPING_START_TOKEN`, `FLOW_MAPPING_START_TOKEN` - Mapping delimiters
+- `BLOCK_SEQUENCE_START_TOKEN`, `FLOW_SEQUENCE_START_TOKEN` - Sequence delimiters
+- `ANCHOR_TOKEN`, `ALIAS_TOKEN` - Anchor definitions and references
+- `TAG_TOKEN` - Type tags
+- `DOCUMENT_START_TOKEN`, `DOCUMENT_END_TOKEN` - Document boundaries
+
+**Responsibilities**:
+- Character encoding detection (UTF-8, UTF-16LE, UTF-16BE)
+- Line break normalization
+- Indentation tracking
+- Quote and escape sequence handling
+
+### 2. Parser (parser.go)
+
+The parser converts tokens into events following YAML grammar rules.
+
+**Input**: Stream of tokens from Scanner
+**Output**: Stream of events
+
+**Event types include**:
+- `STREAM_START_EVENT`, `STREAM_END_EVENT` - Stream boundaries
+- `DOCUMENT_START_EVENT`, `DOCUMENT_END_EVENT` - Document boundaries
+- `SCALAR_EVENT` - Scalar values
+- `MAPPING_START_EVENT`, `MAPPING_END_EVENT` - Mapping boundaries
+- `SEQUENCE_START_EVENT`, `SEQUENCE_END_EVENT` - Sequence boundaries
+- `ALIAS_EVENT` - Anchor references
+
+**Responsibilities**:
+- Implementing YAML grammar and validation
+- Managing document directives (%YAML, %TAG)
+- Resolving anchors and aliases
+- Tracking implicit vs explicit markers
+- Style preservation (plain, single-quoted, double-quoted, literal, folded)
+
+### 3. Emitter (emitter.go)
+
+The emitter converts events back into YAML text.
+
+**Input**: Stream of events
+**Output**: YAML text
+
+**Responsibilities**:
+- Style selection (plain/quoted scalars, block/flow collections)
+- Formatting control (canonical mode, indentation, line width)
+- Character encoding
+- Anchor and tag serialization
+- Document marker generation (---, ...)
+
+**Configuration options**:
+- `Canonical` - Emit in canonical YAML form
+- `Indent` - Indentation width (2-9 spaces)
+- `Width` - Line width (-1 for unlimited)
+- `Unicode` - Enable Unicode character output
+- `LineBreak` - Line break style (LN, CR, CRLN)
+
+## Testing Framework
+
+### Test Architecture
+
+The testing framework uses a data-driven approach:
+
+1. **Test data** is stored in YAML files in the `testdata/` directory
+2. **Test logic** is implemented in Go files (`*_test.go`)
+3. **One-to-one pairing**: Each `testdata/foo.yaml` has a corresponding `foo_test.go`
+
+**Benefits**:
+- Easy to add new test cases without writing Go code
+- Test data is human-readable and self-documenting
+- Test logic is reusable across many test cases
+- Test data is separated from test code for clarity
+- Tests can become a common suite for multiple YAML frameworks
+
+### Test Data Files
+
+Each YAML file contains test cases for a specific component:
+
+- **scanner.yaml** - Scanner/tokenization tests
+ - Token sequence verification
+ - Token property validation (value, style)
+ - Error detection
+
+- **parser.yaml** - Parser/event generation tests
+ - Event sequence verification
+ - Event property validation (anchor, tag, value, directives)
+ - Error detection
+
+- **emitter.yaml** - Emitter/serialization tests
+ - Event-to-YAML conversion
+ - Configuration options testing
+ - Roundtrip testing (parse → emit)
+ - Writer integration
+
+- **api.yaml** - API constructor and method tests
+ - Constructor validation
+ - Method behavior and state changes
+ - Panic conditions
+ - Cleanup verification
+
+- **yaml.yaml** - Utility function tests
+ - Enum String() methods
+ - Style accessor methods
+
+- **reader.yaml** - Reader/input handling tests
+ - Encoding detection (UTF-8, UTF-16LE, UTF-16BE)
+ - Buffer management
+ - Error handling
+
+- **writer.yaml** - Writer/output handling tests
+ - Buffer flushing
+ - Output handlers (string, io.Writer)
+ - Error conditions
+
+- **yamlprivate.yaml** - Character classification tests
+ - Character type predicates (isAlpha, isDigit, isHex, etc.)
+ - Character conversion functions (asDigit, asHex, width)
+ - Unicode handling
+
+- **loader.yaml** - Data loader scalar resolution tests
+ - Numeric type resolution (integers, floats)
+ - Boolean and null value handling
+ - String vs numeric type disambiguation
+ - Mixed-type collections
+
+### Test Framework Implementation
+
+The test framework is implemented in `yamldatatest_loader.go` and `yamldatatest_test.go`:
+
+**Core functions**:
+- `LoadYAML(data []byte) (interface{}, error)` - Parses YAML using libyaml parser with scalar type resolution (exported)
+- `UnmarshalStruct(target interface{}, data map[string]interface{}) error` - Populates structs (exported)
+- `LoadTestCases(filename string) ([]TestCase, error)` - Loads and parses test YAML files
+- `coerceScalar(value string) interface{}` - Resolves scalar strings to appropriate Go types (int, float64, bool, nil, string)
+
+**Core types**:
+- `TestCase` struct - Umbrella structure containing fields for all test types
+ - Uses `interface{}` for flexible field types
+ - Post-processing converts generic fields to specific types
+
+**Post-processing**:
+After loading, the framework processes test data:
+- Converts `Want` (interface{}) to `WantEvents`, `WantTokens`, or `WantSpecs` based on test type
+- Converts `Want` (interface{}) to `WantContains` (handles both scalar and sequence)
+- Converts `Checks` to field validation specifications
+
+### Test Types
+
+#### Scanner Tests
+
+**scan-tokens** - Verify token sequence
+
+```yaml
+- scan-tokens:
+ name: Simple scalar
+ yaml: |-
+ hello
+ want:
+ - STREAM_START_TOKEN
+ - SCALAR_TOKEN
+ - STREAM_END_TOKEN
+```
+
+**scan-tokens-detailed** - Verify token properties
+
+```yaml
+- scan-tokens-detailed:
+ name: Single quoted scalar
+ yaml: |-
+ 'hello world'
+ want:
+ - STREAM_START_TOKEN
+ - SCALAR_TOKEN:
+ style: SINGLE_QUOTED_SCALAR_STYLE
+ value: hello world
+ - STREAM_END_TOKEN
+```
+
+**scan-error** - Verify error detection
+
+```yaml
+- scan-error:
+ name: Invalid character
+ yaml: "\x01"
+```
+
+#### Parser Tests
+
+**parse-events** - Verify event sequence
+
+```yaml
+- parse-events:
+ name: Simple mapping
+ yaml: |
+ key: value
+ want:
+ - STREAM_START_EVENT
+ - DOCUMENT_START_EVENT
+ - MAPPING_START_EVENT
+ - SCALAR_EVENT
+ - SCALAR_EVENT
+ - MAPPING_END_EVENT
+ - DOCUMENT_END_EVENT
+ - STREAM_END_EVENT
+```
+
+**parse-events-detailed** - Verify event properties
+
+```yaml
+- parse-events-detailed:
+ name: Anchor and alias
+ yaml: |
+ - &anchor value
+ - *anchor
+ want:
+ - STREAM_START_EVENT
+ - DOCUMENT_START_EVENT
+ - SEQUENCE_START_EVENT
+ - SCALAR_EVENT:
+ anchor: anchor
+ value: value
+ - ALIAS_EVENT:
+ anchor: anchor
+ - SEQUENCE_END_EVENT
+ - DOCUMENT_END_EVENT
+ - STREAM_END_EVENT
+```
+
+**parse-error** - Verify error detection
+
+```yaml
+- parse-error:
+ name: Error state
+ yaml: |
+ key: : invalid
+```
+
+#### Emitter Tests
+
+**emit** - Emit events and verify output contains expected strings
+
+```yaml
+- emit:
+ name: Simple scalar
+ data:
+ - STREAM_START_EVENT:
+ encoding: UTF8_ENCODING
+ - DOCUMENT_START_EVENT:
+ implicit: true
+ - SCALAR_EVENT:
+ value: hello
+ implicit: true
+ style: PLAIN_SCALAR_STYLE
+ - DOCUMENT_END_EVENT:
+ implicit: true
+ - STREAM_END_EVENT
+ want: hello
+```
+
+**emit-config** - Emit with configuration
+
+```yaml
+- emit-config:
+ name: Custom indent
+ conf:
+ indent: 4
+ data:
+ - STREAM_START_EVENT:
+ encoding: UTF8_ENCODING
+ - DOCUMENT_START_EVENT:
+ implicit: true
+ - MAPPING_START_EVENT:
+ implicit: true
+ style: BLOCK_MAPPING_STYLE
+ # ... more events
+ want: key
+```
+
+**roundtrip** - Parse → emit, verify output
+
+```yaml
+- roundtrip:
+ name: Roundtrip
+ yaml: |
+ key: value
+ list:
+ - item1
+ - item2
+ want:
+ - key
+ - value
+ - item1
+```
+
+**emit-writer** - Emit to io.Writer
+
+```yaml
+- emit-writer:
+ name: Writer
+ data:
+ - STREAM_START_EVENT:
+ encoding: UTF8_ENCODING
+ # ... more events
+ want: test
+```
+
+#### API Tests
+
+**api-new** - Test constructors
+
+```yaml
+- api-new:
+ name: New parser
+ with: NewParser
+ test:
+ - nil: [raw-buffer, false]
+ - cap: [raw-buffer, 512]
+ - nil: [buffer, false]
+ - cap: [buffer, 1536]
+```
+
+**api-method** - Test methods and field state
+
+```yaml
+- api-method:
+ name: Parser set input string
+ with: NewParser
+ byte: true
+ call: [SetInputString, 'key: value']
+ test:
+ - eq: [input, 'key: value']
+ - eq: [input-pos, 0]
+ - nil: [read-handler, false]
+```
+
+**api-panic** - Test methods that should panic
+
+```yaml
+- api-panic:
+ name: Parser set input string twice
+ with: NewParser
+ byte: true
+ init: [SetInputString, first]
+ call: [SetInputString, second]
+ want: must set the input source only once
+```
+
+**api-delete** - Test cleanup
+
+```yaml
+- api-delete:
+ name: Parser delete
+ with: NewParser
+ byte: true
+ init: [SetInputString, test]
+ test:
+ - len: [input, 0]
+ - len: [buffer, 0]
+```
+
+**api-new-event** - Test event constructors
+
+```yaml
+- api-new-event:
+ name: New stream start event
+ call: [NewStreamStartEvent, UTF8_ENCODING]
+ test:
+ - eq: [Type, STREAM_START_EVENT]
+ - eq: [encoding, UTF8_ENCODING]
+```
+
+#### Utility Tests
+
+**enum-string** - Test String() methods of enums
+
+```yaml
+- enum-string:
+ name: Scalar style plain
+ enum: [ScalarStyle, PLAIN_SCALAR_STYLE]
+ want: Plain
+```
+
+**style-accessor** - Test style accessor methods
+
+```yaml
+- style-accessor:
+ name: Event scalar style
+ test: [ScalarStyle, DOUBLE_QUOTED_SCALAR_STYLE]
+```
+
+#### Loader Tests
+
+**scalar-resolution** - Test scalar type resolution
+
+```yaml
+- scalar-resolution:
+ name: Positive integer
+ yaml: "42"
+ want: 42
+
+- scalar-resolution:
+ name: Negative float
+ yaml: "-2.5"
+ want: -2.5
+```
+
+**Resolution order**:
+1. Boolean (true, false)
+2. Null (null keyword only)
+3. Hexadecimal integer (0x prefix)
+4. Float (contains .)
+5. Decimal integer
+6. String (fallback)
+
+### Common Keys in Test YAML Files
+
+Test cases use a **type-as-key** format where the test type is the map key:
+
+```yaml
+- test-type:
+ name: Test case name
+ # ... other fields
+```
+
+**Common fields**:
+- **name** - Test case name (title case convention)
+- **yaml** - Input YAML string to test
+- **want** - Expected result (format varies by test type)
+ - For api-panic: string containing expected panic message substring
+ - For scan-error/parse-error: boolean (defaults to true if omitted; set to false if no error expected)
+ - For enum-string: string representing expected String() output
+ - For other types: varies (may be sequence or scalar)
+- **data** - For emitter tests: list of event specifications to emit
+- **conf** - For emitter config tests: emitter configuration options
+- **with** - For API tests: constructor name (NewParser, NewEmitter)
+- **call** - For API tests: method call [MethodName, arg1, arg2, ...]
+- **init** - For API panic tests: setup method call before main method
+- **byte** - For API tests: boolean flag to convert string args to []byte
+- **test** - For API tests: list of field validation checks in format `operator: [field, value]` where operator is one of: nil, cap, len, eq, gte, len-gt.
+- **test** - For style-accessor tests: array of [Method, STYLE] where Method is the accessor method (e.g., ScalarStyle) and STYLE is the style constant (e.g., DOUBLE_QUOTED_SCALAR_STYLE).
+- **enum** - For enum tests: array of [Type, Value] where Type is the enum type (e.g., ScalarStyle) and Value is the constant (e.g., PLAIN_SCALAR_STYLE)
+
+**Note on scalar type resolution**: Unquoted scalar values in test data are automatically resolved to appropriate Go types (int, float64, bool, nil) by the `LoadYAML` function. Quoted scalars remain as strings.
+
+### Running Tests
+
+```bash
+# Run all tests in the package
+go test ./internal/libyaml
+
+# Run specific test file
+go test ./internal/libyaml -run TestScanner
+go test ./internal/libyaml -run TestParser
+go test ./internal/libyaml -run TestEmitter
+go test ./internal/libyaml -run TestAPI
+go test ./internal/libyaml -run TestYAML
+go test ./internal/libyaml -run TestLoader
+
+# Run specific test case (using subtest name)
+go test ./internal/libyaml -run TestScanner/Block_sequence
+go test ./internal/libyaml -run TestParser/Anchor_and_alias
+go test ./internal/libyaml -run TestEmitter/Flow_mapping
+go test ./internal/libyaml -run TestLoader/Scientific_notation_lowercase_e
+
+# Run with verbose output
+go test -v ./internal/libyaml
+
+# Run with coverage
+go test -cover ./internal/libyaml
+```
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/api.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/api.go
new file mode 100644
index 00000000000..f0807f5b069
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/api.go
@@ -0,0 +1,733 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// High-level API helpers for parser and emitter initialization and
+// configuration.
+// Provides convenience functions for token insertion and stream management.
+
+package libyaml
+
+import (
+ "io"
+)
+
+func (parser *Parser) insertToken(pos int, token *Token) {
+ // fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+ // Check if we can move the queue at the beginning of the buffer.
+ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+ if parser.tokens_head != len(parser.tokens) {
+ copy(parser.tokens, parser.tokens[parser.tokens_head:])
+ }
+ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+ parser.tokens_head = 0
+ }
+ parser.tokens = append(parser.tokens, *token)
+ if pos < 0 {
+ return
+ }
+ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+ parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// NewParser creates a new parser object.
+func NewParser() Parser {
+ return Parser{
+ raw_buffer: make([]byte, 0, input_raw_buffer_size),
+ buffer: make([]byte, 0, input_buffer_size),
+ }
+}
+
+// Delete a parser object.
+func (parser *Parser) Delete() {
+ *parser = Parser{}
+}
+
+// String read handler.
+func yamlStringReadHandler(parser *Parser, buffer []byte) (n int, err error) {
+ if parser.input_pos == len(parser.input) {
+ return 0, io.EOF
+ }
+ n = copy(buffer, parser.input[parser.input_pos:])
+ parser.input_pos += n
+ return n, nil
+}
+
+// Reader read handler.
+func yamlReaderReadHandler(parser *Parser, buffer []byte) (n int, err error) {
+ return parser.input_reader.Read(buffer)
+}
+
+// SetInputString sets a string input.
+func (parser *Parser) SetInputString(input []byte) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yamlStringReadHandler
+ parser.input = input
+ parser.input_pos = 0
+}
+
+// SetInputReader sets a file input.
+func (parser *Parser) SetInputReader(r io.Reader) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yamlReaderReadHandler
+ parser.input_reader = r
+}
+
+// SetEncoding sets the source encoding.
+func (parser *Parser) SetEncoding(encoding Encoding) {
+ if parser.encoding != ANY_ENCODING {
+ panic("must set the encoding only once")
+ }
+ parser.encoding = encoding
+}
+
+// GetPendingComments returns the parser's comment queue for CLI access.
+func (parser *Parser) GetPendingComments() []Comment {
+ return parser.comments
+}
+
+// GetCommentsHead returns the current position in the comment queue.
+func (parser *Parser) GetCommentsHead() int {
+ return parser.comments_head
+}
+
+// NewEmitter creates a new emitter object.
+func NewEmitter() Emitter {
+ return Emitter{
+ buffer: make([]byte, output_buffer_size),
+ states: make([]EmitterState, 0, initial_stack_size),
+ events: make([]Event, 0, initial_queue_size),
+ best_width: -1,
+ }
+}
+
+// Delete an emitter object.
+func (emitter *Emitter) Delete() {
+ *emitter = Emitter{}
+}
+
+// String write handler.
+func yamlStringWriteHandler(emitter *Emitter, buffer []byte) error {
+ *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+ return nil
+}
+
+// yamlWriterWriteHandler uses emitter.output_writer to write the
+// emitted text.
+func yamlWriterWriteHandler(emitter *Emitter, buffer []byte) error {
+ _, err := emitter.output_writer.Write(buffer)
+ return err
+}
+
+// SetOutputString sets a string output.
+func (emitter *Emitter) SetOutputString(output_buffer *[]byte) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yamlStringWriteHandler
+ emitter.output_buffer = output_buffer
+}
+
+// SetOutputWriter sets a file output.
+func (emitter *Emitter) SetOutputWriter(w io.Writer) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yamlWriterWriteHandler
+ emitter.output_writer = w
+}
+
+// SetEncoding sets the output encoding.
+func (emitter *Emitter) SetEncoding(encoding Encoding) {
+ if emitter.encoding != ANY_ENCODING {
+ panic("must set the output encoding only once")
+ }
+ emitter.encoding = encoding
+}
+
+// SetCanonical sets the canonical output style.
+func (emitter *Emitter) SetCanonical(canonical bool) {
+ emitter.canonical = canonical
+}
+
+// SetIndent sets the indentation increment.
+func (emitter *Emitter) SetIndent(indent int) {
+ if indent < 2 || indent > 9 {
+ indent = 2
+ }
+ emitter.BestIndent = indent
+}
+
+// SetWidth sets the preferred line width.
+func (emitter *Emitter) SetWidth(width int) {
+ if width < 0 {
+ width = -1
+ }
+ emitter.best_width = width
+}
+
+// SetUnicode sets if unescaped non-ASCII characters are allowed.
+func (emitter *Emitter) SetUnicode(unicode bool) {
+ emitter.unicode = unicode
+}
+
+// SetLineBreak sets the preferred line break character.
+func (emitter *Emitter) SetLineBreak(line_break LineBreak) {
+ emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+// assert(token); // Non-NULL token object expected.
+//
+// switch (token.type)
+// {
+// case YAML_TAG_DIRECTIVE_TOKEN:
+// yaml_free(token.data.tag_directive.handle);
+// yaml_free(token.data.tag_directive.prefix);
+// break;
+//
+// case YAML_ALIAS_TOKEN:
+// yaml_free(token.data.alias.value);
+// break;
+//
+// case YAML_ANCHOR_TOKEN:
+// yaml_free(token.data.anchor.value);
+// break;
+//
+// case YAML_TAG_TOKEN:
+// yaml_free(token.data.tag.handle);
+// yaml_free(token.data.tag.suffix);
+// break;
+//
+// case YAML_SCALAR_TOKEN:
+// yaml_free(token.data.scalar.value);
+// break;
+//
+// default:
+// break;
+// }
+//
+// memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+// yaml_char_t *end = start+length;
+// yaml_char_t *pointer = start;
+//
+// while (pointer < end) {
+// unsigned char octet;
+// unsigned int width;
+// unsigned int value;
+// size_t k;
+//
+// octet = pointer[0];
+// width = (octet & 0x80) == 0x00 ? 1 :
+// (octet & 0xE0) == 0xC0 ? 2 :
+// (octet & 0xF0) == 0xE0 ? 3 :
+// (octet & 0xF8) == 0xF0 ? 4 : 0;
+// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+// if (!width) return 0;
+// if (pointer+width > end) return 0;
+// for (k = 1; k < width; k ++) {
+// octet = pointer[k];
+// if ((octet & 0xC0) != 0x80) return 0;
+// value = (value << 6) + (octet & 0x3F);
+// }
+// if (!((width == 1) ||
+// (width == 2 && value >= 0x80) ||
+// (width == 3 && value >= 0x800) ||
+// (width == 4 && value >= 0x10000))) return 0;
+//
+// pointer += width;
+// }
+//
+// return 1;
+//}
+//
+
+// NewStreamStartEvent creates a new STREAM-START event.
+func NewStreamStartEvent(encoding Encoding) Event {
+ return Event{
+ Type: STREAM_START_EVENT,
+ encoding: encoding,
+ }
+}
+
+// NewStreamEndEvent creates a new STREAM-END event.
+func NewStreamEndEvent() Event {
+ return Event{
+ Type: STREAM_END_EVENT,
+ }
+}
+
+// NewDocumentStartEvent creates a new DOCUMENT-START event.
+func NewDocumentStartEvent(version_directive *VersionDirective, tag_directives []TagDirective, implicit bool) Event {
+ return Event{
+ Type: DOCUMENT_START_EVENT,
+ versionDirective: version_directive,
+ tagDirectives: tag_directives,
+ Implicit: implicit,
+ }
+}
+
+// NewDocumentEndEvent creates a new DOCUMENT-END event.
+func NewDocumentEndEvent(implicit bool) Event {
+ return Event{
+ Type: DOCUMENT_END_EVENT,
+ Implicit: implicit,
+ }
+}
+
+// NewAliasEvent creates a new ALIAS event.
+func NewAliasEvent(anchor []byte) Event {
+ return Event{
+ Type: ALIAS_EVENT,
+ Anchor: anchor,
+ }
+}
+
+// NewScalarEvent creates a new SCALAR event.
+func NewScalarEvent(anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style ScalarStyle) Event {
+ return Event{
+ Type: SCALAR_EVENT,
+ Anchor: anchor,
+ Tag: tag,
+ Value: value,
+ Implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ Style: Style(style),
+ }
+}
+
+// NewSequenceStartEvent creates a new SEQUENCE-START event.
+func NewSequenceStartEvent(anchor, tag []byte, implicit bool, style SequenceStyle) Event {
+ return Event{
+ Type: SEQUENCE_START_EVENT,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(style),
+ }
+}
+
+// NewSequenceEndEvent creates a new SEQUENCE-END event.
+func NewSequenceEndEvent() Event {
+ return Event{
+ Type: SEQUENCE_END_EVENT,
+ }
+}
+
+// NewMappingStartEvent creates a new MAPPING-START event.
+func NewMappingStartEvent(anchor, tag []byte, implicit bool, style MappingStyle) Event {
+ return Event{
+ Type: MAPPING_START_EVENT,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(style),
+ }
+}
+
+// NewMappingEndEvent creates a new MAPPING-END event.
+func NewMappingEndEvent() Event {
+ return Event{
+ Type: MAPPING_END_EVENT,
+ }
+}
+
+// Delete an event object.
+func (e *Event) Delete() {
+ *e = Event{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+// version_directive *yaml_version_directive_t,
+// tag_directives_start *yaml_tag_directive_t,
+// tag_directives_end *yaml_tag_directive_t,
+// start_implicit int, end_implicit int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// struct {
+// start *yaml_node_t
+// end *yaml_node_t
+// top *yaml_node_t
+// } nodes = { NULL, NULL, NULL }
+// version_directive_copy *yaml_version_directive_t = NULL
+// struct {
+// start *yaml_tag_directive_t
+// end *yaml_tag_directive_t
+// top *yaml_tag_directive_t
+// } tag_directives_copy = { NULL, NULL, NULL }
+// value yaml_tag_directive_t = { NULL, NULL }
+// mark yaml_mark_t = { 0, 0, 0 }
+//
+// assert(document) // Non-NULL document object is expected.
+// assert((tag_directives_start && tag_directives_end) ||
+// (tag_directives_start == tag_directives_end))
+// // Valid tag directives are expected.
+//
+// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+// if (version_directive) {
+// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+// if (!version_directive_copy) goto error
+// version_directive_copy.major = version_directive.major
+// version_directive_copy.minor = version_directive.minor
+// }
+//
+// if (tag_directives_start != tag_directives_end) {
+// tag_directive *yaml_tag_directive_t
+// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+// goto error
+// for (tag_directive = tag_directives_start
+// tag_directive != tag_directives_end; tag_directive ++) {
+// assert(tag_directive.handle)
+// assert(tag_directive.prefix)
+// if (!yaml_check_utf8(tag_directive.handle,
+// strlen((char *)tag_directive.handle)))
+// goto error
+// if (!yaml_check_utf8(tag_directive.prefix,
+// strlen((char *)tag_directive.prefix)))
+// goto error
+// value.handle = yaml_strdup(tag_directive.handle)
+// value.prefix = yaml_strdup(tag_directive.prefix)
+// if (!value.handle || !value.prefix) goto error
+// if (!PUSH(&context, tag_directives_copy, value))
+// goto error
+// value.handle = NULL
+// value.prefix = NULL
+// }
+// }
+//
+// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+// tag_directives_copy.start, tag_directives_copy.top,
+// start_implicit, end_implicit, mark, mark)
+//
+// return 1
+//
+//error:
+// STACK_DEL(&context, nodes)
+// yaml_free(version_directive_copy)
+// while (!STACK_EMPTY(&context, tag_directives_copy)) {
+// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+// }
+// STACK_DEL(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+//
+// return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// tag_directive *yaml_tag_directive_t
+//
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// while (!STACK_EMPTY(&context, document.nodes)) {
+// node yaml_node_t = POP(&context, document.nodes)
+// yaml_free(node.tag)
+// switch (node.type) {
+// case YAML_SCALAR_NODE:
+// yaml_free(node.data.scalar.value)
+// break
+// case YAML_SEQUENCE_NODE:
+// STACK_DEL(&context, node.data.sequence.items)
+// break
+// case YAML_MAPPING_NODE:
+// STACK_DEL(&context, node.data.mapping.pairs)
+// break
+// default:
+// assert(0) // Should not happen.
+// }
+// }
+// STACK_DEL(&context, document.nodes)
+//
+// yaml_free(document.version_directive)
+// for (tag_directive = document.tag_directives.start
+// tag_directive != document.tag_directives.end
+// tag_directive++) {
+// yaml_free(tag_directive.handle)
+// yaml_free(tag_directive.prefix)
+// }
+// yaml_free(document.tag_directives.start)
+//
+// memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+// return document.nodes.start + index - 1
+// }
+// return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (document.nodes.top != document.nodes.start) {
+// return document.nodes.start
+// }
+// return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+// tag *yaml_char_t, value *yaml_char_t, length int,
+// style yaml_scalar_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// value_copy *yaml_char_t = NULL
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+// assert(value) // Non-NULL value is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (length < 0) {
+// length = strlen((char *)value)
+// }
+//
+// if (!yaml_check_utf8(value, length)) goto error
+// value_copy = yaml_malloc(length+1)
+// if (!value_copy) goto error
+// memcpy(value_copy, value, length)
+// value_copy[length] = '\0'
+//
+// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// yaml_free(tag_copy)
+// yaml_free(value_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_item_t
+// end *yaml_node_item_t
+// top *yaml_node_item_t
+// } items = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, items)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_pair_t
+// end *yaml_node_pair_t
+// top *yaml_node_pair_t
+// } pairs = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, pairs)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+// sequence int, item int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// assert(document) // Non-NULL document is required.
+// assert(sequence > 0
+// && document.nodes.start + sequence <= document.nodes.top)
+// // Valid sequence id is required.
+// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+// // A sequence node is required.
+// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+// // Valid item id is required.
+//
+// if (!PUSH(&context,
+// document.nodes.start[sequence-1].data.sequence.items, item))
+// return 0
+//
+// return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+// mapping int, key int, value int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// pair yaml_node_pair_t
+//
+// assert(document) // Non-NULL document is required.
+// assert(mapping > 0
+// && document.nodes.start + mapping <= document.nodes.top)
+// // Valid mapping id is required.
+// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+// // A mapping node is required.
+// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+// // Valid key id is required.
+// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+// // Valid value id is required.
+//
+// pair.key = key
+// pair.value = value
+//
+// if (!PUSH(&context,
+// document.nodes.start[mapping-1].data.mapping.pairs, pair))
+// return 0
+//
+// return 1
+//}
+//
+//
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/composer.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/composer.go
new file mode 100644
index 00000000000..57dd7f1e6ed
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/composer.go
@@ -0,0 +1,362 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Composer stage: Builds a node tree from a libyaml event stream.
+// Handles document structure, anchors, and comment attachment.
+
+package libyaml
+
+import (
+ "fmt"
+ "io"
+)
+
+// Composer produces a node tree out of a libyaml event stream.
+type Composer struct {
+ Parser Parser
+ event Event
+ doc *Node
+ anchors map[string]*Node
+ doneInit bool
+ Textless bool
+ streamNodes bool // enable stream node emission
+ returnStream bool // flag to return stream node next
+ atStreamEnd bool // at stream end
+ encoding Encoding // stream encoding from STREAM_START
+}
+
+// NewComposer creates a new composer from a byte slice.
+func NewComposer(b []byte) *Composer {
+ p := Composer{
+ Parser: NewParser(),
+ }
+ if len(b) == 0 {
+ b = []byte{'\n'}
+ }
+ p.Parser.SetInputString(b)
+ return &p
+}
+
+// NewComposerFromReader creates a new composer from an io.Reader.
+func NewComposerFromReader(r io.Reader) *Composer {
+ p := Composer{
+ Parser: NewParser(),
+ }
+ p.Parser.SetInputReader(r)
+ return &p
+}
+
+func (c *Composer) init() {
+ if c.doneInit {
+ return
+ }
+ c.anchors = make(map[string]*Node)
+ // Peek to get the encoding from STREAM_START_EVENT
+ if c.peek() == STREAM_START_EVENT {
+ c.encoding = c.event.GetEncoding()
+ }
+ c.expect(STREAM_START_EVENT)
+ c.doneInit = true
+
+ // If stream nodes are enabled, prepare to return the first stream node
+ if c.streamNodes {
+ c.returnStream = true
+ }
+}
+
+func (c *Composer) Destroy() {
+ if c.event.Type != NO_EVENT {
+ c.event.Delete()
+ }
+ c.Parser.Delete()
+}
+
+// SetStreamNodes enables or disables stream node emission.
+func (c *Composer) SetStreamNodes(enable bool) {
+ c.streamNodes = enable
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (c *Composer) expect(e EventType) {
+ if c.event.Type == NO_EVENT {
+ if err := c.Parser.Parse(&c.event); err != nil {
+ c.fail(err)
+ }
+ }
+ if c.event.Type == STREAM_END_EVENT {
+ failf("attempted to go past the end of stream; corrupted value?")
+ }
+ if c.event.Type != e {
+ c.fail(fmt.Errorf("expected %s event but got %s", e, c.event.Type))
+ }
+ c.event.Delete()
+ c.event.Type = NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into c.event and returns the event type.
+func (c *Composer) peek() EventType {
+ if c.event.Type != NO_EVENT {
+ return c.event.Type
+ }
+ // It's curious choice from the underlying API to generally return a
+ // positive result on success, but on this case return true in an error
+ // scenario. This was the source of bugs in the past (issue #666).
+ if err := c.Parser.Parse(&c.event); err != nil {
+ c.fail(err)
+ }
+ return c.event.Type
+}
+
+func (c *Composer) fail(err error) {
+ Fail(err)
+}
+
+func (c *Composer) anchor(n *Node, anchor []byte) {
+ if anchor != nil {
+ n.Anchor = string(anchor)
+ c.anchors[n.Anchor] = n
+ }
+}
+
+// Parse parses the next YAML node from the event stream.
+func (c *Composer) Parse() *Node {
+ c.init()
+
+ // Handle stream nodes if enabled
+ if c.streamNodes {
+ // Check for stream end first
+ if c.peek() == STREAM_END_EVENT {
+ // If we haven't returned the final stream node yet, return it now
+ if !c.atStreamEnd {
+ c.atStreamEnd = true
+ return c.createStreamNode()
+ }
+ // Already returned final stream node
+ return nil
+ }
+
+ // Check if we should return a stream node before the next document
+ if c.returnStream {
+ c.returnStream = false
+ n := c.createStreamNode()
+ // Capture directives from upcoming document
+ c.captureDirectives(n)
+ return n
+ }
+ }
+
+ switch c.peek() {
+ case SCALAR_EVENT:
+ return c.scalar()
+ case ALIAS_EVENT:
+ return c.alias()
+ case MAPPING_START_EVENT:
+ return c.mapping()
+ case SEQUENCE_START_EVENT:
+ return c.sequence()
+ case DOCUMENT_START_EVENT:
+ return c.document()
+ case STREAM_END_EVENT:
+ // Happens when attempting to decode an empty buffer (when not using stream nodes).
+ return nil
+ case TAIL_COMMENT_EVENT:
+ panic("internal error: unexpected tail comment event (please report)")
+ default:
+ panic("internal error: attempted to parse unknown event (please report): " + c.event.Type.String())
+ }
+}
+
+func (c *Composer) node(kind Kind, defaultTag, tag, value string) *Node {
+ var style Style
+ if tag != "" && tag != "!" {
+ // Normalize tag to short form (e.g., tag:yaml.org,2002:str -> !!str)
+ tag = shortTag(tag)
+ style = TaggedStyle
+ } else if defaultTag != "" {
+ tag = defaultTag
+ } else if kind == ScalarNode {
+ // Delegate to resolver to determine tag from value
+ tag, _ = resolve("", value)
+ }
+ n := &Node{
+ Kind: kind,
+ Tag: tag,
+ Value: value,
+ Style: style,
+ }
+ if !c.Textless {
+ n.Line = c.event.StartMark.Line + 1
+ n.Column = c.event.StartMark.Column + 1
+ n.HeadComment = string(c.event.HeadComment)
+ n.LineComment = string(c.event.LineComment)
+ n.FootComment = string(c.event.FootComment)
+ }
+ return n
+}
+
+func (c *Composer) parseChild(parent *Node) *Node {
+ child := c.Parse()
+ parent.Content = append(parent.Content, child)
+ return child
+}
+
+func (c *Composer) document() *Node {
+ n := c.node(DocumentNode, "", "", "")
+ c.doc = n
+ c.expect(DOCUMENT_START_EVENT)
+ c.parseChild(n)
+ if c.peek() == DOCUMENT_END_EVENT {
+ n.FootComment = string(c.event.FootComment)
+ }
+ c.expect(DOCUMENT_END_EVENT)
+
+ // If stream nodes enabled, prepare to return a stream node next
+ if c.streamNodes {
+ c.returnStream = true
+ }
+
+ return n
+}
+
+func (c *Composer) createStreamNode() *Node {
+ n := &Node{
+ Kind: StreamNode,
+ Encoding: c.encoding,
+ }
+ if !c.Textless && c.event.Type != NO_EVENT {
+ n.Line = c.event.StartMark.Line + 1
+ n.Column = c.event.StartMark.Column + 1
+ }
+ return n
+}
+
+// captureDirectives captures version and tag directives from upcoming DOCUMENT_START.
+func (c *Composer) captureDirectives(n *Node) {
+ if c.peek() == DOCUMENT_START_EVENT {
+ if vd := c.event.GetVersionDirective(); vd != nil {
+ n.Version = &StreamVersionDirective{
+ Major: vd.Major(),
+ Minor: vd.Minor(),
+ }
+ }
+ if tds := c.event.GetTagDirectives(); len(tds) > 0 {
+ n.TagDirectives = make([]StreamTagDirective, len(tds))
+ for i, td := range tds {
+ n.TagDirectives[i] = StreamTagDirective{
+ Handle: td.GetHandle(),
+ Prefix: td.GetPrefix(),
+ }
+ }
+ }
+ }
+}
+
+func (c *Composer) alias() *Node {
+ n := c.node(AliasNode, "", "", string(c.event.Anchor))
+ n.Alias = c.anchors[n.Value]
+ if n.Alias == nil {
+ msg := fmt.Sprintf("unknown anchor '%s' referenced", n.Value)
+ Fail(&ParserError{
+ Message: msg,
+ Mark: Mark{
+ Line: n.Line,
+ Column: n.Column,
+ },
+ })
+ }
+ c.expect(ALIAS_EVENT)
+ return n
+}
+
+func (c *Composer) scalar() *Node {
+ parsedStyle := c.event.ScalarStyle()
+ var nodeStyle Style
+ switch {
+ case parsedStyle&DOUBLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = DoubleQuotedStyle
+ case parsedStyle&SINGLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = SingleQuotedStyle
+ case parsedStyle&LITERAL_SCALAR_STYLE != 0:
+ nodeStyle = LiteralStyle
+ case parsedStyle&FOLDED_SCALAR_STYLE != 0:
+ nodeStyle = FoldedStyle
+ }
+ nodeValue := string(c.event.Value)
+ nodeTag := string(c.event.Tag)
+ var defaultTag string
+ if nodeStyle != 0 {
+ defaultTag = strTag
+ }
+ n := c.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+ n.Style |= nodeStyle
+ c.anchor(n, c.event.Anchor)
+ c.expect(SCALAR_EVENT)
+ return n
+}
+
+func (c *Composer) sequence() *Node {
+ n := c.node(SequenceNode, seqTag, string(c.event.Tag), "")
+ if c.event.SequenceStyle()&FLOW_SEQUENCE_STYLE != 0 {
+ n.Style |= FlowStyle
+ }
+ c.anchor(n, c.event.Anchor)
+ c.expect(SEQUENCE_START_EVENT)
+ for c.peek() != SEQUENCE_END_EVENT {
+ c.parseChild(n)
+ }
+ n.LineComment = string(c.event.LineComment)
+ n.FootComment = string(c.event.FootComment)
+ c.expect(SEQUENCE_END_EVENT)
+ return n
+}
+
+func (c *Composer) mapping() *Node {
+ n := c.node(MappingNode, mapTag, string(c.event.Tag), "")
+ block := true
+ if c.event.MappingStyle()&FLOW_MAPPING_STYLE != 0 {
+ block = false
+ n.Style |= FlowStyle
+ }
+ c.anchor(n, c.event.Anchor)
+ c.expect(MAPPING_START_EVENT)
+ for c.peek() != MAPPING_END_EVENT {
+ k := c.parseChild(n)
+ if block && k.FootComment != "" {
+ // Must be a foot comment for the prior value when being dedented.
+ if len(n.Content) > 2 {
+ n.Content[len(n.Content)-3].FootComment = k.FootComment
+ k.FootComment = ""
+ }
+ }
+ v := c.parseChild(n)
+ if k.FootComment == "" && v.FootComment != "" {
+ k.FootComment = v.FootComment
+ v.FootComment = ""
+ }
+ if c.peek() == TAIL_COMMENT_EVENT {
+ if k.FootComment == "" {
+ k.FootComment = string(c.event.FootComment)
+ }
+ c.expect(TAIL_COMMENT_EVENT)
+ }
+ }
+ n.LineComment = string(c.event.LineComment)
+ n.FootComment = string(c.event.FootComment)
+ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+ n.Content[len(n.Content)-2].FootComment = n.FootComment
+ n.FootComment = ""
+ }
+ c.expect(MAPPING_END_EVENT)
+ return n
+}
+
+func Fail(err error) {
+ panic(&YAMLError{err})
+}
+
+func failf(format string, args ...any) {
+ panic(&YAMLError{fmt.Errorf("yaml: "+format, args...)})
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/constructor.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/constructor.go
new file mode 100644
index 00000000000..66f209a5985
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/constructor.go
@@ -0,0 +1,1187 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Constructor stage: Converts YAML nodes to Go values.
+// Handles type resolution, custom unmarshalers, and struct field mapping.
+
+package libyaml
+
+import (
+ "encoding"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "math"
+ "reflect"
+ "strings"
+ "sync"
+ "time"
+)
+
+// --------------------------------------------------------------------------
+// Interfaces and types needed by constructor
+
+// constructor interface may be implemented by types to customize their
+// behavior when being constructed from a YAML document.
+type constructor interface {
+ UnmarshalYAML(value *Node) error
+}
+
+type obsoleteConstructor interface {
+ UnmarshalYAML(construct func(any) error) error
+}
+
+// Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document.
+type Marshaler interface {
+ MarshalYAML() (any, error)
+}
+
+// IsZeroer is used to check whether an object is zero to determine whether
+// it should be omitted when marshaling with the ,omitempty flag. One notable
+// implementation is time.Time.
+type IsZeroer interface {
+ IsZero() bool
+}
+
+// handleErr recovers from panics caused by yaml errors
+func handleErr(err *error) {
+ if v := recover(); v != nil {
+ if e, ok := v.(*YAMLError); ok {
+ *err = e.Err
+ } else {
+ panic(v)
+ }
+ }
+}
+
+// --------------------------------------------------------------------------
+// Struct field information
+
+type structInfo struct {
+ FieldsMap map[string]fieldInfo
+ FieldsList []fieldInfo
+
+ // InlineMap is the number of the field in the struct that
+ // contains an ,inline map, or -1 if there's none.
+ InlineMap int
+
+ // InlineConstructors holds indexes to inlined fields that
+ // contain constructor values.
+ InlineConstructors [][]int
+}
+
+type fieldInfo struct {
+ Key string
+ Num int
+ OmitEmpty bool
+ Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
+
+ // Inline holds the field index if the field is part of an inlined struct.
+ Inline []int
+}
+
+var (
+ structMap = make(map[reflect.Type]*structInfo)
+ fieldMapMutex sync.RWMutex
+ constructorType reflect.Type
+)
+
+func init() {
+ var v constructor
+ constructorType = reflect.ValueOf(&v).Elem().Type()
+}
+
+// hasConstructYAMLMethod checks if a type has an UnmarshalYAML method
+// that looks like it implements yaml.Unmarshaler (from root package).
+// This is needed because we can't directly check for the interface type
+// since it's in a different package that we can't import.
+func hasConstructYAMLMethod(t reflect.Type) bool {
+ method, found := t.MethodByName("UnmarshalYAML")
+ if !found {
+ return false
+ }
+
+ // Check signature: func(*T) UnmarshalYAML(*Node) error
+ mtype := method.Type
+ if mtype.NumIn() != 2 || mtype.NumOut() != 1 {
+ return false
+ }
+
+ // First param is receiver (already checked by MethodByName)
+ // Second param should be a pointer to a Node-like struct
+ paramType := mtype.In(1)
+ if paramType.Kind() != reflect.Ptr {
+ return false
+ }
+
+ elemType := paramType.Elem()
+ if elemType.Kind() != reflect.Struct || elemType.Name() != "Node" {
+ return false
+ }
+
+ // Return type should be error
+ retType := mtype.Out(0)
+ if retType.Kind() != reflect.Interface || retType.Name() != "error" {
+ return false
+ }
+
+ return true
+}
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+ fieldMapMutex.RLock()
+ sinfo, found := structMap[st]
+ fieldMapMutex.RUnlock()
+ if found {
+ return sinfo, nil
+ }
+
+ n := st.NumField()
+ fieldsMap := make(map[string]fieldInfo)
+ fieldsList := make([]fieldInfo, 0, n)
+ inlineMap := -1
+ inlineConstructors := [][]int(nil)
+ for i := 0; i != n; i++ {
+ field := st.Field(i)
+ if field.PkgPath != "" && !field.Anonymous {
+ continue // Private field
+ }
+
+ info := fieldInfo{Num: i}
+
+ tag := field.Tag.Get("yaml")
+ if tag == "" && !strings.Contains(string(field.Tag), ":") {
+ tag = string(field.Tag)
+ }
+ if tag == "-" {
+ continue
+ }
+
+ inline := false
+ fields := strings.Split(tag, ",")
+ if len(fields) > 1 {
+ for _, flag := range fields[1:] {
+ switch flag {
+ case "omitempty":
+ info.OmitEmpty = true
+ case "flow":
+ info.Flow = true
+ case "inline":
+ inline = true
+ default:
+ return nil, fmt.Errorf("unsupported flag %q in tag %q of type %s", flag, tag, st)
+ }
+ }
+ tag = fields[0]
+ }
+
+ if inline {
+ switch field.Type.Kind() {
+ case reflect.Map:
+ if inlineMap >= 0 {
+ return nil, errors.New("multiple ,inline maps in struct " + st.String())
+ }
+ if field.Type.Key() != reflect.TypeOf("") {
+ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
+ }
+ inlineMap = info.Num
+ case reflect.Struct, reflect.Pointer:
+ ftype := field.Type
+ for ftype.Kind() == reflect.Pointer {
+ ftype = ftype.Elem()
+ }
+ if ftype.Kind() != reflect.Struct {
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ // Check for both libyaml.constructor and yaml.Unmarshaler (by method name)
+ if reflect.PointerTo(ftype).Implements(constructorType) || hasConstructYAMLMethod(reflect.PointerTo(ftype)) {
+ inlineConstructors = append(inlineConstructors, []int{i})
+ } else {
+ sinfo, err := getStructInfo(ftype)
+ if err != nil {
+ return nil, err
+ }
+ for _, index := range sinfo.InlineConstructors {
+ inlineConstructors = append(inlineConstructors, append([]int{i}, index...))
+ }
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
+ }
+ }
+ default:
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ continue
+ }
+
+ if tag != "" {
+ info.Key = tag
+ } else {
+ info.Key = strings.ToLower(field.Name)
+ }
+
+ if _, found = fieldsMap[info.Key]; found {
+ msg := "duplicated key '" + info.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+
+ info.Id = len(fieldsList)
+ fieldsList = append(fieldsList, info)
+ fieldsMap[info.Key] = info
+ }
+
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ InlineConstructors: inlineConstructors,
+ }
+
+ fieldMapMutex.Lock()
+ structMap[st] = sinfo
+ fieldMapMutex.Unlock()
+ return sinfo, nil
+}
+
+// isZero reports whether v represents the zero value for its type.
+// If v implements the IsZeroer interface, IsZero() is called.
+// Otherwise, zero is determined by checking type-specific conditions.
+// This is used to determine omitempty behavior when marshaling.
+func isZero(v reflect.Value) bool {
+ kind := v.Kind()
+ if z, ok := v.Interface().(IsZeroer); ok {
+ if (kind == reflect.Pointer || kind == reflect.Interface) && v.IsNil() {
+ return true
+ }
+ return z.IsZero()
+ }
+ switch kind {
+ case reflect.String:
+ return len(v.String()) == 0
+ case reflect.Interface, reflect.Pointer:
+ return v.IsNil()
+ case reflect.Slice:
+ return v.Len() == 0
+ case reflect.Map:
+ return v.Len() == 0
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Struct:
+ vt := v.Type()
+ for i := v.NumField() - 1; i >= 0; i-- {
+ if vt.Field(i).PkgPath != "" {
+ continue // Private field
+ }
+ if !isZero(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+type Constructor struct {
+ doc *Node
+ aliases map[*Node]bool
+ TypeErrors []*ConstructError
+
+ stringMapType reflect.Type
+ generalMapType reflect.Type
+
+ KnownFields bool
+ UniqueKeys bool
+ constructCount int
+ aliasCount int
+ aliasDepth int
+
+ mergedFields map[any]bool
+}
+
+var (
+ nodeType = reflect.TypeOf(Node{})
+ durationType = reflect.TypeOf(time.Duration(0))
+ stringMapType = reflect.TypeOf(map[string]any{})
+ generalMapType = reflect.TypeOf(map[any]any{})
+ ifaceType = generalMapType.Elem()
+)
+
+func NewConstructor(opts *Options) *Constructor {
+ return &Constructor{
+ stringMapType: stringMapType,
+ generalMapType: generalMapType,
+ KnownFields: opts.KnownFields,
+ UniqueKeys: opts.UniqueKeys,
+ aliases: make(map[*Node]bool),
+ }
+}
+
+// Construct decodes YAML input into the provided output value.
+// The out parameter must be a pointer to the value to decode into.
+// Returns a [LoadErrors] if type mismatches occur during decoding.
+func Construct(in []byte, out any, opts *Options) error {
+ d := NewConstructor(opts)
+ p := NewComposer(in)
+ defer p.Destroy()
+ node := p.Parse()
+ if node != nil {
+ v := reflect.ValueOf(out)
+ if v.Kind() == reflect.Pointer && !v.IsNil() {
+ v = v.Elem()
+ }
+ d.Construct(node, v)
+ }
+ if len(d.TypeErrors) > 0 {
+ return &LoadErrors{Errors: d.TypeErrors}
+ }
+ return nil
+}
+
+func (c *Constructor) tagError(n *Node, tag string, out reflect.Value) {
+ if n.Tag != "" {
+ tag = n.Tag
+ }
+ value := n.Value
+ if tag != seqTag && tag != mapTag {
+ if len(value) > 10 {
+ value = " `" + value[:7] + "...`"
+ } else {
+ value = " `" + value + "`"
+ }
+ }
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: fmt.Errorf("cannot construct %s%s into %s", shortTag(tag), value, out.Type()),
+ Line: n.Line,
+ Column: n.Column,
+ })
+}
+
+func (c *Constructor) callConstructor(n *Node, u constructor) (good bool) {
+ err := u.UnmarshalYAML(n)
+ switch e := err.(type) {
+ case nil:
+ return true
+ case *LoadErrors:
+ c.TypeErrors = append(c.TypeErrors, e.Errors...)
+ return false
+ default:
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: err,
+ Line: n.Line,
+ Column: n.Column,
+ })
+ return false
+ }
+}
+
+func (c *Constructor) callObsoleteConstructor(n *Node, u obsoleteConstructor) (good bool) {
+ terrlen := len(c.TypeErrors)
+ err := u.UnmarshalYAML(func(v any) (err error) {
+ defer handleErr(&err)
+ c.Construct(n, reflect.ValueOf(v))
+ if len(c.TypeErrors) > terrlen {
+ issues := c.TypeErrors[terrlen:]
+ c.TypeErrors = c.TypeErrors[:terrlen]
+ return &LoadErrors{issues}
+ }
+ return nil
+ })
+ switch e := err.(type) {
+ case nil:
+ return true
+ case *LoadErrors:
+ c.TypeErrors = append(c.TypeErrors, e.Errors...)
+ return false
+ default:
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: err,
+ Line: n.Line,
+ Column: n.Column,
+ })
+ return false
+ }
+}
+
+func isTextUnmarshaler(out reflect.Value) bool {
+ // Dereference pointers to check the underlying type,
+ // similar to how prepare() handles Constructor checks.
+ for out.Kind() == reflect.Pointer {
+ if out.IsNil() {
+ // Create a new instance to check the type
+ out = reflect.New(out.Type().Elem()).Elem()
+ } else {
+ out = out.Elem()
+ }
+ }
+ if out.CanAddr() {
+ _, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ return ok
+ }
+ return false
+}
+
+// prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// construction was already done by UnmarshalYAML, and if so whether
+// its types constructed appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (c *Constructor) prepare(n *Node, out reflect.Value) (newout reflect.Value, constructed, good bool) {
+ if n.ShortTag() == nullTag {
+ return out, false, false
+ }
+ again := true
+ for again {
+ again = false
+ if out.Kind() == reflect.Pointer {
+ if out.IsNil() {
+ out.Set(reflect.New(out.Type().Elem()))
+ }
+ out = out.Elem()
+ again = true
+ }
+ if out.CanAddr() {
+ // Try yaml.Unmarshaler (from root package) first
+ if called, good := c.tryCallYAMLConstructor(n, out); called {
+ return out, true, good
+ }
+
+ outi := out.Addr().Interface()
+ // Check for libyaml.constructor
+ if u, ok := outi.(constructor); ok {
+ good = c.callConstructor(n, u)
+ return out, true, good
+ }
+ if u, ok := outi.(obsoleteConstructor); ok {
+ good = c.callObsoleteConstructor(n, u)
+ return out, true, good
+ }
+ }
+ }
+ return out, false, false
+}
+
+func (c *Constructor) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+ if n.ShortTag() == nullTag {
+ return reflect.Value{}
+ }
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Pointer {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+const (
+ // 400,000 decode operations is ~500kb of dense object declarations, or
+ // ~5kb of dense object declarations with 10000% alias expansion
+ alias_ratio_range_low = 400000
+
+ // 4,000,000 decode operations is ~5MB of dense object declarations, or
+ // ~4.5MB of dense object declarations with 10% alias expansion
+ alias_ratio_range_high = 4000000
+
+ // alias_ratio_range is the range over which we scale allowed alias ratios
+ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(constructCount int) float64 {
+ switch {
+ case constructCount <= alias_ratio_range_low:
+ // allow 99% to come from alias expansion for small-to-medium documents
+ return 0.99
+ case constructCount >= alias_ratio_range_high:
+ // allow 10% to come from alias expansion for very large documents
+ return 0.10
+ default:
+ // scale smoothly from 99% down to 10% over the range.
+ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+ return 0.99 - 0.89*(float64(constructCount-alias_ratio_range_low)/alias_ratio_range)
+ }
+}
+
+// constructorAdapter is an interface that wraps the root package's Unmarshaler interface.
+// This allows the constructor to call constructors that expect *yaml.Node instead of *libyaml.Node.
+type constructorAdapter interface {
+ CallRootConstructor(n *Node) error
+}
+
+// tryCallYAMLConstructor checks if the value has an UnmarshalYAML method that takes
+// a *yaml.Node (from the root package) and calls it if found.
+// This handles the case where user types implement yaml.Unmarshaler instead of libyaml.constructor.
+func (c *Constructor) tryCallYAMLConstructor(n *Node, out reflect.Value) (called bool, good bool) {
+ if !out.CanAddr() {
+ return false, false
+ }
+
+ addr := out.Addr()
+ // Check for UnmarshalYAML method
+ method := addr.MethodByName("UnmarshalYAML")
+ if !method.IsValid() {
+ return false, false
+ }
+
+ // Check method signature: func(*yaml.Node) error
+ mtype := method.Type()
+ if mtype.NumIn() != 1 || mtype.NumOut() != 1 {
+ return false, false
+ }
+
+ // Check if parameter is a pointer to a Node-like struct
+ paramType := mtype.In(0)
+ if paramType.Kind() != reflect.Ptr {
+ return false, false
+ }
+
+ elemType := paramType.Elem()
+ if elemType.Kind() != reflect.Struct {
+ return false, false
+ }
+
+ // Check if it's the same underlying type as our Node
+ // Both yaml.Node and libyaml.Node have the same structure
+ if elemType.Name() != "Node" {
+ return false, false
+ }
+
+ // Call the method with a converted node
+ // Since yaml.Node and libyaml.Node have the same structure,
+ // we can convert using unsafe pointer cast
+ nodeValue := reflect.NewAt(elemType, reflect.ValueOf(n).UnsafePointer())
+
+ results := method.Call([]reflect.Value{nodeValue})
+ err := results[0].Interface()
+
+ if err == nil {
+ return true, true
+ }
+
+ switch e := err.(type) {
+ case *LoadErrors:
+ c.TypeErrors = append(c.TypeErrors, e.Errors...)
+ return true, false
+ default:
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: e.(error),
+ Line: n.Line,
+ Column: n.Column,
+ })
+ return true, false
+ }
+}
+
+func (c *Constructor) Construct(n *Node, out reflect.Value) (good bool) {
+ c.constructCount++
+ if c.aliasDepth > 0 {
+ c.aliasCount++
+ }
+ if c.aliasCount > 100 && c.constructCount > 1000 && float64(c.aliasCount)/float64(c.constructCount) > allowedAliasRatio(c.constructCount) {
+ failf("document contains excessive aliasing")
+ }
+ if out.Type() == nodeType {
+ out.Set(reflect.ValueOf(n).Elem())
+ return true
+ }
+
+ // When out type implements [encoding.TextUnmarshaler], ensure the node is
+ // a scalar. Otherwise, for example, constructing a YAML mapping into
+ // a struct having no exported fields, but implementing TextUnmarshaler
+ // would silently succeed, but do nothing.
+ //
+ // Note that this matches the behavior of both encoding/json and encoding/json/v2.
+ if n.Kind != ScalarNode && isTextUnmarshaler(out) {
+ err := fmt.Errorf("cannot construct %s into %s (TextUnmarshaler)", shortTag(n.Tag), out.Type())
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: err,
+ Line: n.Line,
+ Column: n.Column,
+ })
+ return false
+ }
+ switch n.Kind {
+ case DocumentNode:
+ return c.document(n, out)
+ case AliasNode:
+ return c.alias(n, out)
+ }
+ out, constructed, good := c.prepare(n, out)
+ if constructed {
+ return good
+ }
+ switch n.Kind {
+ case ScalarNode:
+ good = c.scalar(n, out)
+ case MappingNode:
+ good = c.mapping(n, out)
+ case SequenceNode:
+ good = c.sequence(n, out)
+ case 0:
+ if n.IsZero() {
+ return c.null(out)
+ }
+ fallthrough
+ default:
+ failf("cannot construct node with unknown kind %d", n.Kind)
+ }
+ return good
+}
+
+func (c *Constructor) document(n *Node, out reflect.Value) (good bool) {
+ if len(n.Content) == 1 {
+ c.doc = n
+ c.Construct(n.Content[0], out)
+ return true
+ }
+ return false
+}
+
+func (c *Constructor) alias(n *Node, out reflect.Value) (good bool) {
+ if c.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
+ failf("anchor '%s' value contains itself", n.Value)
+ }
+ c.aliases[n] = true
+ c.aliasDepth++
+ good = c.Construct(n.Alias, out)
+ c.aliasDepth--
+ delete(c.aliases, n)
+ return good
+}
+
+func (c *Constructor) null(out reflect.Value) bool {
+ if out.CanAddr() {
+ switch out.Kind() {
+ case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice:
+ out.Set(reflect.Zero(out.Type()))
+ return true
+ }
+ }
+ return false
+}
+
+func (c *Constructor) scalar(n *Node, out reflect.Value) bool {
+ var tag string
+ var resolved any
+ if n.indicatedString() {
+ tag = strTag
+ resolved = n.Value
+ } else {
+ tag, resolved = resolve(n.Tag, n.Value)
+ if tag == binaryTag {
+ data, err := base64.StdEncoding.DecodeString(resolved.(string))
+ if err != nil {
+ failf("!!binary value contains invalid base64 data")
+ }
+ resolved = string(data)
+ }
+ }
+ if resolved == nil {
+ return c.null(out)
+ }
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ // We've resolved to exactly the type we want, so use that.
+ out.Set(resolvedv)
+ return true
+ }
+ // Perhaps we can use the value as a TextUnmarshaler to
+ // set its value.
+ if out.CanAddr() {
+ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ if ok {
+ var text []byte
+ if tag == binaryTag {
+ text = []byte(resolved.(string))
+ } else {
+ // We let any value be constructed into TextUnmarshaler.
+ // That might be more lax than we'd like, but the
+ // TextUnmarshaler itself should bowl out any dubious values.
+ text = []byte(n.Value)
+ }
+ err := u.UnmarshalText(text)
+ if err != nil {
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: err,
+ Line: n.Line,
+ Column: n.Column,
+ })
+ return false
+ }
+ return true
+ }
+ }
+ switch out.Kind() {
+ case reflect.String:
+ if tag == binaryTag {
+ out.SetString(resolved.(string))
+ return true
+ }
+ out.SetString(n.Value)
+ return true
+ case reflect.Slice:
+ // allow decoding !!binary-tagged value into []byte specifically
+ if out.Type().Elem().Kind() == reflect.Uint8 {
+ if tag == binaryTag {
+ out.SetBytes([]byte(resolved.(string)))
+ return true
+ }
+ }
+ case reflect.Interface:
+ out.Set(reflect.ValueOf(resolved))
+ return true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ // This used to work in v2, but it's very unfriendly.
+ isDuration := out.Type() == durationType
+
+ switch resolved := resolved.(type) {
+ case int:
+ if !isDuration && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ } else if isDuration && resolved == 0 {
+ out.SetInt(0)
+ return true
+ }
+ case int64:
+ if !isDuration && !out.OverflowInt(resolved) {
+ out.SetInt(resolved)
+ return true
+ }
+ case uint64:
+ if !isDuration && resolved <= math.MaxInt64 {
+ intVal := int64(resolved)
+ if !out.OverflowInt(intVal) {
+ out.SetInt(intVal)
+ return true
+ }
+ }
+ case float64:
+ if !isDuration && resolved >= math.MinInt64 && resolved <= math.MaxInt64 {
+ intVal := int64(resolved)
+ // Verify conversion is lossless (handles floating-point precision)
+ if float64(intVal) == resolved && !out.OverflowInt(intVal) {
+ out.SetInt(intVal)
+ return true
+ }
+ }
+ case string:
+ if out.Type() == durationType {
+ d, err := time.ParseDuration(resolved)
+ if err == nil {
+ out.SetInt(int64(d))
+ return true
+ }
+ }
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch resolved := resolved.(type) {
+ case int:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case int64:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case uint64:
+ if !out.OverflowUint(resolved) {
+ out.SetUint(resolved)
+ return true
+ }
+ case float64:
+ if resolved >= 0 && resolved <= math.MaxUint64 {
+ uintVal := uint64(resolved)
+ // Verify conversion is lossless (handles floating-point precision)
+ if float64(uintVal) == resolved && !out.OverflowUint(uintVal) {
+ out.SetUint(uintVal)
+ return true
+ }
+ }
+ }
+ case reflect.Bool:
+ switch resolved := resolved.(type) {
+ case bool:
+ out.SetBool(resolved)
+ return true
+ case string:
+ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+ // It only works if explicitly attempting to construct into a typed bool value.
+ switch resolved {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+ out.SetBool(true)
+ return true
+ case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ out.SetBool(false)
+ return true
+ }
+ }
+ case reflect.Float32, reflect.Float64:
+ switch resolved := resolved.(type) {
+ case int:
+ out.SetFloat(float64(resolved))
+ return true
+ case int64:
+ out.SetFloat(float64(resolved))
+ return true
+ case uint64:
+ out.SetFloat(float64(resolved))
+ return true
+ case float64:
+ out.SetFloat(resolved)
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
+ }
+ case reflect.Pointer:
+ panic("yaml internal error: please report the issue")
+ }
+ c.tagError(n, tag, out)
+ return false
+}
+
+func settableValueOf(i any) reflect.Value {
+ v := reflect.ValueOf(i)
+ sv := reflect.New(v.Type()).Elem()
+ sv.Set(v)
+ return sv
+}
+
+func (c *Constructor) sequence(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+
+ var iface reflect.Value
+ switch out.Kind() {
+ case reflect.Slice:
+ out.Set(reflect.MakeSlice(out.Type(), l, l))
+ case reflect.Array:
+ if l != out.Len() {
+ failf("invalid array: want %d elements but got %d", out.Len(), l)
+ }
+ case reflect.Interface:
+ // No type hints. Will have to use a generic sequence.
+ iface = out
+ out = settableValueOf(make([]any, l))
+ default:
+ c.tagError(n, seqTag, out)
+ return false
+ }
+ et := out.Type().Elem()
+
+ j := 0
+ for i := 0; i < l; i++ {
+ e := reflect.New(et).Elem()
+ if ok := c.Construct(n.Content[i], e); ok {
+ out.Index(j).Set(e)
+ j++
+ }
+ }
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
+ if iface.IsValid() {
+ iface.Set(out)
+ }
+ return true
+}
+
+func (c *Constructor) mapping(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+ if c.UniqueKeys {
+ nerrs := len(c.TypeErrors)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ for j := i + 2; j < l; j += 2 {
+ nj := n.Content[j]
+ if ni.Kind == nj.Kind && ni.Value == nj.Value {
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: fmt.Errorf("mapping key %#v already defined at line %d", nj.Value, ni.Line),
+ Line: nj.Line,
+ Column: nj.Column,
+ })
+ }
+ }
+ }
+ if len(c.TypeErrors) > nerrs {
+ return false
+ }
+ }
+ switch out.Kind() {
+ case reflect.Struct:
+ return c.mappingStruct(n, out)
+ case reflect.Map:
+ // okay
+ case reflect.Interface:
+ iface := out
+ if isStringMap(n) {
+ out = reflect.MakeMap(c.stringMapType)
+ } else {
+ out = reflect.MakeMap(c.generalMapType)
+ }
+ iface.Set(out)
+ default:
+ c.tagError(n, mapTag, out)
+ return false
+ }
+
+ outt := out.Type()
+ kt := outt.Key()
+ et := outt.Elem()
+
+ stringMapType := c.stringMapType
+ generalMapType := c.generalMapType
+ if outt.Elem() == ifaceType {
+ if outt.Key().Kind() == reflect.String {
+ c.stringMapType = outt
+ } else if outt.Key() == ifaceType {
+ c.generalMapType = outt
+ }
+ }
+
+ mergedFields := c.mergedFields
+ c.mergedFields = nil
+
+ var mergeNode *Node
+
+ mapIsNew := false
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(outt))
+ mapIsNew = true
+ }
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.Content[i]) {
+ mergeNode = n.Content[i+1]
+ continue
+ }
+ k := reflect.New(kt).Elem()
+ if c.Construct(n.Content[i], k) {
+ if mergedFields != nil {
+ ki := k.Interface()
+ if c.getPossiblyUnhashableKey(mergedFields, ki) {
+ continue
+ }
+ c.setPossiblyUnhashableKey(mergedFields, ki, true)
+ }
+ kkind := k.Kind()
+ if kkind == reflect.Interface {
+ kkind = k.Elem().Kind()
+ }
+ if kkind == reflect.Map || kkind == reflect.Slice {
+ failf("cannot use '%#v' as a map key; try decoding into yaml.Node", k.Interface())
+ }
+ e := reflect.New(et).Elem()
+ if c.Construct(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+ out.SetMapIndex(k, e)
+ }
+ }
+ }
+
+ c.mergedFields = mergedFields
+ if mergeNode != nil {
+ c.merge(n, mergeNode, out)
+ }
+
+ c.stringMapType = stringMapType
+ c.generalMapType = generalMapType
+ return true
+}
+
+func isStringMap(n *Node) bool {
+ if n.Kind != MappingNode {
+ return false
+ }
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ shortTag := n.Content[i].ShortTag()
+ if shortTag != strTag && shortTag != mergeTag {
+ return false
+ }
+ }
+ return true
+}
+
+func (c *Constructor) mappingStruct(n *Node, out reflect.Value) (good bool) {
+ sinfo, err := getStructInfo(out.Type())
+ if err != nil {
+ panic(err)
+ }
+
+ var inlineMap reflect.Value
+ var elemType reflect.Type
+ if sinfo.InlineMap != -1 {
+ inlineMap = out.Field(sinfo.InlineMap)
+ elemType = inlineMap.Type().Elem()
+ }
+
+ for _, index := range sinfo.InlineConstructors {
+ field := c.fieldByIndex(n, out, index)
+ c.prepare(n, field)
+ }
+
+ mergedFields := c.mergedFields
+ c.mergedFields = nil
+ var mergeNode *Node
+ var doneFields []bool
+ if c.UniqueKeys {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
+ name := settableValueOf("")
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ if isMerge(ni) {
+ mergeNode = n.Content[i+1]
+ continue
+ }
+ if !c.Construct(ni, name) {
+ continue
+ }
+ sname := name.String()
+ if mergedFields != nil {
+ if mergedFields[sname] {
+ continue
+ }
+ mergedFields[sname] = true
+ }
+ if info, ok := sinfo.FieldsMap[sname]; ok {
+ if c.UniqueKeys {
+ if doneFields[info.Id] {
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: fmt.Errorf("field %s already set in type %s", name.String(), out.Type()),
+ Line: ni.Line,
+ Column: ni.Column,
+ })
+ continue
+ }
+ doneFields[info.Id] = true
+ }
+ var field reflect.Value
+ if info.Inline == nil {
+ field = out.Field(info.Num)
+ } else {
+ field = c.fieldByIndex(n, out, info.Inline)
+ }
+ c.Construct(n.Content[i+1], field)
+ } else if sinfo.InlineMap != -1 {
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+ value := reflect.New(elemType).Elem()
+ c.Construct(n.Content[i+1], value)
+ inlineMap.SetMapIndex(name, value)
+ } else if c.KnownFields {
+ c.TypeErrors = append(c.TypeErrors, &ConstructError{
+ Err: fmt.Errorf("field %s not found in type %s", name.String(), out.Type()),
+ Line: ni.Line,
+ Column: ni.Column,
+ })
+ }
+ }
+
+ c.mergedFields = mergedFields
+ if mergeNode != nil {
+ c.merge(n, mergeNode, out)
+ }
+ return true
+}
+
+func failWantMap() {
+ failf("map merge requires map or sequence of maps as the value")
+}
+
+func (c *Constructor) setPossiblyUnhashableKey(m map[any]bool, key any, value bool) {
+ defer func() {
+ if err := recover(); err != nil {
+ failf("%v", err)
+ }
+ }()
+ m[key] = value
+}
+
+func (c *Constructor) getPossiblyUnhashableKey(m map[any]bool, key any) bool {
+ defer func() {
+ if err := recover(); err != nil {
+ failf("%v", err)
+ }
+ }()
+ return m[key]
+}
+
+func (c *Constructor) merge(parent *Node, merge *Node, out reflect.Value) {
+ mergedFields := c.mergedFields
+ if mergedFields == nil {
+ c.mergedFields = make(map[any]bool)
+ for i := 0; i < len(parent.Content); i += 2 {
+ k := reflect.New(ifaceType).Elem()
+ if c.Construct(parent.Content[i], k) {
+ c.setPossiblyUnhashableKey(c.mergedFields, k.Interface(), true)
+ }
+ }
+ }
+
+ switch merge.Kind {
+ case MappingNode:
+ c.Construct(merge, out)
+ case AliasNode:
+ if merge.Alias != nil && merge.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ c.Construct(merge, out)
+ case SequenceNode:
+ for i := 0; i < len(merge.Content); i++ {
+ ni := merge.Content[i]
+ if ni.Kind == AliasNode {
+ if ni.Alias != nil && ni.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ } else if ni.Kind != MappingNode {
+ failWantMap()
+ }
+ c.Construct(ni, out)
+ }
+ default:
+ failWantMap()
+ }
+
+ c.mergedFields = mergedFields
+}
+
+func isMerge(n *Node) bool {
+ return n.Kind == ScalarNode && shortTag(n.Tag) == mergeTag
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/doc.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/doc.go
new file mode 100644
index 00000000000..7f8690575d2
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Package libyaml contains internal helpers for working with YAML
+//
+// It's a reworked version of the original libyaml package from go-yaml v2/v3,
+// adapted to work with Go specifications
+package libyaml
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/emitter.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/emitter.go
new file mode 100644
index 00000000000..7ea83e89cdb
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/emitter.go
@@ -0,0 +1,2083 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Emitter stage: Generates YAML output from events.
+// Handles formatting, indentation, line wrapping, and output buffering.
+
+package libyaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Flush the buffer if needed.
+func (emitter *Emitter) flushIfNeeded() error {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ return emitter.flush()
+ }
+ return nil
+}
+
+// Put a character to the output buffer.
+func (emitter *Emitter) put(value byte) error {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ if err := emitter.flush(); err != nil {
+ return err
+ }
+ }
+ emitter.buffer[emitter.buffer_pos] = value
+ emitter.buffer_pos++
+ emitter.column++
+ return nil
+}
+
+// Put a line break to the output buffer.
+func (emitter *Emitter) putLineBreak() error {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ if err := emitter.flush(); err != nil {
+ return err
+ }
+ }
+ switch emitter.line_break {
+ case CR_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\r'
+ emitter.buffer_pos += 1
+ case LN_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\n'
+ emitter.buffer_pos += 1
+ case CRLN_BREAK:
+ emitter.buffer[emitter.buffer_pos+0] = '\r'
+ emitter.buffer[emitter.buffer_pos+1] = '\n'
+ emitter.buffer_pos += 2
+ default:
+ panic("unknown line break setting")
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and below and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ return nil
+}
+
+// Copy a character from a string into buffer.
+func (emitter *Emitter) write(s []byte, i *int) error {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ if err := emitter.flush(); err != nil {
+ return err
+ }
+ }
+ p := emitter.buffer_pos
+ w := width(s[*i])
+ switch w {
+ case 4:
+ emitter.buffer[p+3] = s[*i+3]
+ fallthrough
+ case 3:
+ emitter.buffer[p+2] = s[*i+2]
+ fallthrough
+ case 2:
+ emitter.buffer[p+1] = s[*i+1]
+ fallthrough
+ case 1:
+ emitter.buffer[p+0] = s[*i+0]
+ default:
+ panic("unknown character width")
+ }
+ emitter.column++
+ emitter.buffer_pos += w
+ *i += w
+ return nil
+}
+
+// Write a whole string into buffer.
+func (emitter *Emitter) writeAll(s []byte) error {
+ for i := 0; i < len(s); {
+ if err := emitter.write(s, &i); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Copy a line break character from a string into buffer.
+func (emitter *Emitter) writeLineBreak(s []byte, i *int) error {
+ if s[*i] == '\n' {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ *i++
+ } else {
+ if err := emitter.write(s, i); err != nil {
+ return err
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and above and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ }
+ return nil
+}
+
+// Emit an event.
+func (emitter *Emitter) Emit(event *Event) error {
+ emitter.events = append(emitter.events, *event)
+ for !emitter.needMoreEvents() {
+ event := &emitter.events[emitter.events_head]
+ if err := emitter.analyzeEvent(event); err != nil {
+ return err
+ }
+ if err := emitter.stateMachine(event); err != nil {
+ return err
+ }
+ event.Delete()
+ emitter.events_head++
+ }
+ return nil
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+// - 1 event for DOCUMENT-START
+// - 2 events for SEQUENCE-START
+// - 3 events for MAPPING-START
+func (emitter *Emitter) needMoreEvents() bool {
+ if emitter.events_head == len(emitter.events) {
+ return true
+ }
+ var accumulate int
+ switch emitter.events[emitter.events_head].Type {
+ case DOCUMENT_START_EVENT:
+ accumulate = 1
+ case SEQUENCE_START_EVENT:
+ accumulate = 2
+ case MAPPING_START_EVENT:
+ accumulate = 3
+ default:
+ return false
+ }
+ if len(emitter.events)-emitter.events_head > accumulate {
+ return false
+ }
+ var level int
+ for i := emitter.events_head; i < len(emitter.events); i++ {
+ switch emitter.events[i].Type {
+ case STREAM_START_EVENT, DOCUMENT_START_EVENT, SEQUENCE_START_EVENT, MAPPING_START_EVENT:
+ level++
+ case STREAM_END_EVENT, DOCUMENT_END_EVENT, SEQUENCE_END_EVENT, MAPPING_END_EVENT:
+ level--
+ }
+ if level == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Append a directive to the directives stack.
+func (emitter *Emitter) appendTagDirective(value *TagDirective, allow_duplicates bool) error {
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+ if allow_duplicates {
+ return nil
+ }
+ return EmitterError{
+ Message: "duplicate %TAG directive",
+ }
+ }
+ }
+
+ // [Go] Do we actually need to copy this given garbage collection
+ // and the lack of deallocating destructors?
+ tag_copy := TagDirective{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(tag_copy.handle, value.handle)
+ copy(tag_copy.prefix, value.prefix)
+ emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+ return nil
+}
+
+// Increase the indentation level.
+func (emitter *Emitter) increaseIndentCompact(flow, indentless bool, compact_seq bool) error {
+ emitter.indents = append(emitter.indents, emitter.indent)
+ if emitter.indent < 0 {
+ if flow {
+ emitter.indent = emitter.BestIndent
+ } else {
+ emitter.indent = 0
+ }
+ } else if !indentless {
+ // [Go] This was changed so that indentations are more regular.
+ if emitter.states[len(emitter.states)-1] == EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+ // The first indent inside a sequence will just skip the "- " indicator.
+ emitter.indent += 2
+ } else {
+ // Everything else aligns to the chosen indentation.
+ emitter.indent = emitter.BestIndent * ((emitter.indent + emitter.BestIndent) / emitter.BestIndent)
+ if compact_seq {
+ // The value compact_seq passed in is almost always set to `false` when this function is called,
+ // except when we are dealing with sequence nodes. So this gets triggered to subtract 2 only when we
+ // are increasing the indent to account for sequence nodes, which will be correct because we need to
+ // subtract 2 to account for the - at the beginning of the sequence node.
+ emitter.indent = emitter.indent - 2
+ }
+ }
+ }
+ return nil
+}
+
+// State dispatcher.
+func (emitter *Emitter) stateMachine(event *Event) error {
+ switch emitter.state {
+ default:
+ case EMIT_STREAM_START_STATE:
+ return emitter.emitStreamStart(event)
+
+ case EMIT_FIRST_DOCUMENT_START_STATE:
+ return emitter.emitDocumentStart(event, true)
+
+ case EMIT_DOCUMENT_START_STATE:
+ return emitter.emitDocumentStart(event, false)
+
+ case EMIT_DOCUMENT_CONTENT_STATE:
+ return emitter.emitDocumentContent(event)
+
+ case EMIT_DOCUMENT_END_STATE:
+ return emitter.emitDocumentEnd(event)
+
+ case EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return emitter.emitFlowSequenceItem(event, true, false)
+
+ case EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+ return emitter.emitFlowSequenceItem(event, false, true)
+
+ case EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return emitter.emitFlowSequenceItem(event, false, false)
+
+ case EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return emitter.emitFlowMappingKey(event, true, false)
+
+ case EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+ return emitter.emitFlowMappingKey(event, false, true)
+
+ case EMIT_FLOW_MAPPING_KEY_STATE:
+ return emitter.emitFlowMappingKey(event, false, false)
+
+ case EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return emitter.emitFlowMappingValue(event, true)
+
+ case EMIT_FLOW_MAPPING_VALUE_STATE:
+ return emitter.emitFlowMappingValue(event, false)
+
+ case EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return emitter.emitBlockSequenceItem(event, true)
+
+ case EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return emitter.emitBlockSequenceItem(event, false)
+
+ case EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return emitter.emitBlockMappingKey(event, true)
+
+ case EMIT_BLOCK_MAPPING_KEY_STATE:
+ return emitter.emitBlockMappingKey(event, false)
+
+ case EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return emitter.emitBlockMappingValue(event, true)
+
+ case EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return emitter.emitBlockMappingValue(event, false)
+
+ case EMIT_END_STATE:
+ return EmitterError{
+ Message: "expected nothing after STREAM-END",
+ }
+ }
+ panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func (emitter *Emitter) emitStreamStart(event *Event) error {
+ if event.Type != STREAM_START_EVENT {
+ return EmitterError{
+ Message: "expected STREAM-START",
+ }
+ }
+ if emitter.encoding == ANY_ENCODING {
+ emitter.encoding = event.encoding
+ if emitter.encoding == ANY_ENCODING {
+ emitter.encoding = UTF8_ENCODING
+ }
+ }
+ if emitter.BestIndent < 2 || emitter.BestIndent > 9 {
+ emitter.BestIndent = 2
+ }
+ if emitter.best_width >= 0 && emitter.best_width <= emitter.BestIndent*2 {
+ emitter.best_width = 80
+ }
+ if emitter.best_width < 0 {
+ emitter.best_width = 1<<31 - 1
+ }
+ if emitter.line_break == ANY_BREAK {
+ emitter.line_break = LN_BREAK
+ }
+
+ emitter.indent = -1
+ emitter.line = 0
+ emitter.column = 0
+ emitter.whitespace = true
+ emitter.indention = true
+ emitter.space_above = true
+ emitter.foot_indent = -1
+
+ if emitter.encoding != UTF8_ENCODING {
+ if err := emitter.writeBom(); err != nil {
+ return err
+ }
+ }
+ emitter.state = EMIT_FIRST_DOCUMENT_START_STATE
+ return nil
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func (emitter *Emitter) emitDocumentStart(event *Event, first bool) error {
+ if event.Type == DOCUMENT_START_EVENT {
+
+ if event.versionDirective != nil {
+ if err := emitter.analyzeVersionDirective(event.versionDirective); err != nil {
+ return err
+ }
+ }
+
+ for i := 0; i < len(event.tagDirectives); i++ {
+ tag_directive := &event.tagDirectives[i]
+ if err := emitter.analyzeTagDirective(tag_directive); err != nil {
+ return err
+ }
+ if err := emitter.appendTagDirective(tag_directive, false); err != nil {
+ return err
+ }
+ }
+
+ for i := 0; i < len(default_tag_directives); i++ {
+ tag_directive := &default_tag_directives[i]
+ if err := emitter.appendTagDirective(tag_directive, true); err != nil {
+ return err
+ }
+ }
+
+ implicit := event.Implicit
+ if !first || emitter.canonical {
+ implicit = false
+ }
+
+ if emitter.OpenEnded && (event.versionDirective != nil || len(event.tagDirectives) > 0) {
+ if err := emitter.writeIndicator([]byte("..."), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+
+ if event.versionDirective != nil {
+ implicit = false
+ if err := emitter.writeIndicator([]byte("%YAML"), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeIndicator([]byte("1.1"), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+
+ if len(event.tagDirectives) > 0 {
+ implicit = false
+ for i := 0; i < len(event.tagDirectives); i++ {
+ tag_directive := &event.tagDirectives[i]
+ if err := emitter.writeIndicator([]byte("%TAG"), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeTagHandle(tag_directive.handle); err != nil {
+ return err
+ }
+ if err := emitter.writeTagContent(tag_directive.prefix, true); err != nil {
+ return err
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ }
+
+ if emitter.checkEmptyDocument() {
+ implicit = false
+ }
+ if !implicit {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if err := emitter.writeIndicator([]byte("---"), true, false, false); err != nil {
+ return err
+ }
+ if emitter.canonical || true {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ }
+
+ if len(emitter.HeadComment) > 0 {
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+
+ emitter.state = EMIT_DOCUMENT_CONTENT_STATE
+ return nil
+ }
+
+ if event.Type == STREAM_END_EVENT {
+ if emitter.OpenEnded {
+ if err := emitter.writeIndicator([]byte("..."), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.flush(); err != nil {
+ return err
+ }
+ emitter.state = EMIT_END_STATE
+ return nil
+ }
+
+ return EmitterError{
+ Message: "expected DOCUMENT-START or STREAM-END",
+ }
+}
+
+// emitter preserves the original signature and delegates to
+// increaseIndentCompact without compact-sequence indentation
+func (emitter *Emitter) increaseIndent(flow, indentless bool) error {
+ return emitter.increaseIndentCompact(flow, indentless, false)
+}
+
+// processLineComment preserves the original signature and delegates to
+// processLineCommentLinebreak passing false for linebreak
+func (emitter *Emitter) processLineComment() error {
+ return emitter.processLineCommentLinebreak(false)
+}
+
+// Expect the root node.
+func (emitter *Emitter) emitDocumentContent(event *Event) error {
+ emitter.states = append(emitter.states, EMIT_DOCUMENT_END_STATE)
+
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+ if err := emitter.emitNode(event, true, false, false, false); err != nil {
+ return err
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Expect DOCUMENT-END.
+func (emitter *Emitter) emitDocumentEnd(event *Event) error {
+ if event.Type != DOCUMENT_END_EVENT {
+ return EmitterError{
+ Message: "expected DOCUMENT-END",
+ }
+ }
+ // [Go] Force document foot separation.
+ emitter.foot_indent = 0
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ emitter.foot_indent = -1
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if !event.Implicit {
+ // [Go] Allocate the slice elsewhere.
+ if err := emitter.writeIndicator([]byte("..."), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.flush(); err != nil {
+ return err
+ }
+ emitter.state = EMIT_DOCUMENT_START_STATE
+ emitter.tag_directives = emitter.tag_directives[:0]
+ return nil
+}
+
+// Expect a flow item node.
+func (emitter *Emitter) emitFlowSequenceItem(event *Event, first, trail bool) error {
+ if first {
+ if err := emitter.writeIndicator([]byte{'['}, true, true, false); err != nil {
+ return err
+ }
+ if err := emitter.increaseIndent(true, false); err != nil {
+ return err
+ }
+ emitter.flow_level++
+ }
+
+ if event.Type == SEQUENCE_END_EVENT {
+ if emitter.canonical && !first && !trail {
+ if err := emitter.writeIndicator([]byte{','}, false, false, false); err != nil {
+ return err
+ }
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.column == 0 || emitter.canonical && !first {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeIndicator([]byte{']'}, false, false, false); err != nil {
+ return err
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+
+ return nil
+ }
+
+ if !first && !trail {
+ if err := emitter.writeIndicator([]byte{','}, false, false, false); err != nil {
+ return err
+ }
+ }
+
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+ if emitter.column == 0 {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if len(emitter.LineComment)+len(emitter.FootComment)+len(emitter.TailComment) > 0 {
+ emitter.states = append(emitter.states, EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+ } else {
+ emitter.states = append(emitter.states, EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ }
+ if err := emitter.emitNode(event, false, true, false, false); err != nil {
+ return err
+ }
+ if len(emitter.LineComment)+len(emitter.FootComment)+len(emitter.TailComment) > 0 {
+ if err := emitter.writeIndicator([]byte{','}, false, false, false); err != nil {
+ return err
+ }
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Expect a flow key node.
+func (emitter *Emitter) emitFlowMappingKey(event *Event, first, trail bool) error {
+ if first {
+ if err := emitter.writeIndicator([]byte{'{'}, true, true, false); err != nil {
+ return err
+ }
+ if err := emitter.increaseIndent(true, false); err != nil {
+ return err
+ }
+ emitter.flow_level++
+ }
+
+ if event.Type == MAPPING_END_EVENT {
+ if (emitter.canonical || len(emitter.HeadComment)+len(emitter.FootComment)+len(emitter.TailComment) > 0) && !first && !trail {
+ if err := emitter.writeIndicator([]byte{','}, false, false, false); err != nil {
+ return err
+ }
+ }
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeIndicator([]byte{'}'}, false, false, false); err != nil {
+ return err
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return nil
+ }
+
+ if !first && !trail {
+ if err := emitter.writeIndicator([]byte{','}, false, false, false); err != nil {
+ return err
+ }
+ }
+
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+
+ if emitter.column == 0 {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+
+ if !emitter.canonical && emitter.checkSimpleKey() {
+ emitter.states = append(emitter.states, EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+ return emitter.emitNode(event, false, false, true, true)
+ }
+ if err := emitter.writeIndicator([]byte{'?'}, true, false, false); err != nil {
+ return err
+ }
+ emitter.states = append(emitter.states, EMIT_FLOW_MAPPING_VALUE_STATE)
+ return emitter.emitNode(event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func (emitter *Emitter) emitFlowMappingValue(event *Event, simple bool) error {
+ if simple {
+ if err := emitter.writeIndicator([]byte{':'}, false, false, false); err != nil {
+ return err
+ }
+ } else {
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeIndicator([]byte{':'}, true, false, false); err != nil {
+ return err
+ }
+ }
+ if len(emitter.LineComment)+len(emitter.FootComment)+len(emitter.TailComment) > 0 {
+ emitter.states = append(emitter.states, EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+ } else {
+ emitter.states = append(emitter.states, EMIT_FLOW_MAPPING_KEY_STATE)
+ }
+ if err := emitter.emitNode(event, false, false, true, false); err != nil {
+ return err
+ }
+ if len(emitter.LineComment)+len(emitter.FootComment)+len(emitter.TailComment) > 0 {
+ if err := emitter.writeIndicator([]byte{','}, false, false, false); err != nil {
+ return err
+ }
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Expect a block item node.
+func (emitter *Emitter) emitBlockSequenceItem(event *Event, first bool) error {
+ if first {
+ // emitter.mapping context tells us if we are currently in a mapping context.
+ // emitter.column tells us which column we are in the yaml output. 0 is the first char of the column.
+ // emitter.indentation tells us if the last character was an indentation character.
+ // emitter.compact_sequence_indent tells us if '- ' is considered part of the indentation for sequence elements.
+ // So, `seq` means that we are in a mapping context, and we are either at the first char of the column or
+ // the last character was not an indentation character, and we consider '- ' part of the indentation
+ // for sequence elements.
+ seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) &&
+ emitter.CompactSequenceIndent
+ if err := emitter.increaseIndentCompact(false, false, seq); err != nil {
+ return err
+ }
+ }
+ if event.Type == SEQUENCE_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return nil
+ }
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if err := emitter.writeIndicator([]byte{'-'}, true, false, true); err != nil {
+ return err
+ }
+ emitter.states = append(emitter.states, EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+ if err := emitter.emitNode(event, false, true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Expect a block key node.
+func (emitter *Emitter) emitBlockMappingKey(event *Event, first bool) error {
+ if first {
+ if err := emitter.increaseIndent(false, false); err != nil {
+ return err
+ }
+ }
+ if err := emitter.processHeadComment(); err != nil {
+ return err
+ }
+ if event.Type == MAPPING_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return nil
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if len(emitter.LineComment) > 0 {
+ // [Go] A line comment was provided for the key. That's unusual as the
+ // scanner associates line comments with the value. Either way,
+ // save the line comment and render it appropriately later.
+ emitter.key_line_comment = emitter.LineComment
+ emitter.LineComment = nil
+ }
+ if emitter.checkSimpleKey() {
+ emitter.states = append(emitter.states, EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+ if err := emitter.emitNode(event, false, false, true, true); err != nil {
+ return err
+ }
+
+ if event.Type == ALIAS_EVENT {
+ // make sure there's a space after the alias
+ return emitter.put(' ')
+ }
+
+ return nil
+ }
+ if err := emitter.writeIndicator([]byte{'?'}, true, false, true); err != nil {
+ return err
+ }
+ emitter.states = append(emitter.states, EMIT_BLOCK_MAPPING_VALUE_STATE)
+ return emitter.emitNode(event, false, false, true, false)
+}
+
+// Expect a block value node.
+func (emitter *Emitter) emitBlockMappingValue(event *Event, simple bool) error {
+ if simple {
+ if err := emitter.writeIndicator([]byte{':'}, false, false, false); err != nil {
+ return err
+ }
+ } else {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if err := emitter.writeIndicator([]byte{':'}, true, false, true); err != nil {
+ return err
+ }
+ }
+ if len(emitter.key_line_comment) > 0 {
+ // [Go] Line comments are generally associated with the value, but when there's
+ // no value on the same line as a mapping key they end up attached to the
+ // key itself.
+ if event.Type == SCALAR_EVENT {
+ if len(emitter.LineComment) == 0 {
+ // A scalar is coming and it has no line comments by itself yet,
+ // so just let it handle the line comment as usual. If it has a
+ // line comment, we can't have both so the one from the key is lost.
+ emitter.LineComment = emitter.key_line_comment
+ emitter.key_line_comment = nil
+ }
+ } else if event.SequenceStyle() != FLOW_SEQUENCE_STYLE && (event.Type == MAPPING_START_EVENT || event.Type == SEQUENCE_START_EVENT) {
+ // An indented block follows, so write the comment right now.
+ emitter.LineComment, emitter.key_line_comment = emitter.key_line_comment, emitter.LineComment
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ emitter.LineComment, emitter.key_line_comment = emitter.key_line_comment, emitter.LineComment
+ }
+ }
+ emitter.states = append(emitter.states, EMIT_BLOCK_MAPPING_KEY_STATE)
+ if err := emitter.emitNode(event, false, false, true, false); err != nil {
+ return err
+ }
+ if err := emitter.processLineComment(); err != nil {
+ return err
+ }
+ if err := emitter.processFootComment(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (emitter *Emitter) silentNilEvent(event *Event) bool {
+ return event.Type == SCALAR_EVENT && event.Implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
+// Expect a node.
+func (emitter *Emitter) emitNode(event *Event,
+ root bool, sequence bool, mapping bool, simple_key bool,
+) error {
+ emitter.root_context = root
+ emitter.sequence_context = sequence
+ emitter.mapping_context = mapping
+ emitter.simple_key_context = simple_key
+
+ switch event.Type {
+ case ALIAS_EVENT:
+ return emitter.emitAlias(event)
+ case SCALAR_EVENT:
+ return emitter.emitScalar(event)
+ case SEQUENCE_START_EVENT:
+ return emitter.emitSequenceStart(event)
+ case MAPPING_START_EVENT:
+ return emitter.emitMappingStart(event)
+ default:
+ return EmitterError{
+ Message: fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.Type),
+ }
+ }
+}
+
+// Expect ALIAS.
+func (emitter *Emitter) emitAlias(event *Event) error {
+ if err := emitter.processAnchor(); err != nil {
+ return err
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return nil
+}
+
+// requiredQuoteStyle returns the appropriate quote style based on the
+// emitter's quotePreference setting.
+func (emitter *Emitter) requiredQuoteStyle() ScalarStyle {
+ if emitter.quotePreference == QuoteDouble {
+ return DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return SINGLE_QUOTED_SCALAR_STYLE
+}
+
+// Expect SCALAR.
+func (emitter *Emitter) emitScalar(event *Event) error {
+ if err := emitter.selectScalarStyle(event); err != nil {
+ return err
+ }
+ if err := emitter.processAnchor(); err != nil {
+ return err
+ }
+ if err := emitter.processTag(); err != nil {
+ return err
+ }
+ if err := emitter.increaseIndent(true, false); err != nil {
+ return err
+ }
+ if err := emitter.processScalar(); err != nil {
+ return err
+ }
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return nil
+}
+
+// Expect SEQUENCE-START.
+func (emitter *Emitter) emitSequenceStart(event *Event) error {
+ if err := emitter.processAnchor(); err != nil {
+ return err
+ }
+ if err := emitter.processTag(); err != nil {
+ return err
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.SequenceStyle() == FLOW_SEQUENCE_STYLE ||
+ emitter.checkEmptySequence() {
+ emitter.state = EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+ } else {
+ emitter.state = EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+ }
+ return nil
+}
+
+// Expect MAPPING-START.
+func (emitter *Emitter) emitMappingStart(event *Event) error {
+ if err := emitter.processAnchor(); err != nil {
+ return err
+ }
+ if err := emitter.processTag(); err != nil {
+ return err
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.MappingStyle() == FLOW_MAPPING_STYLE ||
+ emitter.checkEmptyMapping() {
+ emitter.state = EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+ } else {
+ emitter.state = EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+ }
+ return nil
+}
+
+// Check if the document content is an empty scalar.
+func (emitter *Emitter) checkEmptyDocument() bool {
+ return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func (emitter *Emitter) checkEmptySequence() bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].Type == SEQUENCE_START_EVENT &&
+ emitter.events[emitter.events_head+1].Type == SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func (emitter *Emitter) checkEmptyMapping() bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].Type == MAPPING_START_EVENT &&
+ emitter.events[emitter.events_head+1].Type == MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func (emitter *Emitter) checkSimpleKey() bool {
+ length := 0
+ switch emitter.events[emitter.events_head].Type {
+ case ALIAS_EVENT:
+ length += len(emitter.anchor_data.anchor)
+ case SCALAR_EVENT:
+ if emitter.scalar_data.multiline {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix) +
+ len(emitter.scalar_data.value)
+ case SEQUENCE_START_EVENT:
+ if !emitter.checkEmptySequence() {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ case MAPPING_START_EVENT:
+ if !emitter.checkEmptyMapping() {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ default:
+ return false
+ }
+ return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func (emitter *Emitter) selectScalarStyle(event *Event) error {
+ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+ if no_tag && !event.Implicit && !event.quoted_implicit {
+ return EmitterError{
+ Message: "neither tag nor implicit flags are specified",
+ }
+ }
+
+ style := event.ScalarStyle()
+ if style == ANY_SCALAR_STYLE {
+ style = PLAIN_SCALAR_STYLE
+ }
+ if emitter.canonical {
+ style = DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ if emitter.simple_key_context && emitter.scalar_data.multiline {
+ style = DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ if style == PLAIN_SCALAR_STYLE {
+ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+ style = emitter.requiredQuoteStyle()
+ }
+ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+ style = emitter.requiredQuoteStyle()
+ }
+ if no_tag && !event.Implicit {
+ style = emitter.requiredQuoteStyle()
+ }
+ }
+ if style == SINGLE_QUOTED_SCALAR_STYLE {
+ if !emitter.scalar_data.single_quoted_allowed {
+ style = DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == LITERAL_SCALAR_STYLE || style == FOLDED_SCALAR_STYLE {
+ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+ style = DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+
+ if no_tag && !event.quoted_implicit && style != PLAIN_SCALAR_STYLE {
+ emitter.tag_data.handle = []byte{'!'}
+ }
+ emitter.scalar_data.style = style
+ return nil
+}
+
+// Write an anchor.
+func (emitter *Emitter) processAnchor() error {
+ if emitter.anchor_data.anchor == nil {
+ return nil
+ }
+ c := []byte{'&'}
+ if emitter.anchor_data.alias {
+ c[0] = '*'
+ }
+ if err := emitter.writeIndicator(c, true, false, false); err != nil {
+ return err
+ }
+ return emitter.writeAnchor(emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func (emitter *Emitter) processTag() error {
+ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+ return nil
+ }
+ if len(emitter.tag_data.handle) > 0 {
+ if err := emitter.writeTagHandle(emitter.tag_data.handle); err != nil {
+ return err
+ }
+ if len(emitter.tag_data.suffix) > 0 {
+ if err := emitter.writeTagContent(emitter.tag_data.suffix, false); err != nil {
+ return err
+ }
+ }
+ } else {
+ // [Go] Allocate these slices elsewhere.
+ if err := emitter.writeIndicator([]byte("!<"), true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeTagContent(emitter.tag_data.suffix, false); err != nil {
+ return err
+ }
+ if err := emitter.writeIndicator([]byte{'>'}, false, false, false); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Write a scalar.
+func (emitter *Emitter) processScalar() error {
+ switch emitter.scalar_data.style {
+ case PLAIN_SCALAR_STYLE:
+ return emitter.writePlainScalar(emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case SINGLE_QUOTED_SCALAR_STYLE:
+ return emitter.writeSingleQuotedScalar(emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case DOUBLE_QUOTED_SCALAR_STYLE:
+ return emitter.writeDoubleQuotedScalar(emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case LITERAL_SCALAR_STYLE:
+ return emitter.writeLiteralScalar(emitter.scalar_data.value)
+
+ case FOLDED_SCALAR_STYLE:
+ return emitter.writeFoldedScalar(emitter.scalar_data.value)
+ }
+ panic("unknown scalar style")
+}
+
+// Write a head comment.
+func (emitter *Emitter) processHeadComment() error {
+ if len(emitter.TailComment) > 0 {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if err := emitter.writeComment(emitter.TailComment); err != nil {
+ return err
+ }
+ emitter.TailComment = emitter.TailComment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ }
+
+ if len(emitter.HeadComment) == 0 {
+ return nil
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if err := emitter.writeComment(emitter.HeadComment); err != nil {
+ return err
+ }
+ emitter.HeadComment = emitter.HeadComment[:0]
+ return nil
+}
+
+// Write an line comment.
+func (emitter *Emitter) processLineCommentLinebreak(linebreak bool) error {
+ if len(emitter.LineComment) == 0 {
+ // The next 3 lines are needed to resolve an issue with leading newlines
+ // See https://github.com/go-yaml/yaml/issues/755
+ // When linebreak is set to true, put_break will be called and will add
+ // the needed newline.
+ if linebreak {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ if !emitter.whitespace {
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeComment(emitter.LineComment); err != nil {
+ return err
+ }
+ emitter.LineComment = emitter.LineComment[:0]
+ return nil
+}
+
+// Write a foot comment.
+func (emitter *Emitter) processFootComment() error {
+ if len(emitter.FootComment) == 0 {
+ return nil
+ }
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if err := emitter.writeComment(emitter.FootComment); err != nil {
+ return err
+ }
+ emitter.FootComment = emitter.FootComment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ return nil
+}
+
+// Check if a %YAML directive is valid.
+func (emitter *Emitter) analyzeVersionDirective(version_directive *VersionDirective) error {
+ if version_directive.major != 1 || version_directive.minor != 1 {
+ return EmitterError{
+ Message: "incompatible %YAML directive",
+ }
+ }
+ return nil
+}
+
+// Check if a %TAG directive is valid.
+func (emitter *Emitter) analyzeTagDirective(tag_directive *TagDirective) error {
+ handle := tag_directive.handle
+ prefix := tag_directive.prefix
+ if len(handle) == 0 {
+ return EmitterError{
+ Message: "tag handle must not be empty",
+ }
+ }
+ if handle[0] != '!' {
+ return EmitterError{
+ Message: "tag handle must start with '!'",
+ }
+ }
+ if handle[len(handle)-1] != '!' {
+ return EmitterError{
+ Message: "tag handle must end with '!'",
+ }
+ }
+ for i := 1; i < len(handle)-1; i += width(handle[i]) {
+ if !isAlpha(handle, i) {
+ return EmitterError{
+ Message: "tag handle must contain alphanumerical characters only",
+ }
+ }
+ }
+ if len(prefix) == 0 {
+ return EmitterError{
+ Message: "tag prefix must not be empty",
+ }
+ }
+ return nil
+}
+
+// Check if an anchor is valid.
+func (emitter *Emitter) analyzeAnchor(anchor []byte, alias bool) error {
+ if len(anchor) == 0 {
+ problem := "anchor value must not be empty"
+ if alias {
+ problem = "alias value must not be empty"
+ }
+ return EmitterError{
+ Message: problem,
+ }
+ }
+ for i := 0; i < len(anchor); i += width(anchor[i]) {
+ if !isAnchorChar(anchor, i) {
+ problem := "anchor value must contain valid characters only"
+ if alias {
+ problem = "alias value must contain valid characters only"
+ }
+ return EmitterError{
+ Message: problem,
+ }
+ }
+ }
+ emitter.anchor_data.anchor = anchor
+ emitter.anchor_data.alias = alias
+ return nil
+}
+
+// Check if a tag is valid.
+func (emitter *Emitter) analyzeTag(tag []byte) error {
+ if len(tag) == 0 {
+ return EmitterError{
+ Message: "tag value must not be empty",
+ }
+ }
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ tag_directive := &emitter.tag_directives[i]
+ if bytes.HasPrefix(tag, tag_directive.prefix) {
+ emitter.tag_data.handle = tag_directive.handle
+ emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+ return nil
+ }
+ }
+ emitter.tag_data.suffix = tag
+ return nil
+}
+
+// Check if a scalar is valid.
+func (emitter *Emitter) analyzeScalar(value []byte) error {
+ var block_indicators,
+ flow_indicators,
+ line_breaks,
+ special_characters,
+ tab_characters,
+
+ leading_space,
+ leading_break,
+ trailing_space,
+ trailing_break,
+ break_space,
+ space_break,
+
+ preceded_by_whitespace,
+ followed_by_whitespace,
+ previous_space,
+ previous_break bool
+
+ emitter.scalar_data.value = value
+
+ if len(value) == 0 {
+ emitter.scalar_data.multiline = false
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = false
+ return nil
+ }
+
+ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+ block_indicators = true
+ flow_indicators = true
+ }
+
+ preceded_by_whitespace = true
+ for i, w := 0, 0; i < len(value); i += w {
+ w = width(value[i])
+ followed_by_whitespace = i+w >= len(value) || isBlank(value, i+w)
+
+ if i == 0 {
+ switch value[i] {
+ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+ flow_indicators = true
+ block_indicators = true
+ case '?', ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '-':
+ if followed_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ } else {
+ switch value[i] {
+ case ',', '?', '[', ']', '{', '}':
+ flow_indicators = true
+ case ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '#':
+ if preceded_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ }
+
+ if value[i] == '\t' {
+ tab_characters = true
+ } else if !isPrintable(value, i) || !isASCII(value, i) && !emitter.unicode {
+ special_characters = true
+ }
+ if isSpace(value, i) {
+ if i == 0 {
+ leading_space = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_space = true
+ }
+ if previous_break {
+ break_space = true
+ }
+ previous_space = true
+ previous_break = false
+ } else if isLineBreak(value, i) {
+ line_breaks = true
+ if i == 0 {
+ leading_break = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_break = true
+ }
+ if previous_space {
+ space_break = true
+ }
+ previous_space = false
+ previous_break = true
+ } else {
+ previous_space = false
+ previous_break = false
+ }
+
+ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+ preceded_by_whitespace = isBlankOrZero(value, i)
+ }
+
+ emitter.scalar_data.multiline = line_breaks
+ emitter.scalar_data.flow_plain_allowed = true
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = true
+
+ if leading_space || leading_break || trailing_space || trailing_break {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if trailing_space {
+ emitter.scalar_data.block_allowed = false
+ }
+ if break_space {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || tab_characters || special_characters {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
+ emitter.scalar_data.block_allowed = false
+ }
+ if line_breaks {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if flow_indicators {
+ emitter.scalar_data.flow_plain_allowed = false
+ }
+ if block_indicators {
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ return nil
+}
+
+// Check if the event data is valid.
+func (emitter *Emitter) analyzeEvent(event *Event) error {
+ emitter.anchor_data.anchor = nil
+ emitter.tag_data.handle = nil
+ emitter.tag_data.suffix = nil
+ emitter.scalar_data.value = nil
+
+ if len(event.HeadComment) > 0 {
+ emitter.HeadComment = event.HeadComment
+ }
+ if len(event.LineComment) > 0 {
+ emitter.LineComment = event.LineComment
+ }
+ if len(event.FootComment) > 0 {
+ emitter.FootComment = event.FootComment
+ }
+ if len(event.TailComment) > 0 {
+ emitter.TailComment = event.TailComment
+ }
+
+ switch event.Type {
+ case ALIAS_EVENT:
+ if err := emitter.analyzeAnchor(event.Anchor, true); err != nil {
+ return err
+ }
+
+ case SCALAR_EVENT:
+ if len(event.Anchor) > 0 {
+ if err := emitter.analyzeAnchor(event.Anchor, false); err != nil {
+ return err
+ }
+ }
+ if len(event.Tag) > 0 && (emitter.canonical || (!event.Implicit && !event.quoted_implicit)) {
+ if err := emitter.analyzeTag(event.Tag); err != nil {
+ return err
+ }
+ }
+ if err := emitter.analyzeScalar(event.Value); err != nil {
+ return err
+ }
+
+ case SEQUENCE_START_EVENT:
+ if len(event.Anchor) > 0 {
+ if err := emitter.analyzeAnchor(event.Anchor, false); err != nil {
+ return err
+ }
+ }
+ if len(event.Tag) > 0 && (emitter.canonical || !event.Implicit) {
+ if err := emitter.analyzeTag(event.Tag); err != nil {
+ return err
+ }
+ }
+
+ case MAPPING_START_EVENT:
+ if len(event.Anchor) > 0 {
+ if err := emitter.analyzeAnchor(event.Anchor, false); err != nil {
+ return err
+ }
+ }
+ if len(event.Tag) > 0 && (emitter.canonical || !event.Implicit) {
+ if err := emitter.analyzeTag(event.Tag); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// Write the BOM character.
+func (emitter *Emitter) writeBom() error {
+ if err := emitter.flushIfNeeded(); err != nil {
+ return err
+ }
+ pos := emitter.buffer_pos
+ emitter.buffer[pos+0] = '\xEF'
+ emitter.buffer[pos+1] = '\xBB'
+ emitter.buffer[pos+2] = '\xBF'
+ emitter.buffer_pos += 3
+ return nil
+}
+
+func (emitter *Emitter) writeIndent() error {
+ indent := emitter.indent
+ if indent < 0 {
+ indent = 0
+ }
+ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+ if emitter.foot_indent == indent {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+ for emitter.column < indent {
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+ emitter.whitespace = true
+ emitter.space_above = false
+ emitter.foot_indent = -1
+ return nil
+}
+
+func (emitter *Emitter) writeIndicator(indicator []byte, need_whitespace, is_whitespace, is_indention bool) error {
+ if need_whitespace && !emitter.whitespace {
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeAll(indicator); err != nil {
+ return err
+ }
+ emitter.whitespace = is_whitespace
+ emitter.indention = (emitter.indention && is_indention)
+ emitter.OpenEnded = false
+ return nil
+}
+
+func (emitter *Emitter) writeAnchor(value []byte) error {
+ if err := emitter.writeAll(value); err != nil {
+ return err
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return nil
+}
+
+func (emitter *Emitter) writeTagHandle(value []byte) error {
+ if !emitter.whitespace {
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeAll(value); err != nil {
+ return err
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return nil
+}
+
+func (emitter *Emitter) writeTagContent(value []byte, need_whitespace bool) error {
+ if need_whitespace && !emitter.whitespace {
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+ for i := 0; i < len(value); {
+ var must_write bool
+ switch value[i] {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+ must_write = true
+ default:
+ must_write = isAlpha(value, i)
+ }
+ if must_write {
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ } else {
+ w := width(value[i])
+ for k := 0; k < w; k++ {
+ octet := value[i]
+ i++
+ if err := emitter.put('%'); err != nil {
+ return err
+ }
+
+ c := octet >> 4
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if err := emitter.put(c); err != nil {
+ return err
+ }
+
+ c = octet & 0x0f
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if err := emitter.put(c); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return nil
+}
+
+func (emitter *Emitter) writePlainScalar(value []byte, allow_breaks bool) error {
+ if len(value) > 0 && !emitter.whitespace {
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if isSpace(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && !isSpace(value, i+1) {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ i += width(value[i])
+ } else {
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ }
+ spaces = true
+ } else if isLineBreak(value, i) {
+ if !breaks && value[i] == '\n' {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeLineBreak(value, &i); err != nil {
+ return err
+ }
+ breaks = true
+ } else {
+ if breaks {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+
+ if len(value) > 0 {
+ emitter.whitespace = false
+ }
+ emitter.indention = false
+ if emitter.root_context {
+ emitter.OpenEnded = true
+ }
+
+ return nil
+}
+
+func (emitter *Emitter) writeSingleQuotedScalar(value []byte, allow_breaks bool) error {
+ if err := emitter.writeIndicator([]byte{'\''}, true, false, false); err != nil {
+ return err
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if isSpace(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !isSpace(value, i+1) {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ i += width(value[i])
+ } else {
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ }
+ spaces = true
+ } else if isLineBreak(value, i) {
+ if !breaks && value[i] == '\n' {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.writeLineBreak(value, &i); err != nil {
+ return err
+ }
+ breaks = true
+ } else {
+ if breaks {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if value[i] == '\'' {
+ if err := emitter.put('\''); err != nil {
+ return err
+ }
+ }
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+ if err := emitter.writeIndicator([]byte{'\''}, false, false, false); err != nil {
+ return err
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return nil
+}
+
+func (emitter *Emitter) writeDoubleQuotedScalar(value []byte, allow_breaks bool) error {
+ spaces := false
+ if err := emitter.writeIndicator([]byte{'"'}, true, false, false); err != nil {
+ return err
+ }
+
+ for i := 0; i < len(value); {
+ if !isPrintable(value, i) || (!emitter.unicode && !isASCII(value, i)) ||
+ isBOM(value, i) || isLineBreak(value, i) ||
+ value[i] == '"' || value[i] == '\\' {
+
+ octet := value[i]
+
+ var w int
+ var v rune
+ switch {
+ case octet&0x80 == 0x00:
+ w, v = 1, rune(octet&0x7F)
+ case octet&0xE0 == 0xC0:
+ w, v = 2, rune(octet&0x1F)
+ case octet&0xF0 == 0xE0:
+ w, v = 3, rune(octet&0x0F)
+ case octet&0xF8 == 0xF0:
+ w, v = 4, rune(octet&0x07)
+ }
+ for k := 1; k < w; k++ {
+ octet = value[i+k]
+ v = (v << 6) + (rune(octet) & 0x3F)
+ }
+ i += w
+
+ if err := emitter.put('\\'); err != nil {
+ return err
+ }
+
+ var err error
+ switch v {
+ case 0x00:
+ err = emitter.put('0')
+ case 0x07:
+ err = emitter.put('a')
+ case 0x08:
+ err = emitter.put('b')
+ case 0x09:
+ err = emitter.put('t')
+ case 0x0A:
+ err = emitter.put('n')
+ case 0x0b:
+ err = emitter.put('v')
+ case 0x0c:
+ err = emitter.put('f')
+ case 0x0d:
+ err = emitter.put('r')
+ case 0x1b:
+ err = emitter.put('e')
+ case 0x22:
+ err = emitter.put('"')
+ case 0x5c:
+ err = emitter.put('\\')
+ case 0x85:
+ err = emitter.put('N')
+ case 0xA0:
+ err = emitter.put('_')
+ case 0x2028:
+ err = emitter.put('L')
+ case 0x2029:
+ err = emitter.put('P')
+ default:
+ if v <= 0xFF {
+ err = emitter.put('x')
+ w = 2
+ } else if v <= 0xFFFF {
+ err = emitter.put('u')
+ w = 4
+ } else {
+ err = emitter.put('U')
+ w = 8
+ }
+ for k := (w - 1) * 4; err == nil && k >= 0; k -= 4 {
+ digit := byte((v >> uint(k)) & 0x0F)
+ if digit < 10 {
+ err = emitter.put(digit + '0')
+ } else {
+ err = emitter.put(digit + 'A' - 10)
+ }
+ }
+ }
+ if err != nil {
+ return err
+ }
+ spaces = false
+ } else if isSpace(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ if isSpace(value, i+1) {
+ if err := emitter.put('\\'); err != nil {
+ return err
+ }
+ }
+ i += width(value[i])
+ } else if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ spaces = true
+ } else {
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ spaces = false
+ }
+ }
+ if err := emitter.writeIndicator([]byte{'"'}, false, false, false); err != nil {
+ return err
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return nil
+}
+
+func (emitter *Emitter) writeBlockScalarHints(value []byte) error {
+ if isSpace(value, 0) {
+ // https://github.com/yaml/go-yaml/issues/65
+ // isLineBreak(value, 0) removed as the linebreak will only write the indentation value.
+ indent_hint := []byte{'0' + byte(emitter.BestIndent)}
+ if err := emitter.writeIndicator(indent_hint, false, false, false); err != nil {
+ return err
+ }
+ }
+
+ emitter.OpenEnded = false
+
+ var chomp_hint [1]byte
+ if len(value) == 0 {
+ chomp_hint[0] = '-'
+ } else {
+ i := len(value) - 1
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if !isLineBreak(value, i) {
+ chomp_hint[0] = '-'
+ } else if i == 0 {
+ chomp_hint[0] = '+'
+ emitter.OpenEnded = true
+ } else {
+ i--
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if isLineBreak(value, i) {
+ chomp_hint[0] = '+'
+ emitter.OpenEnded = true
+ }
+ }
+ }
+ if chomp_hint[0] != 0 {
+ if err := emitter.writeIndicator(chomp_hint[:], false, false, false); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (emitter *Emitter) writeLiteralScalar(value []byte) error {
+ if err := emitter.writeIndicator([]byte{'|'}, true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeBlockScalarHints(value); err != nil {
+ return err
+ }
+ if err := emitter.processLineCommentLinebreak(true); err != nil {
+ return err
+ }
+ emitter.whitespace = true
+ breaks := true
+ for i := 0; i < len(value); {
+ if isLineBreak(value, i) {
+ if err := emitter.writeLineBreak(value, &i); err != nil {
+ return err
+ }
+ breaks = true
+ } else {
+ if breaks {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+
+ return nil
+}
+
+func (emitter *Emitter) writeFoldedScalar(value []byte) error {
+ if err := emitter.writeIndicator([]byte{'>'}, true, false, false); err != nil {
+ return err
+ }
+ if err := emitter.writeBlockScalarHints(value); err != nil {
+ return err
+ }
+ if err := emitter.processLineCommentLinebreak(true); err != nil {
+ return err
+ }
+
+ emitter.whitespace = true
+
+ breaks := true
+ leading_spaces := true
+ for i := 0; i < len(value); {
+ if isLineBreak(value, i) {
+ if !breaks && !leading_spaces && value[i] == '\n' {
+ k := 0
+ for isLineBreak(value, k) {
+ k += width(value[k])
+ }
+ if !isBlankOrZero(value, k) {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+ }
+ if err := emitter.writeLineBreak(value, &i); err != nil {
+ return err
+ }
+ breaks = true
+ } else {
+ if breaks {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ leading_spaces = isBlank(value, i)
+ }
+ if !breaks && isSpace(value, i) && !isSpace(value, i+1) && emitter.column > emitter.best_width {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ i += width(value[i])
+ } else {
+ if err := emitter.write(value, &i); err != nil {
+ return err
+ }
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ return nil
+}
+
+func (emitter *Emitter) writeComment(comment []byte) error {
+ breaks := false
+ pound := false
+ for i := 0; i < len(comment); {
+ if isLineBreak(comment, i) {
+ if err := emitter.writeLineBreak(comment, &i); err != nil {
+ return err
+ }
+ breaks = true
+ pound = false
+ } else {
+ if breaks {
+ if err := emitter.writeIndent(); err != nil {
+ return err
+ }
+ }
+ if !pound {
+ if comment[i] != '#' {
+ if err := emitter.put('#'); err != nil {
+ return err
+ }
+ if err := emitter.put(' '); err != nil {
+ return err
+ }
+ }
+ pound = true
+ }
+ if err := emitter.write(comment, &i); err != nil {
+ return err
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ if !breaks {
+ if err := emitter.putLineBreak(); err != nil {
+ return err
+ }
+ }
+
+ emitter.whitespace = true
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/errors.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/errors.go
new file mode 100644
index 00000000000..8b279bfdaa7
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/errors.go
@@ -0,0 +1,171 @@
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Error types for YAML parsing and emitting.
+// Provides structured error reporting with line/column information.
+
+package libyaml
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+)
+
+type MarkedYAMLError struct {
+ // optional context
+ ContextMark Mark
+ ContextMessage string
+
+ Mark Mark
+ Message string
+}
+
+func (e MarkedYAMLError) Error() string {
+ var builder strings.Builder
+ builder.WriteString("yaml: ")
+ if len(e.ContextMessage) > 0 {
+ fmt.Fprintf(&builder, "%s at %s: ", e.ContextMessage, e.ContextMark)
+ }
+ if len(e.ContextMessage) == 0 || e.ContextMark != e.Mark {
+ fmt.Fprintf(&builder, "%s: ", e.Mark)
+ }
+ builder.WriteString(e.Message)
+ return builder.String()
+}
+
+type ParserError MarkedYAMLError
+
+func (e ParserError) Error() string {
+ return MarkedYAMLError(e).Error()
+}
+
+type ScannerError MarkedYAMLError
+
+func (e ScannerError) Error() string {
+ return MarkedYAMLError(e).Error()
+}
+
+type ReaderError struct {
+ Offset int
+ Value int
+ Err error
+}
+
+func (e ReaderError) Error() string {
+ return fmt.Sprintf("yaml: offset %d: %s", e.Offset, e.Err)
+}
+
+func (e ReaderError) Unwrap() error {
+ return e.Err
+}
+
+type EmitterError struct {
+ Message string
+}
+
+func (e EmitterError) Error() string {
+ return fmt.Sprintf("yaml: %s", e.Message)
+}
+
+type WriterError struct {
+ Err error
+}
+
+func (e WriterError) Error() string {
+ return fmt.Sprintf("yaml: %s", e.Err)
+}
+
+func (e WriterError) Unwrap() error {
+ return e.Err
+}
+
+// ConstructError represents a single, non-fatal error that occurred during
+// the constructing of a YAML document into a Go value.
+type ConstructError struct {
+ Err error
+ Line int
+ Column int
+}
+
+func (e *ConstructError) Error() string {
+ return fmt.Sprintf("line %d: %s", e.Line, e.Err.Error())
+}
+
+func (e *ConstructError) Unwrap() error {
+ return e.Err
+}
+
+// LoadErrors is returned when one or more fields cannot be properly decoded.
+type LoadErrors struct {
+ Errors []*ConstructError
+}
+
+func (e *LoadErrors) Error() string {
+ var b strings.Builder
+ b.WriteString("yaml: construct errors:")
+ for _, err := range e.Errors {
+ b.WriteString("\n ")
+ b.WriteString(err.Error())
+ }
+ return b.String()
+}
+
+// As implements errors.As for Go versions prior to 1.20 that don't support
+// the Unwrap() []error interface. It allows [LoadErrors] to match against
+// *ConstructError targets by returning the first error in the list.
+func (e *LoadErrors) As(target any) bool {
+ switch t := target.(type) {
+ case **ConstructError:
+ if len(e.Errors) == 0 {
+ return false
+ }
+ *t = e.Errors[0]
+ return true
+ case **TypeError:
+ var msgs []string
+ for _, err := range e.Errors {
+ msgs = append(msgs, err.Error())
+ }
+ *t = &TypeError{Errors: msgs}
+ return true
+ }
+ return false
+}
+
+// Is implements errors.Is for Go versions prior to 1.20 that don't support
+// the Unwrap() []error interface. It checks if any wrapped error matches
+// the target error.
+func (e *LoadErrors) Is(target error) bool {
+ for _, err := range e.Errors {
+ if errors.Is(err, target) {
+ return true
+ }
+ }
+ return false
+}
+
+// TypeError is an obsolete error type retained for compatibility.
+//
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+//
+// Deprecated: Use [LoadErrors] instead.
+type TypeError struct {
+ Errors []string
+}
+
+func (e *TypeError) Error() string {
+ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
+}
+
+// YAMLError is an internal error wrapper type.
+type YAMLError struct {
+ Err error
+}
+
+func (e *YAMLError) Error() string {
+ return e.Err.Error()
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/node.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/node.go
new file mode 100644
index 00000000000..48b2582251b
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/node.go
@@ -0,0 +1,363 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Node types and constants for YAML tree representation.
+// Defines Kind, Style, and Node structure for intermediate YAML representation.
+
+package libyaml
+
+import (
+ "reflect"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// Tag constants for YAML types
+const (
+ nullTag = "!!null"
+ boolTag = "!!bool"
+ strTag = "!!str"
+ intTag = "!!int"
+ floatTag = "!!float"
+ timestampTag = "!!timestamp"
+ seqTag = "!!seq"
+ mapTag = "!!map"
+ binaryTag = "!!binary"
+ mergeTag = "!!merge"
+)
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+var (
+ longTags = make(map[string]string)
+ shortTags = make(map[string]string)
+)
+
+func init() {
+ for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
+ ltag := longTag(stag)
+ longTags[stag] = ltag
+ shortTags[ltag] = stag
+ }
+}
+
+func shortTag(tag string) string {
+ if strings.HasPrefix(tag, longTagPrefix) {
+ if stag, ok := shortTags[tag]; ok {
+ return stag
+ }
+ return "!!" + tag[len(longTagPrefix):]
+ }
+ return tag
+}
+
+func longTag(tag string) string {
+ if strings.HasPrefix(tag, "!!") {
+ if ltag, ok := longTags[tag]; ok {
+ return ltag
+ }
+ return longTagPrefix + tag[2:]
+ }
+ return tag
+}
+
+// Kind represents the type of YAML node
+type Kind uint32
+
+const (
+ DocumentNode Kind = 1 << iota
+ SequenceNode
+ MappingNode
+ ScalarNode
+ AliasNode
+ StreamNode
+)
+
+// Style represents the formatting style of a YAML node
+type Style uint32
+
+const (
+ TaggedStyle Style = 1 << iota
+ DoubleQuotedStyle
+ SingleQuotedStyle
+ LiteralStyle
+ FoldedStyle
+ FlowStyle
+)
+
+// StreamVersionDirective represents a YAML %YAML version directive for stream nodes.
+type StreamVersionDirective struct {
+ Major int
+ Minor int
+}
+
+// StreamTagDirective represents a YAML %TAG directive for stream nodes.
+type StreamTagDirective struct {
+ Handle string
+ Prefix string
+}
+
+// Node represents an element in the YAML document hierarchy. While documents
+// are typically encoded and decoded into higher level types, such as structs
+// and maps, Node is an intermediate representation that allows detailed
+// control over the content being decoded or encoded.
+//
+// It's worth noting that although Node offers access into details such as
+// line numbers, columns, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data pleasantly, and to preserve comments near the data they
+// describe, though.
+//
+// Values that make use of the Node type interact with the yaml package in the
+// same way any other type would do, by encoding and decoding yaml data
+// directly or indirectly into them.
+//
+// For example:
+//
+// var person struct {
+// Name string
+// Address yaml.Node
+// }
+// err := yaml.Unmarshal(data, &person)
+//
+// Or by itself:
+//
+// var person Node
+// err := yaml.Unmarshal(data, &person)
+type Node struct {
+ // Kind defines whether the node is a document, a mapping, a sequence,
+ // a scalar value, or an alias to another node. The specific data type of
+ // scalar nodes may be obtained via the ShortTag and LongTag methods.
+ Kind Kind
+
+ // Style allows customizing the appearance of the node in the tree.
+ Style Style
+
+ // Tag holds the YAML tag defining the data type for the value.
+ // When decoding, this field will always be set to the resolved tag,
+ // even when it wasn't explicitly provided in the YAML content.
+ // When encoding, if this field is unset the value type will be
+ // implied from the node properties, and if it is set, it will only
+ // be serialized into the representation if TaggedStyle is used or
+ // the implicit tag diverges from the provided one.
+ Tag string
+
+ // Value holds the unescaped and unquoted representation of the value.
+ Value string
+
+ // Anchor holds the anchor name for this node, which allows aliases to point to it.
+ Anchor string
+
+ // Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
+ Alias *Node
+
+ // Content holds contained nodes for documents, mappings, and sequences.
+ Content []*Node
+
+ // HeadComment holds any comments in the lines preceding the node and
+ // not separated by an empty line.
+ HeadComment string
+
+ // LineComment holds any comments at the end of the line where the node is in.
+ LineComment string
+
+ // FootComment holds any comments following the node and before empty lines.
+ FootComment string
+
+ // Line and Column hold the node position in the decoded YAML text.
+ // These fields are not respected when encoding the node.
+ Line int
+ Column int
+
+ // StreamNode-specific fields (only valid when Kind == StreamNode)
+
+ // Encoding holds the stream encoding (UTF-8, UTF-16LE, UTF-16BE).
+ // Only valid for StreamNode.
+ Encoding Encoding
+
+ // Version holds the YAML version directive (%YAML).
+ // Only valid for StreamNode.
+ Version *StreamVersionDirective
+
+ // TagDirectives holds the %TAG directives.
+ // Only valid for StreamNode.
+ TagDirectives []StreamTagDirective
+}
+
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+ return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+ n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 &&
+ n.Encoding == 0 && n.Version == nil && n.TagDirectives == nil
+}
+
+// LongTag returns the long form of the tag that indicates the data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) LongTag() string {
+ return longTag(n.ShortTag())
+}
+
+// ShortTag returns the short form of the YAML tag that indicates data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) ShortTag() string {
+ if n.indicatedString() {
+ return strTag
+ }
+ if n.Tag == "" || n.Tag == "!" {
+ switch n.Kind {
+ case MappingNode:
+ return mapTag
+ case SequenceNode:
+ return seqTag
+ case AliasNode:
+ if n.Alias != nil {
+ return n.Alias.ShortTag()
+ }
+ case ScalarNode:
+ return strTag
+ case 0:
+ // Special case to make the zero value convenient.
+ if n.IsZero() {
+ return nullTag
+ }
+ }
+ return ""
+ }
+ return shortTag(n.Tag)
+}
+
+func (n *Node) indicatedString() bool {
+ return n.Kind == ScalarNode &&
+ (shortTag(n.Tag) == strTag ||
+ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
+}
+
+// shouldUseLiteralStyle determines if a string should use literal style.
+// It returns true if the string contains newlines AND meets additional criteria:
+// - is at least 2 characters long
+// - contains at least one non-whitespace character
+func shouldUseLiteralStyle(s string) bool {
+ if !strings.Contains(s, "\n") || len(s) < 2 {
+ return false
+ }
+ // Must contain at least one non-whitespace character
+ for _, r := range s {
+ if !unicode.IsSpace(r) {
+ return true
+ }
+ }
+ return false
+}
+
+// SetString is a convenience function that sets the node to a string value
+// and defines its style in a pleasant way depending on its content.
+func (n *Node) SetString(s string) {
+ n.Kind = ScalarNode
+ if utf8.ValidString(s) {
+ n.Value = s
+ n.Tag = strTag
+ } else {
+ n.Value = encodeBase64(s)
+ n.Tag = binaryTag
+ }
+ if shouldUseLiteralStyle(n.Value) {
+ n.Style = LiteralStyle
+ }
+}
+
+// Decode decodes the node and stores its data into the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (n *Node) Decode(v any) (err error) {
+ d := NewConstructor(DefaultOptions)
+ defer handleErr(&err)
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Pointer && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.Construct(n, out)
+ if len(d.TypeErrors) > 0 {
+ return &LoadErrors{Errors: d.TypeErrors}
+ }
+ return nil
+}
+
+// Load decodes the node and stores its data into the value pointed to by v,
+// applying the given options.
+//
+// This method is useful when you need to preserve options like WithKnownFields()
+// inside custom UnmarshalYAML implementations.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as v
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary. The v parameter
+// must not be nil.
+//
+// See the documentation of the package-level Load function for details
+// about YAML to Go conversion and tag options.
+func (n *Node) Load(v any, opts ...Option) (err error) {
+ defer handleErr(&err)
+ o, err := ApplyOptions(opts...)
+ if err != nil {
+ return err
+ }
+ d := NewConstructor(o)
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Pointer && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.Construct(n, out)
+ if len(d.TypeErrors) > 0 {
+ return &LoadErrors{Errors: d.TypeErrors}
+ }
+ return nil
+}
+
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v any) (err error) {
+ defer handleErr(&err)
+ e := NewRepresenter(noWriter, DefaultOptions)
+ defer e.Destroy()
+ e.MarshalDoc("", reflect.ValueOf(v))
+ e.Finish()
+ p := NewComposer(e.Out)
+ p.Textless = true
+ defer p.Destroy()
+ doc := p.Parse()
+ *n = *doc.Content[0]
+ return nil
+}
+
+// Dump encodes value v and stores its representation in n,
+// applying the given options.
+//
+// This method is useful when you need to apply specific encoding options
+// while building Node trees programmatically.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Dump(v any, opts ...Option) (err error) {
+ defer handleErr(&err)
+ o, err := ApplyOptions(opts...)
+ if err != nil {
+ return err
+ }
+ e := NewRepresenter(noWriter, o)
+ defer e.Destroy()
+ e.MarshalDoc("", reflect.ValueOf(v))
+ e.Finish()
+ p := NewComposer(e.Out)
+ p.Textless = true
+ defer p.Destroy()
+ doc := p.Parse()
+ *n = *doc.Content[0]
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/options.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/options.go
new file mode 100644
index 00000000000..a21c53c06a1
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/options.go
@@ -0,0 +1,390 @@
+//
+// Copyright (c) 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// Options configuration for loading and dumping YAML.
+// Provides centralized control for indentation, line width, strictness, and
+// more.
+
+package libyaml
+
+import (
+ "errors"
+ "fmt"
+)
+
+// Options holds configuration for both loading and dumping YAML.
+type Options struct {
+ // Loading options
+ KnownFields bool // Enforce known fields in structs
+ SingleDocument bool // Only load first document
+ UniqueKeys bool // Enforce unique keys in mappings
+ StreamNodes bool // Enable stream node emission
+ AllDocuments bool // Load/Dump all documents in multi-document streams
+
+ // Dumping options
+ Indent int // Indentation spaces (2-9)
+ CompactSeqIndent bool // Whether '- ' counts as indentation
+ LineWidth int // Preferred line width (-1 for unlimited)
+ Unicode bool // Allow non-ASCII characters
+ Canonical bool // Canonical YAML output
+ LineBreak LineBreak // Line ending style
+ ExplicitStart bool // Always emit ---
+ ExplicitEnd bool // Always emit ...
+ FlowSimpleCollections bool // Use flow style for simple collections
+ QuotePreference QuoteStyle // Preferred quote style when quoting is required
+}
+
+// Option allows configuring YAML loading and dumping operations.
+type Option func(*Options) error
+
+// WithIndent sets the number of spaces to use for indentation when
+// dumping YAML content.
+//
+// Valid values are 2-9. Common choices: 2 (compact), 4 (readable).
+func WithIndent(indent int) Option {
+ return func(o *Options) error {
+ if indent < 2 || indent > 9 {
+ return errors.New("yaml: indent must be between 2 and 9 spaces")
+ }
+ o.Indent = indent
+ return nil
+ }
+}
+
+// WithCompactSeqIndent configures whether the sequence indicator '- ' is
+// considered part of the indentation when dumping YAML content.
+//
+// If compact is true, '- ' is treated as part of the indentation.
+// If compact is false, '- ' is not treated as part of the indentation.
+// When called without arguments, defaults to true.
+func WithCompactSeqIndent(compact ...bool) Option {
+ if len(compact) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithCompactSeqIndent accepts at most one argument")
+ }
+ }
+ val := len(compact) == 0 || compact[0]
+ return func(o *Options) error {
+ o.CompactSeqIndent = val
+ return nil
+ }
+}
+
+// WithKnownFields enables or disables strict field checking during YAML loading.
+//
+// When enabled, loading will return an error if the YAML input contains fields
+// that do not correspond to any fields in the target struct.
+// When called without arguments, defaults to true.
+func WithKnownFields(knownFields ...bool) Option {
+ if len(knownFields) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithKnownFields accepts at most one argument")
+ }
+ }
+ val := len(knownFields) == 0 || knownFields[0]
+ return func(o *Options) error {
+ o.KnownFields = val
+ return nil
+ }
+}
+
+// WithSingleDocument configures the Loader to only process the first document
+// in a YAML stream. After the first document is loaded, subsequent calls to
+// Load will return io.EOF.
+//
+// When called without arguments, defaults to true.
+//
+// This is useful when you expect exactly one document and want behavior
+// similar to [Unmarshal].
+func WithSingleDocument(singleDocument ...bool) Option {
+ if len(singleDocument) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithSingleDocument accepts at most one argument")
+ }
+ }
+ val := len(singleDocument) == 0 || singleDocument[0]
+ return func(o *Options) error {
+ o.SingleDocument = val
+ return nil
+ }
+}
+
+// WithStreamNodes enables returning stream boundary nodes when loading YAML.
+//
+// When enabled, Loader.Load returns an interleaved sequence of StreamNode and
+// DocumentNode values:
+//
+// [StreamNode, DocNode, StreamNode, DocNode, ..., StreamNode]
+//
+// StreamNodes contain metadata about the stream including:
+// - Encoding (UTF-8, UTF-16LE, UTF-16BE)
+// - YAML version directive (%YAML)
+// - Tag directives (%TAG)
+// - Position information (Line, Column)
+//
+// An empty YAML stream returns a single StreamNode.
+// When called without arguments, defaults to true.
+//
+// The default is false.
+func WithStreamNodes(enable ...bool) Option {
+ if len(enable) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithStreamNodes accepts at most one argument")
+ }
+ }
+ val := len(enable) == 0 || enable[0]
+ return func(o *Options) error {
+ o.StreamNodes = val
+ return nil
+ }
+}
+
+// WithAllDocuments enables multi-document mode for Load and Dump operations.
+//
+// When used with Load, the target must be a pointer to a slice.
+// All documents in the YAML stream will be decoded into the slice.
+// Zero documents results in an empty slice (no error).
+//
+// When used with Dump, the input must be a slice.
+// Each element will be encoded as a separate YAML document
+// with "---" separators.
+//
+// When called without arguments, defaults to true.
+//
+// The default is false (single-document mode).
+func WithAllDocuments(all ...bool) Option {
+ if len(all) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithAllDocuments accepts at most one argument")
+ }
+ }
+ val := len(all) == 0 || all[0]
+ return func(o *Options) error {
+ o.AllDocuments = val
+ return nil
+ }
+}
+
+// WithLineWidth sets the preferred line width for YAML output.
+//
+// When encoding long strings, the encoder will attempt to wrap them at this
+// width using literal block style (|). Set to -1 or 0 for unlimited width.
+//
+// The default is 80 characters.
+func WithLineWidth(width int) Option {
+ return func(o *Options) error {
+ if width < 0 {
+ width = -1
+ }
+ o.LineWidth = width
+ return nil
+ }
+}
+
+// WithUnicode controls whether non-ASCII characters are allowed in YAML output.
+//
+// When true, non-ASCII characters appear as-is (e.g., "café").
+// When false, non-ASCII characters are escaped (e.g., "caf\u00e9").
+// When called without arguments, defaults to true.
+//
+// The default is true.
+func WithUnicode(unicode ...bool) Option {
+ if len(unicode) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithUnicode accepts at most one argument")
+ }
+ }
+ val := len(unicode) == 0 || unicode[0]
+ return func(o *Options) error {
+ o.Unicode = val
+ return nil
+ }
+}
+
+// WithUniqueKeys enables or disables duplicate key detection during YAML loading.
+//
+// When enabled, loading will return an error if the YAML input contains
+// duplicate keys in any mapping. This is a security feature that prevents
+// key override attacks.
+// When called without arguments, defaults to true.
+//
+// The default is true.
+func WithUniqueKeys(uniqueKeys ...bool) Option {
+ if len(uniqueKeys) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithUniqueKeys accepts at most one argument")
+ }
+ }
+ val := len(uniqueKeys) == 0 || uniqueKeys[0]
+ return func(o *Options) error {
+ o.UniqueKeys = val
+ return nil
+ }
+}
+
+// WithCanonical forces canonical YAML output format.
+//
+// When enabled, the encoder outputs strictly canonical YAML with explicit
+// tags for all values. This produces verbose output primarily useful for
+// debugging and YAML spec compliance testing.
+// When called without arguments, defaults to true.
+//
+// The default is false.
+func WithCanonical(canonical ...bool) Option {
+ if len(canonical) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithCanonical accepts at most one argument")
+ }
+ }
+ val := len(canonical) == 0 || canonical[0]
+ return func(o *Options) error {
+ o.Canonical = val
+ return nil
+ }
+}
+
+// WithLineBreak sets the line ending style for YAML output.
+//
+// Available options:
+// - LineBreakLN: Unix-style \n (default)
+// - LineBreakCR: Old Mac-style \r
+// - LineBreakCRLN: Windows-style \r\n
+//
+// The default is LineBreakLN.
+func WithLineBreak(lineBreak LineBreak) Option {
+ return func(o *Options) error {
+ o.LineBreak = lineBreak
+ return nil
+ }
+}
+
+// WithExplicitStart controls whether document start markers (---) are always emitted.
+//
+// When true, every document begins with an explicit "---" marker.
+// When false (default), the marker is omitted for the first document.
+// When called without arguments, defaults to true.
+func WithExplicitStart(explicit ...bool) Option {
+ if len(explicit) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithExplicitStart accepts at most one argument")
+ }
+ }
+ val := len(explicit) == 0 || explicit[0]
+ return func(o *Options) error {
+ o.ExplicitStart = val
+ return nil
+ }
+}
+
+// WithExplicitEnd controls whether document end markers (...) are always emitted.
+//
+// When true, every document ends with an explicit "..." marker.
+// When false (default), the marker is omitted.
+// When called without arguments, defaults to true.
+func WithExplicitEnd(explicit ...bool) Option {
+ if len(explicit) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithExplicitEnd accepts at most one argument")
+ }
+ }
+ val := len(explicit) == 0 || explicit[0]
+ return func(o *Options) error {
+ o.ExplicitEnd = val
+ return nil
+ }
+}
+
+// WithFlowSimpleCollections controls whether simple collections use flow style.
+//
+// When true, sequences and mappings containing only scalar values (no nested
+// collections) are rendered in flow style if they fit within the line width.
+// Example: {name: test, count: 42} or [a, b, c]
+// When called without arguments, defaults to true.
+//
+// When false (default), all collections use block style.
+func WithFlowSimpleCollections(flow ...bool) Option {
+ if len(flow) > 1 {
+ return func(o *Options) error {
+ return errors.New("yaml: WithFlowSimpleCollections accepts at most one argument")
+ }
+ }
+ val := len(flow) == 0 || flow[0]
+ return func(o *Options) error {
+ o.FlowSimpleCollections = val
+ return nil
+ }
+}
+
+// WithQuotePreference sets the preferred quote style for strings that require
+// quoting.
+//
+// This option only affects strings that require quoting per the YAML spec.
+// Plain strings that don't need quoting remain unquoted regardless of this
+// setting. Quoting is required for:
+// - Strings that look like other YAML types (true, false, null, 123, etc.)
+// - Strings with leading/trailing whitespace
+// - Strings containing special YAML syntax characters
+// - Empty strings in certain contexts
+//
+// Quote styles:
+// - QuoteSingle: Use single quotes (v4 default)
+// - QuoteDouble: Use double quotes
+// - QuoteLegacy: Legacy v2/v3 behavior (mixed quoting)
+func WithQuotePreference(style QuoteStyle) Option {
+ return func(o *Options) error {
+ switch style {
+ case QuoteSingle, QuoteDouble, QuoteLegacy:
+ o.QuotePreference = style
+ return nil
+ default:
+ return fmt.Errorf("invalid QuoteStyle value: %d", style)
+ }
+ }
+}
+
+// CombineOptions combines multiple options into a single Option.
+// This is useful for creating option presets or combining version defaults
+// with custom options.
+func CombineOptions(opts ...Option) Option {
+ return func(o *Options) error {
+ for _, opt := range opts {
+ if err := opt(o); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+}
+
+// ApplyOptions applies the given options to a new options struct.
+// Starts with v4 defaults.
+func ApplyOptions(opts ...Option) (*Options, error) {
+ o := &Options{
+ Canonical: false,
+ LineBreak: LN_BREAK,
+
+ // v4 defaults
+ Indent: 2,
+ CompactSeqIndent: true,
+ LineWidth: 80,
+ Unicode: true,
+ UniqueKeys: true,
+ }
+ for _, opt := range opts {
+ if err := opt(o); err != nil {
+ return nil, err
+ }
+ }
+ return o, nil
+}
+
+// DefaultOptions holds the default options for APIs that don't accept options.
+var DefaultOptions = &Options{
+ Indent: 4,
+ LineWidth: -1,
+ Unicode: true,
+ UniqueKeys: true,
+ QuotePreference: QuoteLegacy,
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/parser.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/parser.go
new file mode 100644
index 00000000000..34152d69596
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/parser.go
@@ -0,0 +1,1368 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Parser stage: Transforms token stream into event stream.
+// Implements a recursive-descent parser (LL(1)) following the YAML grammar specification.
+//
+// The parser implements the following grammar:
+//
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document ::= block_node DOCUMENT-END*
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// | properties (block_content | indentless_block_sequence)?
+// | block_content
+// | indentless_block_sequence
+// block_node ::= ALIAS
+// | properties block_content?
+// | block_content
+// flow_node ::= ALIAS
+// | properties flow_content?
+// | flow_content
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content ::= block_collection | flow_collection | SCALAR
+// flow_content ::= flow_collection | SCALAR
+// block_collection ::= block_sequence | block_mapping
+// flow_collection ::= flow_sequence | flow_mapping
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// block_mapping ::= BLOCK-MAPPING_START
+// ((KEY block_node_or_indentless_sequence?)?
+// (VALUE block_node_or_indentless_sequence?)?)*
+// BLOCK-END
+// flow_sequence ::= FLOW-SEQUENCE-START
+// (flow_sequence_entry FLOW-ENTRY)*
+// flow_sequence_entry?
+// FLOW-SEQUENCE-END
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping ::= FLOW-MAPPING-START
+// (flow_mapping_entry FLOW-ENTRY)*
+// flow_mapping_entry?
+// FLOW-MAPPING-END
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+package libyaml
+
+import (
+ "bytes"
+ "io"
+ "strings"
+)
+
+// Peek the next token in the token queue.
+func (parser *Parser) peekToken(out **Token) error {
+ if !parser.token_available {
+ if err := parser.fetchMoreTokens(); err != nil {
+ return err
+ }
+ }
+
+ token := &parser.tokens[parser.tokens_head]
+ parser.UnfoldComments(token)
+ *out = token
+ return nil
+}
+
+// UnfoldComments walks through the comments queue and joins all
+// comments behind the position of the provided token into the respective
+// top-level comment slices in the parser.
+func (parser *Parser) UnfoldComments(token *Token) {
+ for parser.comments_head < len(parser.comments) && token.StartMark.Index >= parser.comments[parser.comments_head].TokenMark.Index {
+ comment := &parser.comments[parser.comments_head]
+ if len(comment.Head) > 0 {
+ if token.Type == BLOCK_END_TOKEN {
+ // No heads on ends, so keep comment.Head for a follow up token.
+ break
+ }
+ if len(parser.HeadComment) > 0 {
+ parser.HeadComment = append(parser.HeadComment, '\n')
+ }
+ parser.HeadComment = append(parser.HeadComment, comment.Head...)
+ }
+ if len(comment.Foot) > 0 {
+ if len(parser.FootComment) > 0 {
+ parser.FootComment = append(parser.FootComment, '\n')
+ }
+ parser.FootComment = append(parser.FootComment, comment.Foot...)
+ }
+ if len(comment.Line) > 0 {
+ if len(parser.LineComment) > 0 {
+ parser.LineComment = append(parser.LineComment, '\n')
+ }
+ parser.LineComment = append(parser.LineComment, comment.Line...)
+ }
+ *comment = Comment{}
+ parser.comments_head++
+ }
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func (parser *Parser) skipToken() {
+ parser.token_available = false
+ parser.tokens_parsed++
+ parser.stream_end_produced = parser.tokens[parser.tokens_head].Type == STREAM_END_TOKEN
+ parser.tokens_head++
+}
+
+// Parse gets the next event.
+func (parser *Parser) Parse(event *Event) error {
+ // Erase the event object.
+ *event = Event{}
+
+ if parser.lastError != nil {
+ return parser.lastError
+ }
+
+ // No events after the end of the stream or error.
+ if parser.stream_end_produced || parser.state == PARSE_END_STATE {
+ return io.EOF
+ }
+
+ // Generate the next event.
+ if err := parser.stateMachine(event); err != nil {
+ parser.lastError = err
+ return err
+ }
+
+ return nil
+}
+
+func formatParserError(problem string, problem_mark Mark) error {
+ return ParserError{
+ Mark: problem_mark,
+ Message: problem,
+ }
+}
+
+func formatParserErrorContext(context string, context_mark Mark, problem string, problem_mark Mark) error {
+ return ParserError{
+ ContextMark: context_mark,
+ ContextMessage: context,
+
+ Mark: problem_mark,
+ Message: problem,
+ }
+}
+
+// State dispatcher.
+func (parser *Parser) stateMachine(event *Event) error {
+ // trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+ switch parser.state {
+ case PARSE_STREAM_START_STATE:
+ return parser.parseStreamStart(event)
+
+ case PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return parser.parseDocumentStart(event, true)
+
+ case PARSE_DOCUMENT_START_STATE:
+ return parser.parseDocumentStart(event, false)
+
+ case PARSE_DOCUMENT_CONTENT_STATE:
+ return parser.parseDocumentContent(event)
+
+ case PARSE_DOCUMENT_END_STATE:
+ return parser.parseDocumentEnd(event)
+
+ case PARSE_BLOCK_NODE_STATE:
+ return parser.parseNode(event, true, false)
+
+ case PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return parser.parseBlockSequenceEntry(event, true)
+
+ case PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return parser.parseBlockSequenceEntry(event, false)
+
+ case PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return parser.parseIndentlessSequenceEntry(event)
+
+ case PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return parser.parseBlockMappingKey(event, true)
+
+ case PARSE_BLOCK_MAPPING_KEY_STATE:
+ return parser.parseBlockMappingKey(event, false)
+
+ case PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return parser.parseBlockMappingValue(event)
+
+ case PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return parser.parseFlowSequenceEntry(event, true)
+
+ case PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return parser.parseFlowSequenceEntry(event, false)
+
+ case PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return parser.parseFlowSequenceEntryMappingKey(event)
+
+ case PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return parser.parseFlowSequenceEntryMappingValue(event)
+
+ case PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return parser.parseFlowSequenceEntryMappingEnd(event)
+
+ case PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return parser.parseFlowMappingKey(event, true)
+
+ case PARSE_FLOW_MAPPING_KEY_STATE:
+ return parser.parseFlowMappingKey(event, false)
+
+ case PARSE_FLOW_MAPPING_VALUE_STATE:
+ return parser.parseFlowMappingValue(event, false)
+
+ case PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return parser.parseFlowMappingValue(event, true)
+
+ default:
+ panic("invalid parser state")
+ }
+}
+
+// Parse the production:
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+//
+// ************
+func (parser *Parser) parseStreamStart(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != STREAM_START_TOKEN {
+ return formatParserError("did not find expected ", token.StartMark)
+ }
+ parser.state = PARSE_IMPLICIT_DOCUMENT_START_STATE
+ *event = Event{
+ Type: STREAM_START_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ encoding: token.encoding,
+ }
+ parser.skipToken()
+ return nil
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+//
+// *
+//
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+// *************************
+func (parser *Parser) parseDocumentStart(event *Event, implicit bool) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ // Parse extra document end indicators.
+ if !implicit {
+ for token.Type == DOCUMENT_END_TOKEN {
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ }
+ }
+
+ if implicit && token.Type != VERSION_DIRECTIVE_TOKEN &&
+ token.Type != TAG_DIRECTIVE_TOKEN &&
+ token.Type != DOCUMENT_START_TOKEN &&
+ token.Type != STREAM_END_TOKEN {
+ // Parse an implicit document.
+ if err := parser.processDirectives(nil, nil); err != nil {
+ return err
+ }
+ parser.states = append(parser.states, PARSE_DOCUMENT_END_STATE)
+ parser.state = PARSE_BLOCK_NODE_STATE
+
+ var head_comment []byte
+ if len(parser.HeadComment) > 0 {
+ // [Go] Scan the header comment backwards, and if an empty line is found, break
+ // the header so the part before the last empty line goes into the
+ // document header, while the bottom of it goes into a follow up event.
+ for i := len(parser.HeadComment) - 1; i > 0; i-- {
+ if parser.HeadComment[i] == '\n' {
+ if i == len(parser.HeadComment)-1 {
+ head_comment = parser.HeadComment[:i]
+ parser.HeadComment = parser.HeadComment[i+1:]
+ break
+ } else if parser.HeadComment[i-1] == '\n' {
+ head_comment = parser.HeadComment[:i-1]
+ parser.HeadComment = parser.HeadComment[i+1:]
+ break
+ }
+ }
+ }
+ }
+
+ *event = Event{
+ Type: DOCUMENT_START_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ Implicit: true,
+
+ HeadComment: head_comment,
+ }
+
+ } else if token.Type != STREAM_END_TOKEN {
+ // Parse an explicit document.
+ var version_directive *VersionDirective
+ var tag_directives []TagDirective
+ start_mark := token.StartMark
+ if err := parser.processDirectives(&version_directive, &tag_directives); err != nil {
+ return err
+ }
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != DOCUMENT_START_TOKEN {
+ return formatParserError(
+ "did not find expected ", token.StartMark)
+ }
+ parser.states = append(parser.states, PARSE_DOCUMENT_END_STATE)
+ parser.state = PARSE_DOCUMENT_CONTENT_STATE
+ end_mark := token.EndMark
+
+ *event = Event{
+ Type: DOCUMENT_START_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ versionDirective: version_directive,
+ tagDirectives: tag_directives,
+ Implicit: false,
+ }
+ parser.skipToken()
+
+ } else {
+ // Parse the stream end.
+ parser.state = PARSE_END_STATE
+ *event = Event{
+ Type: STREAM_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ }
+ parser.skipToken()
+ }
+
+ return nil
+}
+
+// Parse the productions:
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+// ***********
+func (parser *Parser) parseDocumentContent(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ if token.Type == VERSION_DIRECTIVE_TOKEN ||
+ token.Type == TAG_DIRECTIVE_TOKEN ||
+ token.Type == DOCUMENT_START_TOKEN ||
+ token.Type == DOCUMENT_END_TOKEN ||
+ token.Type == STREAM_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ return parser.processEmptyScalar(event,
+ token.StartMark)
+ }
+ return parser.parseNode(event, true, false)
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+//
+// *************
+//
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+func (parser *Parser) parseDocumentEnd(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ start_mark := token.StartMark
+ end_mark := token.StartMark
+
+ implicit := true
+ if token.Type == DOCUMENT_END_TOKEN {
+ end_mark = token.EndMark
+ parser.skipToken()
+ implicit = false
+ }
+
+ parser.tag_directives = parser.tag_directives[:0]
+
+ parser.state = PARSE_DOCUMENT_START_STATE
+ *event = Event{
+ Type: DOCUMENT_END_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Implicit: implicit,
+ }
+ parser.setEventComments(event)
+ if len(event.HeadComment) > 0 && len(event.FootComment) == 0 {
+ event.FootComment = event.HeadComment
+ event.HeadComment = nil
+ }
+ return nil
+}
+
+func (parser *Parser) setEventComments(event *Event) {
+ event.HeadComment = parser.HeadComment
+ event.LineComment = parser.LineComment
+ event.FootComment = parser.FootComment
+ parser.HeadComment = nil
+ parser.LineComment = nil
+ parser.FootComment = nil
+ parser.tail_comment = nil
+ parser.stem_comment = nil
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence ::=
+//
+// ALIAS
+// *****
+// | properties (block_content | indentless_block_sequence)?
+// ********** *
+// | block_content | indentless_block_sequence
+// *
+//
+// block_node ::= ALIAS
+//
+// *****
+// | properties block_content?
+// ********** *
+// | block_content
+// *
+//
+// flow_node ::= ALIAS
+//
+// *****
+// | properties flow_content?
+// ********** *
+// | flow_content
+// *
+//
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+//
+// *************************
+//
+// block_content ::= block_collection | flow_collection | SCALAR
+//
+// ******
+//
+// flow_content ::= flow_collection | SCALAR
+//
+// ******
+func (parser *Parser) parseNode(event *Event, block, indentless_sequence bool) error {
+ // defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ if token.Type == ALIAS_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ *event = Event{
+ Type: ALIAS_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ Anchor: token.Value,
+ }
+ parser.setEventComments(event)
+ parser.skipToken()
+ return nil
+ }
+
+ start_mark := token.StartMark
+ end_mark := token.StartMark
+
+ var tag_token bool
+ var tag_handle, tag_suffix, anchor []byte
+ var tag_mark Mark
+ switch token.Type {
+ case ANCHOR_TOKEN:
+ anchor = token.Value
+ start_mark = token.StartMark
+ end_mark = token.EndMark
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type == TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.Value
+ tag_suffix = token.suffix
+ tag_mark = token.StartMark
+ end_mark = token.EndMark
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ }
+ case TAG_TOKEN:
+ tag_token = true
+ tag_handle = token.Value
+ tag_suffix = token.suffix
+ start_mark = token.StartMark
+ tag_mark = token.StartMark
+ end_mark = token.EndMark
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type == ANCHOR_TOKEN {
+ anchor = token.Value
+ end_mark = token.EndMark
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ }
+ }
+
+ var tag []byte
+ if tag_token {
+ if len(tag_handle) == 0 {
+ tag = tag_suffix
+ } else {
+ for i := range parser.tag_directives {
+ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+ tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+ tag = append(tag, tag_suffix...)
+ break
+ }
+ }
+ if len(tag) == 0 {
+ return formatParserErrorContext(
+ "while parsing a node", start_mark,
+ "found undefined tag handle", tag_mark)
+ }
+ }
+ }
+
+ implicit := len(tag) == 0
+ if indentless_sequence && token.Type == BLOCK_ENTRY_TOKEN {
+ end_mark = token.EndMark
+ parser.state = PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ *event = Event{
+ Type: SEQUENCE_START_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(BLOCK_SEQUENCE_STYLE),
+ }
+ return nil
+ }
+ if token.Type == SCALAR_TOKEN {
+ var plain_implicit, quoted_implicit bool
+ end_mark = token.EndMark
+ if (len(tag) == 0 && token.Style == PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+ plain_implicit = true
+ } else if len(tag) == 0 {
+ quoted_implicit = true
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = Event{
+ Type: SCALAR_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Value: token.Value,
+ Implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ Style: Style(token.Style),
+ }
+ parser.setEventComments(event)
+ parser.skipToken()
+ return nil
+ }
+ if token.Type == FLOW_SEQUENCE_START_TOKEN {
+ // [Go] Some of the events below can be merged as they differ only on style.
+ end_mark = token.EndMark
+ parser.state = PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+ *event = Event{
+ Type: SEQUENCE_START_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(FLOW_SEQUENCE_STYLE),
+ }
+ parser.setEventComments(event)
+ return nil
+ }
+ if token.Type == FLOW_MAPPING_START_TOKEN {
+ end_mark = token.EndMark
+ parser.state = PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+ *event = Event{
+ Type: MAPPING_START_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(FLOW_MAPPING_STYLE),
+ }
+ parser.setEventComments(event)
+ return nil
+ }
+ if block && token.Type == BLOCK_SEQUENCE_START_TOKEN {
+ end_mark = token.EndMark
+ parser.state = PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+ *event = Event{
+ Type: SEQUENCE_START_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(BLOCK_SEQUENCE_STYLE),
+ }
+ if parser.stem_comment != nil {
+ event.HeadComment = parser.stem_comment
+ parser.stem_comment = nil
+ }
+ return nil
+ }
+ if block && token.Type == BLOCK_MAPPING_START_TOKEN {
+ end_mark = token.EndMark
+ parser.state = PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+ *event = Event{
+ Type: MAPPING_START_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ Style: Style(BLOCK_MAPPING_STYLE),
+ }
+ if parser.stem_comment != nil {
+ event.HeadComment = parser.stem_comment
+ parser.stem_comment = nil
+ }
+ return nil
+ }
+ if len(anchor) > 0 || len(tag) > 0 {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = Event{
+ Type: SCALAR_EVENT,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Anchor: anchor,
+ Tag: tag,
+ Implicit: implicit,
+ quoted_implicit: false,
+ Style: Style(PLAIN_SCALAR_STYLE),
+ }
+ return nil
+ }
+
+ context := "while parsing a flow node"
+ if block {
+ context = "while parsing a block node"
+ }
+ return formatParserErrorContext(context, start_mark,
+ "did not find expected node content", token.StartMark)
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+//
+// ******************** *********** * *********
+func (parser *Parser) parseBlockSequenceEntry(event *Event, first bool) error {
+ if first {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ parser.marks = append(parser.marks, token.StartMark)
+ parser.skipToken()
+ }
+
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ if token.Type == BLOCK_ENTRY_TOKEN {
+ mark := token.EndMark
+ prior_head_len := len(parser.HeadComment)
+ parser.skipToken()
+ if err := parser.splitStemComment(prior_head_len); err != nil {
+ return err
+ }
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != BLOCK_ENTRY_TOKEN && token.Type != BLOCK_END_TOKEN {
+ parser.states = append(parser.states, PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+ return parser.parseNode(event, true, false)
+ } else {
+ parser.state = PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+ return parser.processEmptyScalar(event, mark)
+ }
+ }
+ if token.Type == BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = Event{
+ Type: SEQUENCE_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ }
+
+ parser.skipToken()
+ return nil
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return formatParserErrorContext(
+ "while parsing a block collection", context_mark,
+ "did not find expected '-' indicator", token.StartMark)
+}
+
+// Parse the productions:
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+//
+// *********** *
+func (parser *Parser) parseIndentlessSequenceEntry(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ if token.Type == BLOCK_ENTRY_TOKEN {
+ mark := token.EndMark
+ prior_head_len := len(parser.HeadComment)
+ parser.skipToken()
+ if err := parser.splitStemComment(prior_head_len); err != nil {
+ return err
+ }
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != BLOCK_ENTRY_TOKEN &&
+ token.Type != KEY_TOKEN &&
+ token.Type != VALUE_TOKEN &&
+ token.Type != BLOCK_END_TOKEN {
+ parser.states = append(parser.states, PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+ return parser.parseNode(event, true, false)
+ }
+ parser.state = PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ return parser.processEmptyScalar(event, mark)
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = Event{
+ Type: SEQUENCE_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.StartMark, // [Go] Shouldn't this be token.end_mark?
+ }
+ return nil
+}
+
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func (parser *Parser) splitStemComment(stem_len int) error {
+ if stem_len == 0 {
+ return nil
+ }
+
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != BLOCK_SEQUENCE_START_TOKEN && token.Type != BLOCK_MAPPING_START_TOKEN {
+ return nil
+ }
+
+ parser.stem_comment = parser.HeadComment[:stem_len]
+ if len(parser.HeadComment) == stem_len {
+ parser.HeadComment = nil
+ } else {
+ // Copy suffix to prevent very strange bugs if someone ever appends
+ // further bytes to the prefix in the stem_comment slice above.
+ parser.HeadComment = append([]byte(nil), parser.HeadComment[stem_len+1:]...)
+ }
+ return nil
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// *******************
+// ((KEY block_node_or_indentless_sequence?)?
+// *** *
+// (VALUE block_node_or_indentless_sequence?)?)*
+//
+// BLOCK-END
+// *********
+func (parser *Parser) parseBlockMappingKey(event *Event, first bool) error {
+ if first {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ parser.marks = append(parser.marks, token.StartMark)
+ parser.skipToken()
+ }
+
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ // [Go] A tail comment was left from the prior mapping value processed. Emit an event
+ // as it needs to be processed with that value and not the following key.
+ if len(parser.tail_comment) > 0 {
+ *event = Event{
+ Type: TAIL_COMMENT_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ FootComment: parser.tail_comment,
+ }
+ parser.tail_comment = nil
+ return nil
+ }
+
+ switch token.Type {
+ case KEY_TOKEN:
+ mark := token.EndMark
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != KEY_TOKEN &&
+ token.Type != VALUE_TOKEN &&
+ token.Type != BLOCK_END_TOKEN {
+ parser.states = append(parser.states, PARSE_BLOCK_MAPPING_VALUE_STATE)
+ return parser.parseNode(event, true, true)
+ } else {
+ parser.state = PARSE_BLOCK_MAPPING_VALUE_STATE
+ return parser.processEmptyScalar(event, mark)
+ }
+ case BLOCK_END_TOKEN:
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = Event{
+ Type: MAPPING_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ }
+ parser.setEventComments(event)
+ parser.skipToken()
+ return nil
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return formatParserErrorContext(
+ "while parsing a block mapping", context_mark,
+ "did not find expected key", token.StartMark)
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// ((KEY block_node_or_indentless_sequence?)?
+//
+// (VALUE block_node_or_indentless_sequence?)?)*
+// ***** *
+// BLOCK-END
+func (parser *Parser) parseBlockMappingValue(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type == VALUE_TOKEN {
+ mark := token.EndMark
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != KEY_TOKEN &&
+ token.Type != VALUE_TOKEN &&
+ token.Type != BLOCK_END_TOKEN {
+ parser.states = append(parser.states, PARSE_BLOCK_MAPPING_KEY_STATE)
+ return parser.parseNode(event, true, true)
+ }
+ parser.state = PARSE_BLOCK_MAPPING_KEY_STATE
+ return parser.processEmptyScalar(event, mark)
+ }
+ parser.state = PARSE_BLOCK_MAPPING_KEY_STATE
+ return parser.processEmptyScalar(event, token.StartMark)
+}
+
+// Parse the productions:
+// flow_sequence ::= FLOW-SEQUENCE-START
+//
+// *******************
+// (flow_sequence_entry FLOW-ENTRY)*
+// * **********
+// flow_sequence_entry?
+// *
+// FLOW-SEQUENCE-END
+// *****************
+//
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+// *
+func (parser *Parser) parseFlowSequenceEntry(event *Event, first bool) error {
+ if first {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ parser.marks = append(parser.marks, token.StartMark)
+ parser.skipToken()
+ }
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != FLOW_SEQUENCE_END_TOKEN {
+ if !first {
+ if token.Type == FLOW_ENTRY_TOKEN {
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return formatParserErrorContext(
+ "while parsing a flow sequence", context_mark,
+ "did not find expected ',' or ']'", token.StartMark)
+ }
+ }
+
+ if token.Type == KEY_TOKEN {
+ parser.state = PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+ *event = Event{
+ Type: MAPPING_START_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ Implicit: true,
+ Style: Style(FLOW_MAPPING_STYLE),
+ }
+ parser.skipToken()
+ return nil
+ } else if token.Type != FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+ return parser.parseNode(event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = Event{
+ Type: SEQUENCE_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ }
+ parser.setEventComments(event)
+
+ parser.skipToken()
+ return nil
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+// *** *
+func (parser *Parser) parseFlowSequenceEntryMappingKey(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != VALUE_TOKEN &&
+ token.Type != FLOW_ENTRY_TOKEN &&
+ token.Type != FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+ return parser.parseNode(event, false, false)
+ }
+ mark := token.EndMark
+ parser.skipToken()
+ parser.state = PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+ return parser.processEmptyScalar(event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+// ***** *
+func (parser *Parser) parseFlowSequenceEntryMappingValue(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type == VALUE_TOKEN {
+ parser.skipToken()
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != FLOW_ENTRY_TOKEN && token.Type != FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+ return parser.parseNode(event, false, false)
+ }
+ }
+ parser.state = PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+ return parser.processEmptyScalar(event, token.StartMark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+// *
+func (parser *Parser) parseFlowSequenceEntryMappingEnd(event *Event) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ parser.state = PARSE_FLOW_SEQUENCE_ENTRY_STATE
+ *event = Event{
+ Type: MAPPING_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.StartMark, // [Go] Shouldn't this be end_mark?
+ }
+ return nil
+}
+
+// Parse the productions:
+// flow_mapping ::= FLOW-MAPPING-START
+//
+// ******************
+// (flow_mapping_entry FLOW-ENTRY)*
+// * **********
+// flow_mapping_entry?
+// ******************
+// FLOW-MAPPING-END
+// ****************
+//
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// - *** *
+func (parser *Parser) parseFlowMappingKey(event *Event, first bool) error {
+ if first {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ parser.marks = append(parser.marks, token.StartMark)
+ parser.skipToken()
+ }
+
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ if token.Type != FLOW_MAPPING_END_TOKEN {
+ if !first {
+ if token.Type == FLOW_ENTRY_TOKEN {
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return formatParserErrorContext(
+ "while parsing a flow mapping", context_mark,
+ "did not find expected ',' or '}'", token.StartMark)
+ }
+ }
+
+ if token.Type == KEY_TOKEN {
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != VALUE_TOKEN &&
+ token.Type != FLOW_ENTRY_TOKEN &&
+ token.Type != FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, PARSE_FLOW_MAPPING_VALUE_STATE)
+ return parser.parseNode(event, false, false)
+ } else {
+ parser.state = PARSE_FLOW_MAPPING_VALUE_STATE
+ return parser.processEmptyScalar(event, token.StartMark)
+ }
+ } else if token.Type != FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+ return parser.parseNode(event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = Event{
+ Type: MAPPING_END_EVENT,
+ StartMark: token.StartMark,
+ EndMark: token.EndMark,
+ }
+ parser.setEventComments(event)
+ parser.skipToken()
+ return nil
+}
+
+// Parse the productions:
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// - ***** *
+func (parser *Parser) parseFlowMappingValue(event *Event, empty bool) error {
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if empty {
+ parser.state = PARSE_FLOW_MAPPING_KEY_STATE
+ return parser.processEmptyScalar(event, token.StartMark)
+ }
+ if token.Type == VALUE_TOKEN {
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ if token.Type != FLOW_ENTRY_TOKEN && token.Type != FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, PARSE_FLOW_MAPPING_KEY_STATE)
+ return parser.parseNode(event, false, false)
+ }
+ }
+ parser.state = PARSE_FLOW_MAPPING_KEY_STATE
+ return parser.processEmptyScalar(event, token.StartMark)
+}
+
+// Generate an empty scalar event.
+func (parser *Parser) processEmptyScalar(event *Event, mark Mark) error {
+ *event = Event{
+ Type: SCALAR_EVENT,
+ StartMark: mark,
+ EndMark: mark,
+ Value: nil, // Empty
+ Implicit: true,
+ Style: Style(PLAIN_SCALAR_STYLE),
+ }
+ return nil
+}
+
+var default_tag_directives = []TagDirective{
+ {[]byte("!"), []byte("!")},
+ {[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func (parser *Parser) processDirectives(version_directive_ref **VersionDirective, tag_directives_ref *[]TagDirective) error {
+ var version_directive *VersionDirective
+ var tag_directives []TagDirective
+
+ var token *Token
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+
+ for token.Type == VERSION_DIRECTIVE_TOKEN || token.Type == TAG_DIRECTIVE_TOKEN {
+ switch token.Type {
+ case VERSION_DIRECTIVE_TOKEN:
+ if version_directive != nil {
+ return formatParserError(
+ "found duplicate %YAML directive", token.StartMark)
+ }
+ if token.major != 1 || token.minor != 1 {
+ return formatParserError(
+ "found incompatible YAML document", token.StartMark)
+ }
+ version_directive = &VersionDirective{
+ major: token.major,
+ minor: token.minor,
+ }
+ case TAG_DIRECTIVE_TOKEN:
+ value := TagDirective{
+ handle: token.Value,
+ prefix: token.prefix,
+ }
+ if err := parser.appendTagDirective(value, false, token.StartMark); err != nil {
+ return err
+ }
+ tag_directives = append(tag_directives, value)
+ }
+
+ parser.skipToken()
+ if err := parser.peekToken(&token); err != nil {
+ return err
+ }
+ }
+
+ for i := range default_tag_directives {
+ if err := parser.appendTagDirective(default_tag_directives[i], true, token.StartMark); err != nil {
+ return err
+ }
+ }
+
+ if version_directive_ref != nil {
+ *version_directive_ref = version_directive
+ }
+ if tag_directives_ref != nil {
+ *tag_directives_ref = tag_directives
+ }
+ return nil
+}
+
+// Append a tag directive to the directives stack.
+func (parser *Parser) appendTagDirective(value TagDirective, allow_duplicates bool, mark Mark) error {
+ for i := range parser.tag_directives {
+ if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+ if allow_duplicates {
+ return nil
+ }
+ return formatParserError("found duplicate %TAG directive", mark)
+ }
+ }
+
+ // [Go] I suspect the copy is unnecessary. This was likely done
+ // because there was no way to track ownership of the data.
+ value_copy := TagDirective{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(value_copy.handle, value.handle)
+ copy(value_copy.prefix, value.prefix)
+ parser.tag_directives = append(parser.tag_directives, value_copy)
+ return nil
+}
+
+// ParserGetEvents parses the YAML input and returns the generated event stream.
+func ParserGetEvents(in []byte) (string, error) {
+ p := NewComposer(in)
+ defer p.Destroy()
+ var events strings.Builder
+ var event Event
+ for {
+ if err := p.Parser.Parse(&event); err != nil {
+ return "", err
+ }
+ formatted := formatEvent(&event)
+ events.WriteString(formatted)
+ if event.Type == STREAM_END_EVENT {
+ event.Delete()
+ break
+ }
+ event.Delete()
+ events.WriteByte('\n')
+ }
+ return events.String(), nil
+}
+
+func formatEvent(e *Event) string {
+ var b strings.Builder
+ switch e.Type {
+ case STREAM_START_EVENT:
+ b.WriteString("+STR")
+ case STREAM_END_EVENT:
+ b.WriteString("-STR")
+ case DOCUMENT_START_EVENT:
+ b.WriteString("+DOC")
+ if !e.Implicit {
+ b.WriteString(" ---")
+ }
+ case DOCUMENT_END_EVENT:
+ b.WriteString("-DOC")
+ if !e.Implicit {
+ b.WriteString(" ...")
+ }
+ case ALIAS_EVENT:
+ b.WriteString("=ALI *")
+ b.Write(e.Anchor)
+ case SCALAR_EVENT:
+ b.WriteString("=VAL")
+ if len(e.Anchor) > 0 {
+ b.WriteString(" &")
+ b.Write(e.Anchor)
+ }
+ if len(e.Tag) > 0 {
+ b.WriteString(" <")
+ b.Write(e.Tag)
+ b.WriteString(">")
+ }
+ switch e.ScalarStyle() {
+ case PLAIN_SCALAR_STYLE:
+ b.WriteString(" :")
+ case LITERAL_SCALAR_STYLE:
+ b.WriteString(" |")
+ case FOLDED_SCALAR_STYLE:
+ b.WriteString(" >")
+ case SINGLE_QUOTED_SCALAR_STYLE:
+ b.WriteString(" '")
+ case DOUBLE_QUOTED_SCALAR_STYLE:
+ b.WriteString(` "`)
+ }
+ // Escape special characters for consistent event output.
+ val := strings.NewReplacer(
+ `\`, `\\`,
+ "\n", `\n`,
+ "\t", `\t`,
+ ).Replace(string(e.Value))
+ b.WriteString(val)
+
+ case SEQUENCE_START_EVENT:
+ b.WriteString("+SEQ")
+ if len(e.Anchor) > 0 {
+ b.WriteString(" &")
+ b.Write(e.Anchor)
+ }
+ if len(e.Tag) > 0 {
+ b.WriteString(" <")
+ b.Write(e.Tag)
+ b.WriteString(">")
+ }
+ if e.SequenceStyle() == FLOW_SEQUENCE_STYLE {
+ b.WriteString(" []")
+ }
+ case SEQUENCE_END_EVENT:
+ b.WriteString("-SEQ")
+ case MAPPING_START_EVENT:
+ b.WriteString("+MAP")
+ if len(e.Anchor) > 0 {
+ b.WriteString(" &")
+ b.Write(e.Anchor)
+ }
+ if len(e.Tag) > 0 {
+ b.WriteString(" <")
+ b.Write(e.Tag)
+ b.WriteString(">")
+ }
+ if e.MappingStyle() == FLOW_MAPPING_STYLE {
+ b.WriteString(" {}")
+ }
+ case MAPPING_END_EVENT:
+ b.WriteString("-MAP")
+ }
+ return b.String()
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/reader.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/reader.go
new file mode 100644
index 00000000000..ecc00fe283e
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/reader.go
@@ -0,0 +1,441 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Input reader with encoding detection and buffering.
+// Handles BOM detection, UTF-8/UTF-16 conversion, and provides buffered input
+// for the scanner.
+
+package libyaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+)
+
+func formatReaderError(problem string, offset int, value int) error {
+ return ReaderError{
+ Offset: offset,
+ Value: value,
+ Err: errors.New(problem),
+ }
+}
+
+// Byte order marks.
+const (
+ bom_UTF8 = "\xef\xbb\xbf"
+ bom_UTF16LE = "\xff\xfe"
+ bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func (parser *Parser) determineEncoding() error {
+ // Ensure that we had enough bytes in the raw buffer.
+ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+ if err := parser.updateRawBuffer(); err != nil {
+ return err
+ }
+ }
+
+ // Determine the encoding.
+ buf := parser.raw_buffer
+ pos := parser.raw_buffer_pos
+ avail := len(buf) - pos
+ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+ parser.encoding = UTF16LE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+ parser.encoding = UTF16BE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+ parser.encoding = UTF8_ENCODING
+ parser.raw_buffer_pos += 3
+ parser.offset += 3
+ } else {
+ parser.encoding = UTF8_ENCODING
+ }
+ return nil
+}
+
+// Update the raw buffer.
+func (parser *Parser) updateRawBuffer() error {
+ size_read := 0
+
+ // Return if the raw buffer is full.
+ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+ return nil
+ }
+
+ // Return on EOF.
+ if parser.eof {
+ return nil
+ }
+
+ // Move the remaining bytes in the raw buffer to the beginning.
+ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+ }
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+ parser.raw_buffer_pos = 0
+
+ // Call the read handler to fill the buffer.
+ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+ if err == io.EOF {
+ parser.eof = true
+ } else if err != nil {
+ return ReaderError{
+ Offset: parser.offset,
+ Value: -1,
+ Err: fmt.Errorf("input error: %w", err),
+ }
+ }
+ return nil
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func (parser *Parser) updateBuffer(length int) error {
+ if parser.read_handler == nil {
+ panic("read handler must be set")
+ }
+
+ // [Go] This function was changed to guarantee the requested length size at EOF.
+ // The fact we need to do this is pretty awful, but the description above implies
+ // for that to be the case, and there are tests
+
+ // If the EOF flag is set and the raw buffer is empty, do nothing.
+ //
+ //nolint:staticcheck // there is no problem with this empty branch as it's documentation.
+ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+ // [Go] ACTUALLY! Read the documentation of this function above.
+ // This is just broken. To return true, we need to have the
+ // given length in the buffer. Not doing that means every single
+ // check that calls this function to make sure the buffer has a
+ // given length is Go) panicking; or C) accessing invalid memory.
+ // return true
+ }
+
+ // Return if the buffer contains enough characters.
+ if parser.unread >= length {
+ return nil
+ }
+
+ // Determine the input encoding if it is not known yet.
+ if parser.encoding == ANY_ENCODING {
+ if err := parser.determineEncoding(); err != nil {
+ return err
+ }
+ }
+
+ // Move the unread characters to the beginning of the buffer.
+ buffer_len := len(parser.buffer)
+ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+ copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+ buffer_len -= parser.buffer_pos
+ parser.buffer_pos = 0
+ } else if parser.buffer_pos == buffer_len {
+ buffer_len = 0
+ parser.buffer_pos = 0
+ }
+
+ // Open the whole buffer for writing, and cut it before returning.
+ parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+ // Fill the buffer until it has enough characters.
+ first := true
+ for parser.unread < length {
+
+ // Fill the raw buffer if necessary.
+ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+ if err := parser.updateRawBuffer(); err != nil {
+ parser.buffer = parser.buffer[:buffer_len]
+ return err
+ }
+ }
+ first = false
+
+ // Decode the raw buffer.
+ inner:
+ for parser.raw_buffer_pos != len(parser.raw_buffer) {
+ var value rune
+ var width int
+
+ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+ // Decode the next character.
+ switch parser.encoding {
+ case UTF8_ENCODING:
+ // Decode a UTF-8 character. Check RFC 3629
+ // (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+ //
+ // The following table (taken from the RFC) is used for
+ // decoding.
+ //
+ // Char. number range | UTF-8 octet sequence
+ // (hexadecimal) | (binary)
+ // --------------------+------------------------------------
+ // 0000 0000-0000 007F | 0xxxxxxx
+ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ //
+ // Additionally, the characters in the range 0xD800-0xDFFF
+ // are prohibited as they are reserved for use with UTF-16
+ // surrogate pairs.
+
+ // Determine the length of the UTF-8 sequence.
+ octet := parser.raw_buffer[parser.raw_buffer_pos]
+ switch {
+ case octet&0x80 == 0x00:
+ width = 1
+ case octet&0xE0 == 0xC0:
+ width = 2
+ case octet&0xF0 == 0xE0:
+ width = 3
+ case octet&0xF8 == 0xF0:
+ width = 4
+ default:
+ // The leading octet is invalid.
+ return formatReaderError(
+ "invalid leading UTF-8 octet",
+ parser.offset, int(octet))
+ }
+
+ // Check if the raw buffer contains an incomplete character.
+ if width > raw_unread {
+ if parser.eof {
+ return formatReaderError(
+ "incomplete UTF-8 octet sequence",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Decode the leading octet.
+ switch {
+ case octet&0x80 == 0x00:
+ value = rune(octet & 0x7F)
+ case octet&0xE0 == 0xC0:
+ value = rune(octet & 0x1F)
+ case octet&0xF0 == 0xE0:
+ value = rune(octet & 0x0F)
+ case octet&0xF8 == 0xF0:
+ value = rune(octet & 0x07)
+ default:
+ value = 0
+ }
+
+ // Check and decode the trailing octets.
+ for k := 1; k < width; k++ {
+ octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+ // Check if the octet is valid.
+ if (octet & 0xC0) != 0x80 {
+ return formatReaderError(
+ "invalid trailing UTF-8 octet",
+ parser.offset+k, int(octet))
+ }
+
+ // Decode the octet.
+ value = (value << 6) + rune(octet&0x3F)
+ }
+
+ // Check the length of the sequence against the value.
+ switch {
+ case width == 1:
+ case width == 2 && value >= 0x80:
+ case width == 3 && value >= 0x800:
+ case width == 4 && value >= 0x10000:
+ default:
+ return formatReaderError(
+ "invalid length of a UTF-8 sequence",
+ parser.offset, -1)
+ }
+
+ // Check the range of the value.
+ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+ return formatReaderError(
+ "invalid Unicode character",
+ parser.offset, int(value))
+ }
+
+ case UTF16LE_ENCODING, UTF16BE_ENCODING:
+ var low, high int
+ if parser.encoding == UTF16LE_ENCODING {
+ low, high = 0, 1
+ } else {
+ low, high = 1, 0
+ }
+
+ // The UTF-16 encoding is not as simple as one might
+ // naively think. Check RFC 2781
+ // (http://www.ietf.org/rfc/rfc2781.txt).
+ //
+ // Normally, two subsequent bytes describe a Unicode
+ // character. However a special technique (called a
+ // surrogate pair) is used for specifying character
+ // values larger than 0xFFFF.
+ //
+ // A surrogate pair consists of two pseudo-characters:
+ // high surrogate area (0xD800-0xDBFF)
+ // low surrogate area (0xDC00-0xDFFF)
+ //
+ // The following formulas are used for decoding
+ // and encoding characters using surrogate pairs:
+ //
+ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
+ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
+ // W1 = 110110yyyyyyyyyy
+ // W2 = 110111xxxxxxxxxx
+ //
+ // where U is the character value, W1 is the high surrogate
+ // area, W2 is the low surrogate area.
+
+ // Check for incomplete UTF-16 character.
+ if raw_unread < 2 {
+ if parser.eof {
+ return formatReaderError(
+ "incomplete UTF-16 character",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the character.
+ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+ // Check for unexpected low surrogate area.
+ if value&0xFC00 == 0xDC00 {
+ return formatReaderError(
+ "unexpected low surrogate area",
+ parser.offset, int(value))
+ }
+
+ // Check for a high surrogate area.
+ if value&0xFC00 == 0xD800 {
+ width = 4
+
+ // Check for incomplete surrogate pair.
+ if raw_unread < 4 {
+ if parser.eof {
+ return formatReaderError(
+ "incomplete UTF-16 surrogate pair",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the next character.
+ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+ // Check for a low surrogate area.
+ if value2&0xFC00 != 0xDC00 {
+ return formatReaderError(
+ "expected low surrogate area",
+ parser.offset+2, int(value2))
+ }
+
+ // Generate the value of the surrogate pair.
+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+ } else {
+ width = 2
+ }
+
+ default:
+ panic("impossible")
+ }
+
+ // YAML 1.2 compatible character sets
+ // Check if the character is in the allowed range:
+ // For JSON compatibility in quoted scalars, we must allow all
+ // non-C0 characters. This includes ASCII DEL (0x7F) and the
+ // C1 control block [#x80-#x9F].
+ // ref: https://yaml.org/spec/1.2.2/#51-character-set
+ switch {
+ // 8 bit set
+ // Tab (\t)
+ case value == 0x09:
+ // Line feed (LF \n)
+ case value == 0x0A:
+ // Carriage Return (CR \r)
+ case value == 0x0D:
+ // 16 bit set
+ // Printable ASCII
+ case value >= 0x20 && value <= 0x7E:
+ // DEL, C1 control
+ // incompatible with YAML versions <= 1.1
+ case value >= 0x7F && value <= 0x9F:
+ // and Basic Multilingual Plane (BMP),
+ case value >= 0xA0 && value <= 0xD7FF:
+ // Additional Unicode Areas
+ case value >= 0xE000 && value <= 0xFFFD:
+ // 32 bit set
+ case value >= 0x10000 && value <= 0x10FFFF:
+ default:
+ return formatReaderError(
+ "control characters are not allowed",
+ parser.offset, int(value))
+ }
+
+ // Move the raw pointers.
+ parser.raw_buffer_pos += width
+ parser.offset += width
+
+ // Finally put the character into the buffer.
+ if value <= 0x7F {
+ // 0000 0000-0000 007F . 0xxxxxxx
+ parser.buffer[buffer_len+0] = byte(value)
+ buffer_len += 1
+ } else if value <= 0x7FF {
+ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+ buffer_len += 2
+ } else if value <= 0xFFFF {
+ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+ buffer_len += 3
+ } else {
+ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+ buffer_len += 4
+ }
+
+ parser.unread++
+ }
+
+ // On EOF, put NUL into the buffer and return.
+ if parser.eof {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ parser.unread++
+ break
+ }
+ }
+ // [Go] Read the documentation of this function above. To return true,
+ // we need to have the given length in the buffer. Not doing that means
+ // every single check that calls this function to make sure the buffer
+ // has a given length is Go) panicking; or C) accessing invalid memory.
+ // This happens here due to the EOF above breaking early.
+ for buffer_len < length {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ }
+ parser.buffer = parser.buffer[:buffer_len]
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/representer.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/representer.go
new file mode 100644
index 00000000000..2f451949f1b
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/representer.go
@@ -0,0 +1,571 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Representer stage: Converts Go values to YAML nodes.
+// Handles marshaling from Go types to the intermediate node representation.
+
+package libyaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+ a := l[i]
+ b := l[j]
+ ak := a.Kind()
+ bk := b.Kind()
+ for (ak == reflect.Interface || ak == reflect.Pointer) && !a.IsNil() {
+ a = a.Elem()
+ ak = a.Kind()
+ }
+ for (bk == reflect.Interface || bk == reflect.Pointer) && !b.IsNil() {
+ b = b.Elem()
+ bk = b.Kind()
+ }
+ af, aok := keyFloat(a)
+ bf, bok := keyFloat(b)
+ if aok && bok {
+ if af != bf {
+ return af < bf
+ }
+ if ak != bk {
+ return ak < bk
+ }
+ return numLess(a, b)
+ }
+ if ak != reflect.String || bk != reflect.String {
+ return ak < bk
+ }
+ ar, br := []rune(a.String()), []rune(b.String())
+ digits := false
+ for i := 0; i < len(ar) && i < len(br); i++ {
+ if ar[i] == br[i] {
+ digits = unicode.IsDigit(ar[i])
+ continue
+ }
+ al := unicode.IsLetter(ar[i])
+ bl := unicode.IsLetter(br[i])
+ if al && bl {
+ return ar[i] < br[i]
+ }
+ if al || bl {
+ if digits {
+ return al
+ } else {
+ return bl
+ }
+ }
+ var ai, bi int
+ var an, bn int64
+ if ar[i] == '0' || br[i] == '0' {
+ for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ if ar[j] != '0' {
+ an = 1
+ bn = 1
+ break
+ }
+ }
+ }
+ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+ an = an*10 + int64(ar[ai]-'0')
+ }
+ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+ bn = bn*10 + int64(br[bi]-'0')
+ }
+ if an != bn {
+ return an < bn
+ }
+ if ai != bi {
+ return ai < bi
+ }
+ return ar[i] < br[i]
+ }
+ return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+ switch v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(v.Int()), true
+ case reflect.Float32, reflect.Float64:
+ return v.Float(), true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return float64(v.Uint()), true
+ case reflect.Bool:
+ if v.Bool() {
+ return 1, true
+ }
+ return 0, true
+ }
+ return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return a.Int() < b.Int()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ }
+ panic("not a number")
+}
+
+// Sentinel values for newRepresenter parameters.
+// These provide clarity at call sites, similar to http.NoBody.
+var (
+ noWriter io.Writer = nil
+ noVersionDirective *VersionDirective = nil
+ noTagDirective []TagDirective = nil
+)
+
+type Representer struct {
+ Emitter Emitter
+ Out []byte
+ flow bool
+ Indent int
+ lineWidth int
+ doneInit bool
+ explicitStart bool
+ explicitEnd bool
+ flowSimpleCollections bool
+ quotePreference QuoteStyle
+}
+
+// NewRepresenter creates a new YAML representr with the given options.
+//
+// The writer parameter specifies the output destination for the representr.
+// If writer is nil, the representr will write to an internal buffer.
+func NewRepresenter(writer io.Writer, opts *Options) *Representer {
+ emitter := NewEmitter()
+ emitter.CompactSequenceIndent = opts.CompactSeqIndent
+ emitter.quotePreference = opts.QuotePreference
+ emitter.SetWidth(opts.LineWidth)
+ emitter.SetUnicode(opts.Unicode)
+ emitter.SetCanonical(opts.Canonical)
+ emitter.SetLineBreak(opts.LineBreak)
+
+ r := &Representer{
+ Emitter: emitter,
+ Indent: opts.Indent,
+ lineWidth: opts.LineWidth,
+ explicitStart: opts.ExplicitStart,
+ explicitEnd: opts.ExplicitEnd,
+ flowSimpleCollections: opts.FlowSimpleCollections,
+ quotePreference: opts.QuotePreference,
+ }
+
+ if writer != nil {
+ r.Emitter.SetOutputWriter(writer)
+ } else {
+ r.Emitter.SetOutputString(&r.Out)
+ }
+
+ return r
+}
+
+func (r *Representer) init() {
+ if r.doneInit {
+ return
+ }
+ if r.Indent == 0 {
+ r.Indent = 4
+ }
+ r.Emitter.BestIndent = r.Indent
+ r.emit(NewStreamStartEvent(UTF8_ENCODING))
+ r.doneInit = true
+}
+
+func (r *Representer) Finish() {
+ r.Emitter.OpenEnded = false
+ r.emit(NewStreamEndEvent())
+}
+
+func (r *Representer) Destroy() {
+ r.Emitter.Delete()
+}
+
+func (r *Representer) emit(event Event) {
+ // This will internally delete the event value.
+ r.must(r.Emitter.Emit(&event))
+}
+
+func (r *Representer) must(err error) {
+ if err != nil {
+ msg := err.Error()
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (r *Representer) MarshalDoc(tag string, in reflect.Value) {
+ r.init()
+ var node *Node
+ if in.IsValid() {
+ node, _ = in.Interface().(*Node)
+ }
+ if node != nil && node.Kind == DocumentNode {
+ r.nodev(in)
+ } else {
+ // Use !explicitStart for implicit flag (true = implicit/no marker)
+ r.emit(NewDocumentStartEvent(noVersionDirective, noTagDirective, !r.explicitStart))
+ r.marshal(tag, in)
+ // Use !explicitEnd for implicit flag
+ r.emit(NewDocumentEndEvent(!r.explicitEnd))
+ }
+}
+
+func (r *Representer) marshal(tag string, in reflect.Value) {
+ tag = shortTag(tag)
+ if !in.IsValid() || in.Kind() == reflect.Pointer && in.IsNil() {
+ r.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch value := iface.(type) {
+ case *Node:
+ r.nodev(in)
+ return
+ case Node:
+ if !in.CanAddr() {
+ n := reflect.New(in.Type()).Elem()
+ n.Set(in)
+ in = n
+ }
+ r.nodev(in.Addr())
+ return
+ case time.Time:
+ r.timev(tag, in)
+ return
+ case *time.Time:
+ r.timev(tag, in.Elem())
+ return
+ case time.Duration:
+ r.stringv(tag, reflect.ValueOf(value.String()))
+ return
+ case Marshaler:
+ v, err := value.MarshalYAML()
+ if err != nil {
+ Fail(err)
+ }
+ if v == nil {
+ r.nilv()
+ return
+ }
+ r.marshal(tag, reflect.ValueOf(v))
+ return
+ case encoding.TextMarshaler:
+ text, err := value.MarshalText()
+ if err != nil {
+ Fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ r.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ r.marshal(tag, in.Elem())
+ case reflect.Map:
+ r.mapv(tag, in)
+ case reflect.Pointer:
+ r.marshal(tag, in.Elem())
+ case reflect.Struct:
+ r.structv(tag, in)
+ case reflect.Slice, reflect.Array:
+ r.slicev(tag, in)
+ case reflect.String:
+ r.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ r.intv(tag, in)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ r.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ r.floatv(tag, in)
+ case reflect.Bool:
+ r.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (r *Representer) mapv(tag string, in reflect.Value) {
+ r.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ r.marshal("", k)
+ r.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (r *Representer) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Pointer {
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+func (r *Representer) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ r.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = r.fieldByIndex(in, info.Inline)
+ if !value.IsValid() {
+ continue
+ }
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ r.marshal("", reflect.ValueOf(info.Key))
+ r.flow = info.Flow
+ r.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ r.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+ }
+ r.marshal("", k)
+ r.flow = false
+ r.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (r *Representer) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := BLOCK_MAPPING_STYLE
+ if r.flow {
+ r.flow = false
+ style = FLOW_MAPPING_STYLE
+ }
+ r.emit(NewMappingStartEvent(nil, []byte(tag), implicit, style))
+ f()
+ r.emit(NewMappingEndEvent())
+}
+
+func (r *Representer) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := BLOCK_SEQUENCE_STYLE
+ if r.flow {
+ r.flow = false
+ style = FLOW_SEQUENCE_STYLE
+ }
+ r.emit(NewSequenceStartEvent(nil, []byte(tag), implicit, style))
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ r.marshal("", in.Index(i))
+ }
+ r.emit(NewSequenceEndEvent())
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshaled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshaled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+ switch s {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+ "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ return true
+ default:
+ return false
+ }
+}
+
+// looksLikeMerge returns true if the given string is the merge indicator "<<".
+//
+// When encoding a scalar with this exact value, it must be quoted to prevent it
+// from being interpreted as a merge indicator during decoding.
+func looksLikeMerge(s string) (result bool) {
+ return s == "<<"
+}
+
+func (r *Representer) stringv(tag string, in reflect.Value) {
+ var style ScalarStyle
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be represented directly as YAML so use a binary tag
+ // and represent it as base64.
+ tag = binaryTag
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when represented unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == strTag &&
+ !(isBase60Float(s) ||
+ isOldBool(s) ||
+ looksLikeMerge(s))
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ if r.flow || !shouldUseLiteralStyle(s) {
+ style = DOUBLE_QUOTED_SCALAR_STYLE
+ } else {
+ style = LITERAL_SCALAR_STYLE
+ }
+ case canUsePlain:
+ style = PLAIN_SCALAR_STYLE
+ default:
+ style = r.quotePreference.ScalarStyle()
+ }
+ r.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (r *Representer) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ r.emitScalar(s, "", tag, PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (r *Representer) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ r.emitScalar(s, "", tag, PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (r *Representer) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ r.emitScalar(s, "", tag, PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (r *Representer) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ r.emitScalar(s, "", tag, PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (r *Representer) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ r.emitScalar(s, "", tag, PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (r *Representer) nilv() {
+ r.emitScalar("null", "", "", PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (r *Representer) emitScalar(
+ value, anchor, tag string, style ScalarStyle, head, line, foot, tail []byte,
+) {
+ // TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+ implicit := tag == ""
+ if !implicit {
+ tag = longTag(tag)
+ }
+ event := NewScalarEvent([]byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)
+ event.HeadComment = head
+ event.LineComment = line
+ event.FootComment = foot
+ event.TailComment = tail
+ r.emit(event)
+}
+
+func (r *Representer) nodev(in reflect.Value) {
+ r.node(in.Interface().(*Node), "")
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/resolver.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/resolver.go
new file mode 100644
index 00000000000..d78a20e8ed8
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/resolver.go
@@ -0,0 +1,231 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Tag resolution for YAML scalars.
+// Determines implicit types (int, float, bool, null, timestamp) from untagged
+// scalar values.
+
+package libyaml
+
+import (
+ "encoding/base64"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type resolveMapItem struct {
+ value any
+ tag string
+}
+
+var (
+ resolveTable = make([]byte, 256)
+ resolveMap = make(map[string]resolveMapItem)
+)
+
+// negativeZero represents -0.0 for YAML encoding/decoding
+// this is needed because Go constants cannot express -0.0
+// https://staticcheck.dev/docs/checks/#SA4026
+var negativeZero = math.Copysign(0.0, -1.0)
+
+func init() {
+ t := resolveTable
+ t[int('+')] = 'S' // Sign
+ t[int('-')] = 'S'
+ for _, c := range "0123456789" {
+ t[int(c)] = 'D' // Digit
+ }
+ for _, c := range "yYnNtTfFoO~<" { // < for merge key <<
+ t[int(c)] = 'M' // In map
+ }
+ t[int('.')] = '.' // Float (potentially in map)
+
+ resolveMapList := []struct {
+ v any
+ tag string
+ l []string
+ }{
+ {true, boolTag, []string{"true", "True", "TRUE"}},
+ {false, boolTag, []string{"false", "False", "FALSE"}},
+ {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
+ {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
+ {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
+ {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
+ {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
+ {negativeZero, floatTag, []string{"-0", "-0.0"}},
+ {"<<", mergeTag, []string{"<<"}},
+ }
+
+ m := resolveMap
+ for _, item := range resolveMapList {
+ for _, s := range item.l {
+ m[s] = resolveMapItem{item.v, item.tag}
+ }
+ }
+}
+
+func resolvableTag(tag string) bool {
+ switch tag {
+ case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
+ return true
+ }
+ return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out any) {
+ tag = shortTag(tag)
+ if !resolvableTag(tag) {
+ return tag, in
+ }
+
+ defer func() {
+ switch tag {
+ case "", rtag, strTag, binaryTag:
+ return
+ case floatTag:
+ if rtag == intTag {
+ switch v := out.(type) {
+ case int64:
+ rtag = floatTag
+ out = float64(v)
+ return
+ case int:
+ rtag = floatTag
+ out = float64(v)
+ return
+ }
+ }
+ }
+ failf("cannot construct %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+ }()
+
+ // Any data is accepted as a !!str or !!binary.
+ // Otherwise, the prefix is enough of a hint about what it might be.
+ hint := byte('N')
+ if in != "" {
+ hint = resolveTable[in[0]]
+ }
+ if hint != 0 && tag != strTag && tag != binaryTag {
+ // Handle things we can lookup in a map.
+ if item, ok := resolveMap[in]; ok {
+ return item.tag, item.value
+ }
+
+ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+ // are purposefully unsupported here. They're still quoted on
+ // the way out for compatibility with other parser, though.
+
+ switch hint {
+ case 'M':
+ // We've already checked the map above.
+
+ case '.':
+ // Not in the map, so maybe a normal float.
+ floatv, err := strconv.ParseFloat(in, 64)
+ if err == nil {
+ return floatTag, floatv
+ }
+
+ case 'D', 'S':
+ // Int, float, or timestamp.
+ // Only try values as a timestamp if the value is unquoted or there's an explicit
+ // !!timestamp tag.
+ if tag == "" || tag == timestampTag {
+ t, ok := parseTimestamp(in)
+ if ok {
+ return timestampTag, t
+ }
+ }
+
+ plain := strings.ReplaceAll(in, "_", "")
+ intv, err := strconv.ParseInt(plain, 0, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain, 0, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ if yamlStyleFloat.MatchString(plain) {
+ floatv, err := strconv.ParseFloat(plain, 64)
+ if err == nil {
+ return floatTag, floatv
+ }
+ }
+ default:
+ panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
+ }
+ }
+ return strTag, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+ const lineLen = 70
+ encLen := base64.StdEncoding.EncodedLen(len(s))
+ lines := encLen/lineLen + 1
+ buf := make([]byte, encLen*2+lines)
+ in := buf[0:encLen]
+ out := buf[encLen:]
+ base64.StdEncoding.Encode(in, []byte(s))
+ k := 0
+ for i := 0; i < len(in); i += lineLen {
+ j := i + lineLen
+ if j > len(in) {
+ j = len(in)
+ }
+ k += copy(out[k:], in[i:j])
+ if lines > 1 {
+ out[k] = '\n'
+ k++
+ }
+ }
+ return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+ "2006-1-2 15:4:5.999999999", // space separated with no time zone
+ "2006-1-2", // date only
+ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+ // from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+ // TODO write code to check all the formats supported by
+ // http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+ // Quick check: all date formats start with YYYY-.
+ i := 0
+ for ; i < len(s); i++ {
+ if c := s[i]; c < '0' || c > '9' {
+ break
+ }
+ }
+ if i != 4 || i == len(s) || s[i] != '-' {
+ return time.Time{}, false
+ }
+ for _, format := range allowedTimestampFormats {
+ if t, err := time.Parse(format, s); err == nil {
+ return t, true
+ }
+ }
+ return time.Time{}, false
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/scanner.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/scanner.go
new file mode 100644
index 00000000000..36f62b0ea0e
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/scanner.go
@@ -0,0 +1,3128 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Scanner stage: Transforms input stream into token sequence.
+// The Scanner is the most complex stage, handling indentation, simple keys,
+// and block collection detection.
+
+package libyaml
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward. The issues are "block collection start" and
+// "simple keys". Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented. We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+// STREAM-START(encoding) # The stream start.
+// STREAM-END # The stream end.
+// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
+// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
+// DOCUMENT-START # '---'
+// DOCUMENT-END # '...'
+// BLOCK-SEQUENCE-START # Indentation increase denoting a block
+// BLOCK-MAPPING-START # sequence or a block mapping.
+// BLOCK-END # Indentation decrease.
+// FLOW-SEQUENCE-START # '['
+// FLOW-SEQUENCE-END # ']'
+// BLOCK-SEQUENCE-START # '{'
+// BLOCK-SEQUENCE-END # '}'
+// BLOCK-ENTRY # '-'
+// FLOW-ENTRY # ','
+// KEY # '?' or nothing (simple keys).
+// VALUE # ':'
+// ALIAS(anchor) # '*anchor'
+// ANCHOR(anchor) # '&anchor'
+// TAG(handle,suffix) # '!handle!suffix'
+// SCALAR(value,style) # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+// STREAM-START(encoding)
+// STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+// VERSION-DIRECTIVE(major,minor)
+// TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+// %YAML 1.1
+// %TAG ! !foo
+// %TAG !yaml! tag:yaml.org,2002:
+// ---
+//
+// The corresponding sequence of tokens:
+//
+// STREAM-START(utf-8)
+// VERSION-DIRECTIVE(1,1)
+// TAG-DIRECTIVE("!","!foo")
+// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+// DOCUMENT-START
+// STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+// DOCUMENT-START
+// DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+// 1. An implicit document:
+//
+// 'a scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// STREAM-END
+//
+// 2. An explicit document:
+//
+// ---
+// 'a scalar'
+// ...
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-END
+// STREAM-END
+//
+// 3. Several documents in a stream:
+//
+// 'a scalar'
+// ---
+// 'another scalar'
+// ---
+// 'yet another scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("another scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("yet another scalar",single-quoted)
+// STREAM-END
+//
+// We have already introduced the SCALAR token above. The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+// ALIAS(anchor)
+// ANCHOR(anchor)
+// TAG(handle,suffix)
+// SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+// 1. A recursive sequence:
+//
+// &A [ *A ]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// ANCHOR("A")
+// FLOW-SEQUENCE-START
+// ALIAS("A")
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A tagged scalar:
+//
+// !!float "3.14" # A good approximation.
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// TAG("!!","float")
+// SCALAR("3.14",double-quoted)
+// STREAM-END
+//
+// 3. Various scalar styles:
+//
+// --- # Implicit empty plain scalars do not produce tokens.
+// --- a plain scalar
+// --- 'a single-quoted scalar'
+// --- "a double-quoted scalar"
+// --- |-
+// a literal scalar
+// --- >-
+// a folded
+// scalar
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// DOCUMENT-START
+// SCALAR("a plain scalar",plain)
+// DOCUMENT-START
+// SCALAR("a single-quoted scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("a double-quoted scalar",double-quoted)
+// DOCUMENT-START
+// SCALAR("a literal scalar",literal)
+// DOCUMENT-START
+// SCALAR("a folded scalar",folded)
+// STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+// FLOW-SEQUENCE-START
+// FLOW-SEQUENCE-END
+// FLOW-MAPPING-START
+// FLOW-MAPPING-END
+// FLOW-ENTRY
+// KEY
+// VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+// 1. A flow sequence:
+//
+// [item 1, item 2, item 3]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-SEQUENCE-START
+// SCALAR("item 1",plain)
+// FLOW-ENTRY
+// SCALAR("item 2",plain)
+// FLOW-ENTRY
+// SCALAR("item 3",plain)
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A flow mapping:
+//
+// {
+// a simple key: a value, # Note that the KEY token is produced.
+// ? a complex key: another value,
+// }
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// FLOW-ENTRY
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// FLOW-ENTRY
+// FLOW-MAPPING-END
+// STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator. Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+// BLOCK-SEQUENCE-START
+// BLOCK-MAPPING-START
+// BLOCK-END
+// BLOCK-ENTRY
+// KEY
+// VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python). However YAML has some syntax peculiarities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+// 1. Block sequences:
+//
+// - item 1
+// - item 2
+// -
+// - item 3.1
+// - item 3.2
+// -
+// key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 3.1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 3.2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Block mappings:
+//
+// a simple key: a value # The KEY token is produced here.
+// ? a complex key
+// : another value
+// a mapping:
+// key 1: value 1
+// key 2: value 2
+// a sequence:
+// - item 1
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// KEY
+// SCALAR("a mapping",plain)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line. If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line. The following examples
+// illustrate this case:
+//
+// 1. Collections in a sequence:
+//
+// - - item 1
+// - item 2
+// - key 1: value 1
+// key 2: value 2
+// - ? complex key
+// : complex value
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("complex key")
+// VALUE
+// SCALAR("complex value")
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Collections in a mapping:
+//
+// ? a sequence
+// : - item 1
+// - item 2
+// ? a mapping
+// : key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a mapping",plain)
+// VALUE
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+// key:
+// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key",plain)
+// VALUE
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+//
+
+// Advance the buffer pointer.
+func (parser *Parser) skip() {
+ if !isBlank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
+ parser.mark.Index++
+ parser.mark.Column++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func (parser *Parser) skipLine() {
+ if isCRLF(parser.buffer, parser.buffer_pos) {
+ parser.mark.Index += 2
+ parser.mark.Column = 0
+ parser.mark.Line++
+ parser.unread -= 2
+ parser.buffer_pos += 2
+ parser.newlines++
+ } else if isLineBreak(parser.buffer, parser.buffer_pos) {
+ parser.mark.Index++
+ parser.mark.Column = 0
+ parser.mark.Line++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+ parser.newlines++
+ }
+}
+
+// Copy a character to a string buffer and advance pointers.
+func (parser *Parser) read(s []byte) []byte {
+ if !isBlank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
+ w := width(parser.buffer[parser.buffer_pos])
+ if w == 0 {
+ panic("invalid character sequence")
+ }
+ if len(s) == 0 {
+ s = make([]byte, 0, 32)
+ }
+ if w == 1 && len(s)+w <= cap(s) {
+ s = s[:len(s)+1]
+ s[len(s)-1] = parser.buffer[parser.buffer_pos]
+ parser.buffer_pos++
+ } else {
+ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+ parser.buffer_pos += w
+ }
+ parser.mark.Index++
+ parser.mark.Column++
+ parser.unread--
+ return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func (parser *Parser) readLine(s []byte) []byte {
+ buf := parser.buffer
+ pos := parser.buffer_pos
+ switch {
+ case buf[pos] == '\r' && buf[pos+1] == '\n':
+ // CR LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ parser.mark.Index++
+ parser.unread--
+ case buf[pos] == '\r' || buf[pos] == '\n':
+ // CR|LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 1
+ case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+ // NEL . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+ // LS|PS . LS|PS
+ s = append(s, buf[parser.buffer_pos:pos+3]...)
+ parser.buffer_pos += 3
+ default:
+ return s
+ }
+ parser.mark.Index++
+ parser.mark.Column = 0
+ parser.mark.Line++
+ parser.unread--
+ parser.newlines++
+ return s
+}
+
+// Scan gets the next token.
+func (parser *Parser) Scan(token *Token) error {
+ // Erase the token object.
+ *token = Token{} // [Go] Is this necessary?
+
+ if parser.lastError != nil {
+ return parser.lastError
+ }
+
+ // No tokens after STREAM-END or error.
+ if parser.stream_end_produced {
+ return io.EOF
+ }
+
+ // Ensure that the tokens queue contains enough tokens.
+ if !parser.token_available {
+ if err := parser.fetchMoreTokens(); err != nil {
+ parser.lastError = err
+ return err
+ }
+ }
+
+ // Fetch the next token from the queue.
+ *token = parser.tokens[parser.tokens_head]
+ parser.tokens_head++
+ parser.tokens_parsed++
+ parser.token_available = false
+
+ if token.Type == STREAM_END_TOKEN {
+ parser.stream_end_produced = true
+ }
+ return nil
+}
+
+func formatScannerError(problem string, problem_mark Mark) error {
+ problem_mark.Line += 1
+
+ return ScannerError{
+ Mark: problem_mark,
+ Message: problem,
+ }
+}
+
+func formatScannerErrorContext(context string, context_mark Mark, problem string, problem_mark Mark) error {
+ context_mark.Line += 1
+ problem_mark.Line += 1
+
+ return ScannerError{
+ ContextMark: context_mark,
+ ContextMessage: context,
+
+ Mark: problem_mark,
+ Message: problem,
+ }
+}
+
+func (parser *Parser) setScannerTagError(directive bool, context_mark Mark, problem string) error {
+ context := "while parsing a tag"
+ if directive {
+ context = "while parsing a %TAG directive"
+ }
+ return formatScannerErrorContext(context, context_mark, problem, parser.mark)
+}
+
+func trace(args ...any) func() {
+ pargs := append([]any{"+++"}, args...)
+ fmt.Println(pargs...)
+ pargs = append([]any{"---"}, args...)
+ return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func (parser *Parser) fetchMoreTokens() error {
+ // While we need more tokens to fetch, do it.
+ for {
+ // [Go] The comment parsing logic requires a lookahead of two tokens
+ // so that foot comments may be parsed in time of associating them
+ // with the tokens that are parsed before them, and also for line
+ // comments to be transformed into head comments in some edge cases.
+ if parser.tokens_head < len(parser.tokens)-2 {
+ // If a potential simple key is at the head position, we need to fetch
+ // the next token to disambiguate it.
+
+ var first_key int
+ found_potential_key := false
+
+ if len(parser.simple_key_stack) > 0 {
+ // Found a simple key on the stack
+ first_key = parser.simple_key_stack[0].token_number
+ found_potential_key = true
+ } else if parser.simple_key_possible {
+ // Found a 'current' simple key (which was not pushed to the stack yet)
+ first_key = parser.simple_key.token_number
+ found_potential_key = true
+ }
+
+ if !found_potential_key {
+ // We don't have any potential simple keys
+ break
+ } else if parser.tokens_parsed != first_key {
+ // We have not reached the potential simple key yet.
+ break
+ }
+ }
+ // Fetch the next token.
+ if err := parser.fetchNextToken(); err != nil {
+ return err
+ }
+ }
+
+ parser.token_available = true
+ return nil
+}
+
+// The dispatcher for token fetchers.
+func (parser *Parser) fetchNextToken() (err error) {
+ // Ensure that the buffer is initialized.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ // Check if we just started scanning. Fetch STREAM-START then.
+ if !parser.stream_start_produced {
+ return parser.fetchStreamStart()
+ }
+
+ scan_mark := parser.mark
+
+ // Eat whitespaces and comments until we reach the next token.
+ if err := parser.scanToNextToken(); err != nil {
+ return err
+ }
+
+ // [Go] While unrolling indents, transform the head comments of prior
+ // indentation levels observed after scan_start into foot comments at
+ // the respective indexes.
+
+ // Check the indentation level against the current column.
+ if err := parser.unrollIndent(parser.mark.Column, scan_mark); err != nil {
+ return err
+ }
+
+ // Ensure that the buffer contains at least 4 characters. 4 is the length
+ // of the longest indicators ('--- ' and '... ').
+ if parser.unread < 4 {
+ if err := parser.updateBuffer(4); err != nil {
+ return err
+ }
+ }
+
+ // Is it the end of the stream?
+ if isZeroChar(parser.buffer, parser.buffer_pos) {
+ return parser.fetchStreamEnd()
+ }
+
+ // Is it a directive?
+ if parser.mark.Column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+ return parser.fetchDirective()
+ }
+
+ buf := parser.buffer
+ pos := parser.buffer_pos
+
+ // Is it the document start indicator?
+ if parser.mark.Column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && isBlankOrZero(buf, pos+3) {
+ return parser.fetchDocumentIndicator(DOCUMENT_START_TOKEN)
+ }
+
+ // Is it the document end indicator?
+ if parser.mark.Column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && isBlankOrZero(buf, pos+3) {
+ return parser.fetchDocumentIndicator(DOCUMENT_END_TOKEN)
+ }
+
+ comment_mark := parser.mark
+ if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
+ // Associate any following comments with the prior token.
+ comment_mark = parser.tokens[len(parser.tokens)-1].StartMark
+ }
+ defer func() {
+ if err != nil {
+ return
+ }
+ if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].Type == BLOCK_ENTRY_TOKEN {
+ // Sequence indicators alone have no line comments. It becomes
+ // a head comment for whatever follows.
+ return
+ }
+ err = parser.scanLineComment(comment_mark)
+ }()
+
+ // Is it the flow sequence start indicator?
+ if buf[pos] == '[' {
+ return parser.fetchFlowCollectionStart(FLOW_SEQUENCE_START_TOKEN)
+ }
+
+ // Is it the flow mapping start indicator?
+ if parser.buffer[parser.buffer_pos] == '{' {
+ return parser.fetchFlowCollectionStart(FLOW_MAPPING_START_TOKEN)
+ }
+
+ // Is it the flow sequence end indicator?
+ if parser.buffer[parser.buffer_pos] == ']' {
+ return parser.fetchFlowCollectionEnd(
+ FLOW_SEQUENCE_END_TOKEN)
+ }
+
+ // Is it the flow mapping end indicator?
+ if parser.buffer[parser.buffer_pos] == '}' {
+ return parser.fetchFlowCollectionEnd(
+ FLOW_MAPPING_END_TOKEN)
+ }
+
+ // Is it the flow entry indicator?
+ if parser.buffer[parser.buffer_pos] == ',' {
+ return parser.fetchFlowEntry()
+ }
+
+ // Is it the block entry indicator?
+ if parser.buffer[parser.buffer_pos] == '-' && isBlankOrZero(parser.buffer, parser.buffer_pos+1) {
+ return parser.fetchBlockEntry()
+ }
+
+ // Is it the key indicator?
+ if parser.buffer[parser.buffer_pos] == '?' && isBlankOrZero(parser.buffer, parser.buffer_pos+1) {
+ return parser.fetchKey()
+ }
+
+ // Is it the value indicator?
+ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 && !parser.isFlowSequence() || isBlankOrZero(parser.buffer, parser.buffer_pos+1)) {
+ return parser.fetchValue()
+ }
+
+ // Is it an alias?
+ if parser.buffer[parser.buffer_pos] == '*' {
+ return parser.fetchAnchor(ALIAS_TOKEN)
+ }
+
+ // Is it an anchor?
+ if parser.buffer[parser.buffer_pos] == '&' {
+ return parser.fetchAnchor(ANCHOR_TOKEN)
+ }
+
+ // Is it a tag?
+ if parser.buffer[parser.buffer_pos] == '!' {
+ return parser.fetchTag()
+ }
+
+ // Is it a literal scalar?
+ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+ return parser.fetchBlockScalar(true)
+ }
+
+ // Is it a folded scalar?
+ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+ return parser.fetchBlockScalar(false)
+ }
+
+ // Is it a single-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ return parser.fetchFlowScalar(true)
+ }
+
+ // Is it a double-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '"' {
+ return parser.fetchFlowScalar(false)
+ }
+
+ // Is it a plain scalar?
+ //
+ // A plain scalar may start with any non-blank characters except
+ //
+ // '-', '?', ':', ',', '[', ']', '{', '}',
+ // '#', '&', '*', '!', '|', '>', '\'', '\"',
+ // '%', '@', '`'.
+ //
+ // In the block context (and, for the '-' indicator, in the flow context
+ // too), it may also start with the characters
+ //
+ // '-', '?', ':'
+ //
+ // if it is followed by a non-space character.
+ //
+ // The last rule is more restrictive than the specification requires.
+ // [Go] TODO Make this logic more reasonable.
+ //switch parser.buffer[parser.buffer_pos] {
+ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+ //}
+ if !(isBlankOrZero(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+ (parser.buffer[parser.buffer_pos] == '-' && !isBlank(parser.buffer, parser.buffer_pos+1)) ||
+ ((parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+ !isBlankOrZero(parser.buffer, parser.buffer_pos+1)) {
+ return parser.fetchPlainScalar()
+ }
+
+ // If we don't determine the token type so far, it is an error.
+ return formatScannerErrorContext(
+ "while scanning for the next token", parser.mark,
+ "found character that cannot start any token", parser.mark)
+}
+
+func (parser *Parser) isFlowSequence() bool {
+ if len(parser.tokens) == 0 {
+ return false
+ }
+ previousToken := parser.tokens[len(parser.tokens)-1]
+ return previousToken.Type == FLOW_ENTRY_TOKEN || previousToken.Type == FLOW_SEQUENCE_START_TOKEN
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func (parser *Parser) saveSimpleKey() error {
+ // A simple key is required at the current position if the scanner is in
+ // the block context and the current column coincides with the indentation
+ // level.
+
+ required := parser.flow_level == 0 && parser.indent == parser.mark.Column
+
+ //
+ // If the current position may start a simple key, save it.
+ //
+ if parser.simple_key_allowed {
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ parser.simple_key_possible = true
+ parser.simple_key = SimpleKey{
+ required: required,
+ flow_level: parser.flow_level,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ }
+ }
+ return nil
+}
+
+// Remove a potential simple key at the current flow level.
+func (parser *Parser) removeSimpleKey() error {
+ // If the key is required, it is an error.
+ if parser.simple_key.required {
+ return formatScannerErrorContext(
+ "while scanning a simple key", parser.simple_key.mark,
+ "could not find expected ':'", parser.mark)
+ }
+
+ parser.simple_key_possible = false // disable the key
+ return nil
+}
+
+// max_flow_level limits the flow_level
+const max_flow_level = 10000
+
+// Increase the flow level and resize the simple key list if needed.
+func (parser *Parser) increaseFlowLevel() error {
+ // Increase the flow level.
+ parser.flow_level++
+ if parser.flow_level > max_flow_level {
+ return formatScannerErrorContext(
+ "while increasing flow level", parser.simple_key.mark,
+ fmt.Sprintf("exceeded max depth of %d", max_flow_level), parser.mark)
+ }
+
+ // If a simple key was possible, push it to the stack before resetting the key.
+ if parser.simple_key_possible {
+ parser.simple_key_stack = append(parser.simple_key_stack, parser.simple_key)
+ }
+
+ // Reset the simple key for the new flow level.
+ parser.simple_key = SimpleKey{}
+
+ return nil
+}
+
+// Decrease the flow level.
+func (parser *Parser) decreaseFlowLevel() error {
+ if parser.flow_level > 0 {
+ parser.flow_level--
+
+ if len(parser.simple_key_stack) == 0 {
+ return nil
+ }
+
+ last := len(parser.simple_key_stack) - 1
+ if parser.simple_key_stack[last].flow_level == parser.flow_level {
+ parser.simple_key = parser.simple_key_stack[last] // use last item
+ parser.simple_key_stack = parser.simple_key_stack[:last] // remove last item
+ parser.simple_key_possible = true // enable the key
+ }
+ }
+ return nil
+}
+
+// max_indents limits the indents stack size
+const max_indents = 10000
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level. In this case,
+// append or insert the specified token into the token queue.
+func (parser *Parser) rollIndent(column, number int, typ TokenType, mark Mark) error {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return nil
+ }
+
+ if parser.indent < column {
+ // Push the current indentation level to the stack and set the new
+ // indentation level.
+ parser.indents = append(parser.indents, parser.indent)
+ parser.indent = column
+ if len(parser.indents) > max_indents {
+ return formatScannerErrorContext(
+ "while increasing indent level", parser.simple_key.mark,
+ fmt.Sprintf("exceeded max depth of %d", max_indents), parser.mark)
+ }
+
+ // Create a token and insert it into the queue.
+ token := Token{
+ Type: typ,
+ StartMark: mark,
+ EndMark: mark,
+ }
+ if number > -1 {
+ number -= parser.tokens_parsed
+ }
+ parser.insertToken(number, &token)
+ }
+ return nil
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column. For each indentation level, append
+// the BLOCK-END token.
+func (parser *Parser) unrollIndent(column int, scan_mark Mark) error {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return nil
+ }
+
+ block_mark := scan_mark
+ block_mark.Index--
+
+ // Loop through the indentation levels in the stack.
+ for parser.indent > column {
+
+ // [Go] Reposition the end token before potential following
+ // foot comments of parent blocks. For that, search
+ // backwards for recent comments that were at the same
+ // indent as the block that is ending now.
+ stop_index := block_mark.Index
+ for i := len(parser.comments) - 1; i >= 0; i-- {
+ comment := &parser.comments[i]
+
+ if comment.EndMark.Index < stop_index {
+ // Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
+ // If requested indent column is < 0, then the document is over and everything else
+ // is a foot anyway.
+ break
+ }
+ if comment.StartMark.Column == parser.indent+1 {
+ // This is a good match. But maybe there's a former comment
+ // at that same indent level, so keep searching.
+ block_mark = comment.StartMark
+ }
+
+ // While the end of the former comment matches with
+ // the start of the following one, we know there's
+ // nothing in between and scanning is still safe.
+ stop_index = comment.ScanMark.Index
+ }
+
+ // Create a token and append it to the queue.
+ token := Token{
+ Type: BLOCK_END_TOKEN,
+ StartMark: block_mark,
+ EndMark: block_mark,
+ }
+ parser.insertToken(-1, &token)
+
+ // Pop the indentation level.
+ parser.indent = parser.indents[len(parser.indents)-1]
+ parser.indents = parser.indents[:len(parser.indents)-1]
+ }
+ return nil
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func (parser *Parser) fetchStreamStart() error {
+ // Set the initial indentation.
+ parser.indent = -1
+
+ // Initialize the simple key stack.
+ parser.simple_key = SimpleKey{}
+ parser.simple_key_stack = []SimpleKey{}
+
+ // A simple key is allowed at the beginning of the stream.
+ parser.simple_key_allowed = true
+
+ // We have started.
+ parser.stream_start_produced = true
+
+ // Create the STREAM-START token and append it to the queue.
+ token := Token{
+ Type: STREAM_START_TOKEN,
+ StartMark: parser.mark,
+ EndMark: parser.mark,
+ encoding: parser.encoding,
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func (parser *Parser) fetchStreamEnd() error {
+ // Force new line.
+ if parser.mark.Column != 0 {
+ parser.mark.Column = 0
+ parser.mark.Line++
+ }
+
+ // Reset the indentation level.
+ if err := parser.unrollIndent(-1, parser.mark); err != nil {
+ return err
+ }
+
+ // Reset simple keys.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+ parser.simple_key = SimpleKey{}
+ parser.simple_key_stack = []SimpleKey{}
+ parser.simple_key_allowed = false
+
+ // Create the STREAM-END token and append it to the queue.
+ token := Token{
+ Type: STREAM_END_TOKEN,
+ StartMark: parser.mark,
+ EndMark: parser.mark,
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func (parser *Parser) fetchDirective() error {
+ // Reset the indentation level.
+ if err := parser.unrollIndent(-1, parser.mark); err != nil {
+ return err
+ }
+
+ // Reset simple keys.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+ token := Token{}
+ if err := parser.scanDirective(&token); err != nil {
+ return err
+ }
+ // Append the token to the queue.
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func (parser *Parser) fetchDocumentIndicator(typ TokenType) error {
+ // Reset the indentation level.
+ if err := parser.unrollIndent(-1, parser.mark); err != nil {
+ return err
+ }
+
+ // Reset simple keys.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+ start_mark := parser.mark
+
+ parser.skip()
+ parser.skip()
+ parser.skip()
+
+ end_mark := parser.mark
+
+ // Create the DOCUMENT-START or DOCUMENT-END token.
+ token := Token{
+ Type: typ,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ // Append the token to the queue.
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func (parser *Parser) fetchFlowCollectionStart(typ TokenType) error {
+ // The indicators '[' and '{' may start a simple key.
+ if err := parser.saveSimpleKey(); err != nil {
+ return err
+ }
+
+ // Increase the flow level.
+ if err := parser.increaseFlowLevel(); err != nil {
+ return err
+ }
+
+ // A simple key may follow the indicators '[' and '{'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+ token := Token{
+ Type: typ,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ // Append the token to the queue.
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func (parser *Parser) fetchFlowCollectionEnd(typ TokenType) error {
+ // Reset any potential simple key on the current flow level.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ // Decrease the flow level.
+ if err := parser.decreaseFlowLevel(); err != nil {
+ return err
+ }
+
+ // No simple keys after the indicators ']' and '}'.
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+
+ start_mark := parser.mark
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+ token := Token{
+ Type: typ,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ // Append the token to the queue.
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the FLOW-ENTRY token.
+func (parser *Parser) fetchFlowEntry() error {
+ // Reset any potential simple keys on the current flow level.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ // Simple keys are allowed after ','.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create the FLOW-ENTRY token and append it to the queue.
+ token := Token{
+ Type: FLOW_ENTRY_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the BLOCK-ENTRY token.
+func (parser *Parser) fetchBlockEntry() error {
+ // Check if the scanner is in the block context.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new entry.
+ if !parser.simple_key_allowed {
+ return formatScannerError("block sequence entries are not allowed in this context", parser.mark)
+ }
+ // Add the BLOCK-SEQUENCE-START token if needed.
+ if err := parser.rollIndent(parser.mark.Column, -1, BLOCK_SEQUENCE_START_TOKEN, parser.mark); err != nil {
+ return err
+ }
+ } else { //nolint:staticcheck // there is no problem with this empty branch as it's documentation.
+
+ // It is an error for the '-' indicator to occur in the flow context,
+ // but we let the Parser detect and report about it because the Parser
+ // is able to point to the context.
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ // Simple keys are allowed after '-'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create the BLOCK-ENTRY token and append it to the queue.
+ token := Token{
+ Type: BLOCK_ENTRY_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the KEY token.
+func (parser *Parser) fetchKey() error {
+ // In the block context, additional checks are required.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new key (not necessary simple).
+ if !parser.simple_key_allowed {
+ return formatScannerError("mapping keys are not allowed in this context", parser.mark)
+ }
+ // Add the BLOCK-MAPPING-START token if needed.
+ if err := parser.rollIndent(parser.mark.Column, -1, BLOCK_MAPPING_START_TOKEN, parser.mark); err != nil {
+ return err
+ }
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ // Simple keys are allowed after '?' in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+
+ // Consume the token.
+ start_mark := parser.mark
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create the KEY token and append it to the queue.
+ token := Token{
+ Type: KEY_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the VALUE token.
+func (parser *Parser) fetchValue() error {
+ simple_key := &parser.simple_key
+
+ // Have we found a simple key?
+ if parser.simple_key_possible && simple_key.mark.Line == parser.mark.Line {
+ // Create the KEY token and insert it into the queue.
+ token := Token{
+ Type: KEY_TOKEN,
+ StartMark: simple_key.mark,
+ EndMark: simple_key.mark,
+ }
+ parser.insertToken(simple_key.token_number-parser.tokens_parsed, &token)
+
+ // In the block context, we may need to add the BLOCK-MAPPING-START token.
+ if err := parser.rollIndent(simple_key.mark.Column,
+ simple_key.token_number,
+ BLOCK_MAPPING_START_TOKEN, simple_key.mark); err != nil {
+ return err
+ }
+
+ // Remove the simple key.
+ parser.simple_key_possible = false
+ simple_key.required = false
+
+ // A simple key cannot follow another simple key.
+ parser.simple_key_allowed = false
+
+ } else {
+ // The ':' indicator follows a complex key.
+
+ // In the block context, extra checks are required.
+ if parser.flow_level == 0 {
+
+ // Check if we are allowed to start a complex value.
+ if !parser.simple_key_allowed {
+ return formatScannerError("mapping values are not allowed in this context", parser.mark)
+ }
+
+ // Add the BLOCK-MAPPING-START token if needed.
+ if err := parser.rollIndent(parser.mark.Column, -1, BLOCK_MAPPING_START_TOKEN, parser.mark); err != nil {
+ return err
+ }
+ }
+
+ // Simple keys after ':' are allowed in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+ }
+
+ // Consume the token.
+ start_mark := parser.mark
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create the VALUE token and append it to the queue.
+ token := Token{
+ Type: VALUE_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the ALIAS or ANCHOR token.
+func (parser *Parser) fetchAnchor(typ TokenType) error {
+ // An anchor or an alias could be a simple key.
+ if err := parser.saveSimpleKey(); err != nil {
+ return err
+ }
+
+ // A simple key cannot follow an anchor or an alias.
+ parser.simple_key_allowed = false
+
+ // Create the ALIAS or ANCHOR token and append it to the queue.
+ var token Token
+ if err := parser.scanAnchor(&token, typ); err != nil {
+ return err
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the TAG token.
+func (parser *Parser) fetchTag() error {
+ // A tag could be a simple key.
+ if err := parser.saveSimpleKey(); err != nil {
+ return err
+ }
+
+ // A simple key cannot follow a tag.
+ parser.simple_key_allowed = false
+
+ // Create the TAG token and append it to the queue.
+ var token Token
+ if err := parser.scanTag(&token); err != nil {
+ return err
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func (parser *Parser) fetchBlockScalar(literal bool) error {
+ // Remove any potential simple keys.
+ if err := parser.removeSimpleKey(); err != nil {
+ return err
+ }
+
+ // A simple key may follow a block scalar.
+ parser.simple_key_allowed = true
+
+ // Create the SCALAR token and append it to the queue.
+ var token Token
+ if err := parser.scanBlockScalar(&token, literal); err != nil {
+ return err
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func (parser *Parser) fetchFlowScalar(single bool) error {
+ // A plain scalar could be a simple key.
+ if err := parser.saveSimpleKey(); err != nil {
+ return err
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token Token
+ if err := parser.scanFlowScalar(&token, single); err != nil {
+ return err
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Produce the SCALAR(...,plain) token.
+func (parser *Parser) fetchPlainScalar() error {
+ // A plain scalar could be a simple key.
+ if err := parser.saveSimpleKey(); err != nil {
+ return err
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token Token
+ if err := parser.scanPlainScalar(&token); err != nil {
+ return err
+ }
+ parser.insertToken(-1, &token)
+ return nil
+}
+
+// Eat whitespaces and comments until the next token is found.
+func (parser *Parser) scanToNextToken() error {
+ scan_mark := parser.mark
+
+ // Until the next token is not found.
+ for {
+ // Allow the BOM mark to start a line.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if parser.mark.Column == 0 && isBOM(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ }
+
+ // Eat whitespaces.
+ // Tabs are allowed:
+ // - in the flow context
+ // - in the block context, but not at the beginning of the line or
+ // after '-', '?', or ':' (complex value).
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Check if we just had a line comment under a sequence entry that
+ // looks more like a header to the following content. Similar to this:
+ //
+ // - # The comment
+ // - Some data
+ //
+ // If so, transform the line comment to a head comment and reposition.
+ if len(parser.comments) > 0 && len(parser.tokens) > 1 {
+ tokenA := parser.tokens[len(parser.tokens)-2]
+ tokenB := parser.tokens[len(parser.tokens)-1]
+ comment := &parser.comments[len(parser.comments)-1]
+ if tokenA.Type == BLOCK_SEQUENCE_START_TOKEN && tokenB.Type == BLOCK_ENTRY_TOKEN && len(comment.Line) > 0 && !isLineBreak(parser.buffer, parser.buffer_pos) {
+ // If it was in the prior line, reposition so it becomes a
+ // header of the follow up token. Otherwise, keep it in place
+ // so it becomes a header of the former.
+ comment.Head = comment.Line
+ comment.Line = nil
+ if comment.StartMark.Line == parser.mark.Line-1 {
+ comment.TokenMark = parser.mark
+ }
+ }
+ }
+
+ // Eat a comment until a line break.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ if err := parser.scanComments(scan_mark); err != nil {
+ return err
+ }
+ }
+
+ // If it is a line break, eat it.
+ if isLineBreak(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ parser.skipLine()
+
+ // In the block context, a new line may start a simple key.
+ if parser.flow_level == 0 {
+ parser.simple_key_allowed = true
+ }
+ } else {
+ break // We have found a token.
+ }
+ }
+
+ return nil
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+//
+// %YAML 1.1 # a comment \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+func (parser *Parser) scanDirective(token *Token) error {
+ // Eat '%'.
+ start_mark := parser.mark
+ parser.skip()
+
+ // Scan the directive name.
+ var name []byte
+ if err := parser.scanDirectiveName(start_mark, &name); err != nil {
+ return err
+ }
+
+ // Is it a YAML directive?
+ if bytes.Equal(name, []byte("YAML")) {
+ // Scan the VERSION directive value.
+ var major, minor int8
+ if err := parser.scanVersionDirectiveValue(start_mark, &major, &minor); err != nil {
+ return err
+ }
+ end_mark := parser.mark
+
+ // Create a VERSION-DIRECTIVE token.
+ *token = Token{
+ Type: VERSION_DIRECTIVE_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ major: major,
+ minor: minor,
+ }
+
+ // Is it a TAG directive?
+ } else if bytes.Equal(name, []byte("TAG")) {
+ // Scan the TAG directive value.
+ var handle, prefix []byte
+ if err := parser.scanTagDirectiveValue(start_mark, &handle, &prefix); err != nil {
+ return err
+ }
+ end_mark := parser.mark
+
+ // Create a TAG-DIRECTIVE token.
+ *token = Token{
+ Type: TAG_DIRECTIVE_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Value: handle,
+ prefix: prefix,
+ }
+
+ // Unknown directive.
+ } else {
+ return formatScannerErrorContext("while scanning a directive", start_mark,
+ "found unknown directive name", parser.mark)
+ }
+
+ // Eat the rest of the line including any comments.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ for isBlank(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ if parser.buffer[parser.buffer_pos] == '#' {
+ // [Go] Discard this inline comment for the time being.
+ //if !parser.ScanLineComment(start_mark) {
+ // return false
+ //}
+ for !isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a directive", start_mark,
+ "did not find expected comment or line break", parser.mark)
+ }
+
+ // Eat a line break.
+ if isLineBreak(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ parser.skipLine()
+ }
+
+ return nil
+}
+
+// Scan the directive name.
+//
+// Scope:
+//
+// %YAML 1.1 # a comment \n
+// ^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^
+func (parser *Parser) scanDirectiveName(start_mark Mark, name *[]byte) error {
+ // Consume the directive name.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ var s []byte
+ for isAlpha(parser.buffer, parser.buffer_pos) {
+ s = parser.read(s)
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Check if the name is empty.
+ if len(s) == 0 {
+ return formatScannerErrorContext("while scanning a directive", start_mark,
+ "could not find expected directive name", parser.mark)
+ }
+
+ // Check for an blank character after the name.
+ if !isBlankOrZero(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a directive", start_mark,
+ "found unexpected non-alphabetical character", parser.mark)
+ }
+ *name = s
+ return nil
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+//
+// %YAML 1.1 # a comment \n
+// ^^^^^^
+func (parser *Parser) scanVersionDirectiveValue(start_mark Mark, major, minor *int8) error {
+ // Eat whitespaces.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ for isBlank(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Consume the major version number.
+ if err := parser.scanVersionDirectiveNumber(start_mark, major); err != nil {
+ return err
+ }
+
+ // Eat '.'.
+ if parser.buffer[parser.buffer_pos] != '.' {
+ return formatScannerErrorContext("while scanning a %YAML directive", start_mark,
+ "did not find expected digit or '.' character", parser.mark)
+ }
+
+ parser.skip()
+
+ // Consume the minor version number.
+ if err := parser.scanVersionDirectiveNumber(start_mark, minor); err != nil {
+ return err
+ }
+ return nil
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+//
+// %YAML 1.1 # a comment \n
+// ^
+// %YAML 1.1 # a comment \n
+// ^
+func (parser *Parser) scanVersionDirectiveNumber(start_mark Mark, number *int8) error {
+ // Repeat while the next character is digit.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ var value, length int8
+ for isDigit(parser.buffer, parser.buffer_pos) {
+ // Check if the number is too long.
+ length++
+ if length > max_number_length {
+ return formatScannerErrorContext("while scanning a %YAML directive", start_mark,
+ "found extremely long version number", parser.mark)
+ }
+ value = value*10 + int8(asDigit(parser.buffer, parser.buffer_pos))
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Check if the number was present.
+ if length == 0 {
+ return formatScannerErrorContext("while scanning a %YAML directive", start_mark,
+ "did not find expected version number", parser.mark)
+ }
+ *number = value
+ return nil
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+//
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+func (parser *Parser) scanTagDirectiveValue(start_mark Mark, handle, prefix *[]byte) error {
+ var handle_value, prefix_value []byte
+
+ // Eat whitespaces.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ for isBlank(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Scan a handle.
+ if err := parser.scanTagHandle(true, start_mark, &handle_value); err != nil {
+ return err
+ }
+
+ // Expect a whitespace.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if !isBlank(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a %TAG directive", start_mark,
+ "did not find expected whitespace", parser.mark)
+ }
+
+ // Eat whitespaces.
+ for isBlank(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Scan a prefix (TAG directive URI - flow indicators allowed).
+ if err := parser.scanTagURI(true, true, nil, start_mark, &prefix_value); err != nil {
+ return err
+ }
+
+ // Expect a whitespace or line break.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if !isBlankOrZero(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a %TAG directive", start_mark,
+ "did not find expected whitespace or line break", parser.mark)
+ }
+
+ *handle = handle_value
+ *prefix = prefix_value
+ return nil
+}
+
+func (parser *Parser) scanAnchor(token *Token, typ TokenType) error {
+ var s []byte
+
+ // Eat the indicator character.
+ start_mark := parser.mark
+ parser.skip()
+
+ // Consume the value.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ for isAnchorChar(parser.buffer, parser.buffer_pos) {
+ s = parser.read(s)
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ end_mark := parser.mark
+
+ /*
+ * Check if length of the anchor is greater than 0 and it is followed by
+ * a whitespace character or one of the indicators:
+ *
+ * '?', ':', ',', ']', '}', '%', '@', '`'.
+ */
+
+ if len(s) == 0 ||
+ !(isBlankOrZero(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '`') {
+ context := "while scanning an alias"
+ if typ == ANCHOR_TOKEN {
+ context = "while scanning an anchor"
+ }
+ return formatScannerErrorContext(context, start_mark,
+ "did not find expected alphabetic or numeric character", parser.mark)
+ }
+
+ // Create a token.
+ *token = Token{
+ Type: typ,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Value: s,
+ }
+
+ return nil
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func (parser *Parser) scanTag(token *Token) error {
+ var handle, suffix []byte
+
+ start_mark := parser.mark
+
+ // Check if the tag is in the canonical form.
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+
+ if parser.buffer[parser.buffer_pos+1] == '<' {
+ // Keep the handle as ''
+
+ // Eat '!<'
+ parser.skip()
+ parser.skip()
+
+ // Consume the tag value (verbatim tag - flow indicators allowed).
+ if err := parser.scanTagURI(false, true, nil, start_mark, &suffix); err != nil {
+ return err
+ }
+
+ // Check for '>' and eat it.
+ if parser.buffer[parser.buffer_pos] != '>' {
+ return formatScannerErrorContext("while scanning a tag", start_mark,
+ "did not find the expected '>'", parser.mark)
+ }
+
+ parser.skip()
+ } else {
+ // The tag has either the '!suffix' or the '!handle!suffix' form.
+
+ // First, try to scan a handle.
+ if err := parser.scanTagHandle(false, start_mark, &handle); err != nil {
+ return err
+ }
+
+ // Check if it is, indeed, handle.
+ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+ // Scan the suffix now (short form - flow indicators not allowed).
+ if err := parser.scanTagURI(false, false, nil, start_mark, &suffix); err != nil {
+ return err
+ }
+ } else {
+ // It wasn't a handle after all. Scan the rest of the tag (short form).
+ if err := parser.scanTagURI(false, false, handle, start_mark, &suffix); err != nil {
+ return err
+ }
+
+ // Set the handle to '!'.
+ handle = []byte{'!'}
+
+ // A special case: the '!' tag. Set the handle to '' and the
+ // suffix to '!'.
+ if len(suffix) == 0 {
+ handle, suffix = suffix, handle
+ }
+ }
+ }
+
+ // Check the character which ends the tag.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if !isBlankOrZero(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a tag", start_mark,
+ "did not find expected whitespace or line break", parser.mark)
+ }
+
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = Token{
+ Type: TAG_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Value: handle,
+ suffix: suffix,
+ }
+ return nil
+}
+
+// Scan a tag handle.
+func (parser *Parser) scanTagHandle(directive bool, start_mark Mark, handle *[]byte) error {
+ // Check the initial '!' character.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if parser.buffer[parser.buffer_pos] != '!' {
+ return parser.setScannerTagError(directive,
+ start_mark, "did not find expected '!'")
+ }
+
+ var s []byte
+
+ // Copy the '!' character.
+ s = parser.read(s)
+
+ // Copy all subsequent alphabetical and numerical characters.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ for isAlpha(parser.buffer, parser.buffer_pos) {
+ s = parser.read(s)
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Check if the trailing character is '!' and copy it.
+ if parser.buffer[parser.buffer_pos] == '!' {
+ s = parser.read(s)
+ } else {
+ // It's either the '!' tag or not really a tag handle. If it's a %TAG
+ // directive, it's an error. If it's a tag token, it must be a part of URI.
+ if directive && string(s) != "!" {
+ return parser.setScannerTagError(directive,
+ start_mark, "did not find expected '!'")
+ }
+ }
+
+ *handle = s
+ return nil
+}
+
+// Scan a tag URI.
+// directive: true if scanning a %TAG directive URI
+// verbatim: true if scanning a verbatim tag !<...> or TAG directive (flow indicators allowed)
+func (parser *Parser) scanTagURI(directive bool, verbatim bool, head []byte, start_mark Mark, uri *[]byte) error {
+ // size_t length = head ? strlen((char *)head) : 0
+ var s []byte
+ hasTag := len(head) > 0
+
+ // Copy the head if needed.
+ //
+ // Note that we don't copy the leading '!' character.
+ if len(head) > 1 {
+ s = append(s, head[1:]...)
+ }
+
+ // Scan the tag.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ // The set of characters that may appear in URI is as follows:
+ //
+ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+ // '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%'.
+ //
+ // Note: Flow indicators (',', '[', ']', '{', '}') are only allowed in verbatim tags.
+ for isTagURIChar(parser.buffer, parser.buffer_pos, verbatim) {
+ // Check if it is a URI-escape sequence.
+ if parser.buffer[parser.buffer_pos] == '%' {
+ if err := parser.scanURIEscapes(directive, start_mark, &s); err != nil {
+ return err
+ }
+ } else {
+ s = parser.read(s)
+ }
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ hasTag = true
+ }
+
+ // Check for characters which are not allowed in tags.
+ // For non-verbatim tags, if we stopped at a printable character that isn't whitespace,
+ // it's an invalid tag character - give a specific error.
+ // For verbatim tags, the caller will check for the expected '>' delimiter.
+ if !verbatim {
+ c := parser.buffer[parser.buffer_pos]
+ if !isBlankOrZero(parser.buffer, parser.buffer_pos) &&
+ c >= 0x20 && c <= 0x7E {
+ return parser.setScannerTagError(directive, start_mark,
+ fmt.Sprintf("found character '%c' that is not allowed in a YAML tag", c))
+ }
+ }
+
+ if !hasTag {
+ return parser.setScannerTagError(directive,
+ start_mark, "did not find expected tag URI")
+ }
+ *uri = s
+ return nil
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func (parser *Parser) scanURIEscapes(directive bool, start_mark Mark, s *[]byte) error {
+ // Decode the required number of characters.
+ w := 1024
+ for w > 0 {
+ // Check for a URI-escaped octet.
+ if parser.unread < 3 {
+ if err := parser.updateBuffer(3); err != nil {
+ return err
+ }
+ }
+
+ if !(parser.buffer[parser.buffer_pos] == '%' &&
+ isHex(parser.buffer, parser.buffer_pos+1) &&
+ isHex(parser.buffer, parser.buffer_pos+2)) {
+ return parser.setScannerTagError(directive,
+ start_mark, "did not find URI escaped octet")
+ }
+
+ // Get the octet.
+ octet := byte((asHex(parser.buffer, parser.buffer_pos+1) << 4) + asHex(parser.buffer, parser.buffer_pos+2))
+
+ // If it is the leading octet, determine the length of the UTF-8 sequence.
+ if w == 1024 {
+ w = width(octet)
+ if w == 0 {
+ return parser.setScannerTagError(directive,
+ start_mark, "found an incorrect leading UTF-8 octet")
+ }
+ } else {
+ // Check if the trailing octet is correct.
+ if octet&0xC0 != 0x80 {
+ return parser.setScannerTagError(directive,
+ start_mark, "found an incorrect trailing UTF-8 octet")
+ }
+ }
+
+ // Copy the octet and move the pointers.
+ *s = append(*s, octet)
+ parser.skip()
+ parser.skip()
+ parser.skip()
+ w--
+ }
+ return nil
+}
+
+// Scan a block scalar.
+func (parser *Parser) scanBlockScalar(token *Token, literal bool) error {
+ // Eat the indicator '|' or '>'.
+ start_mark := parser.mark
+ parser.skip()
+
+ // Scan the additional block scalar indicators.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ // Check for a chomping indicator.
+ var chomping, increment int
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ // Set the chomping method and eat the indicator.
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ parser.skip()
+
+ // Check for an indentation indicator.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if isDigit(parser.buffer, parser.buffer_pos) {
+ // Check that the indentation is greater than 0.
+ if parser.buffer[parser.buffer_pos] == '0' {
+ return formatScannerErrorContext("while scanning a block scalar", start_mark,
+ "found an indentation indicator equal to 0", parser.mark)
+ }
+
+ // Get the indentation level and eat the indicator.
+ increment = asDigit(parser.buffer, parser.buffer_pos)
+ parser.skip()
+ }
+
+ } else if isDigit(parser.buffer, parser.buffer_pos) {
+ // Do the same as above, but in the opposite order.
+
+ if parser.buffer[parser.buffer_pos] == '0' {
+ return formatScannerErrorContext("while scanning a block scalar", start_mark,
+ "found an indentation indicator equal to 0", parser.mark)
+ }
+ increment = asDigit(parser.buffer, parser.buffer_pos)
+ parser.skip()
+
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ parser.skip()
+ }
+ }
+
+ // Eat whitespaces and comments to the end of the line.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ for isBlank(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+ if parser.buffer[parser.buffer_pos] == '#' {
+ if err := parser.scanLineComment(start_mark); err != nil {
+ return err
+ }
+ for !isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a block scalar", start_mark,
+ "did not find expected comment or line break", parser.mark)
+ }
+
+ // Eat a line break.
+ if isLineBreak(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ parser.skipLine()
+ }
+
+ end_mark := parser.mark
+
+ // Set the indentation level if it was specified.
+ var indent int
+ if increment > 0 {
+ if parser.indent >= 0 {
+ indent = parser.indent + increment
+ } else {
+ indent = increment
+ }
+ }
+
+ // Scan the leading line breaks and determine the indentation level if needed.
+ var s, leading_break, trailing_breaks []byte
+ if err := parser.scanBlockScalarBreaks(&indent, &trailing_breaks, start_mark, &end_mark); err != nil {
+ return err
+ }
+
+ // Scan the block scalar content.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ var leading_blank, trailing_blank bool
+ for parser.mark.Column == indent && !isZeroChar(parser.buffer, parser.buffer_pos) {
+ // We are at the beginning of a non-empty line.
+
+ // Is it a trailing whitespace?
+ trailing_blank = isBlank(parser.buffer, parser.buffer_pos)
+
+ // Check if we need to fold the leading line break.
+ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+ // Do we need to join the lines by space?
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ }
+ } else {
+ s = append(s, leading_break...)
+ }
+ leading_break = leading_break[:0]
+
+ // Append the remaining line breaks.
+ s = append(s, trailing_breaks...)
+ trailing_breaks = trailing_breaks[:0]
+
+ // Is it a leading whitespace?
+ leading_blank = isBlank(parser.buffer, parser.buffer_pos)
+
+ // Consume the current line.
+ for !isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ s = parser.read(s)
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+
+ leading_break = parser.readLine(leading_break)
+
+ // Eat the following indentation spaces and line breaks.
+ if err := parser.scanBlockScalarBreaks(&indent, &trailing_breaks, start_mark, &end_mark); err != nil {
+ return err
+ }
+ }
+
+ // Chomp the tail.
+ if chomping != -1 {
+ s = append(s, leading_break...)
+ }
+ if chomping == 1 {
+ s = append(s, trailing_breaks...)
+ }
+
+ // Create a token.
+ *token = Token{
+ Type: SCALAR_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Value: s,
+ Style: LITERAL_SCALAR_STYLE,
+ }
+ if !literal {
+ token.Style = FOLDED_SCALAR_STYLE
+ }
+ return nil
+}
+
+// Scan indentation spaces and line breaks for a block scalar. Determine the
+// indentation level if needed.
+func (parser *Parser) scanBlockScalarBreaks(indent *int, breaks *[]byte, start_mark Mark, end_mark *Mark) error {
+ *end_mark = parser.mark
+
+ // Eat the indentation spaces and line breaks.
+ max_indent := 0
+ for {
+ // Eat the indentation spaces.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ for (*indent == 0 || parser.mark.Column < *indent) && isSpace(parser.buffer, parser.buffer_pos) {
+ parser.skip()
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+ if parser.mark.Column > max_indent {
+ max_indent = parser.mark.Column
+ }
+
+ // Check for a tab character messing the indentation.
+ if (*indent == 0 || parser.mark.Column < *indent) && isTab(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a block scalar", start_mark,
+ "found a tab character where an indentation space is expected", parser.mark)
+ }
+
+ // Have we found a non-empty line?
+ if !isLineBreak(parser.buffer, parser.buffer_pos) {
+ break
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ // [Go] Should really be returning breaks instead.
+ *breaks = parser.readLine(*breaks)
+ *end_mark = parser.mark
+ }
+
+ // Determine the indentation level if needed.
+ if *indent == 0 {
+ *indent = max_indent
+ if *indent < parser.indent+1 {
+ *indent = parser.indent + 1
+ }
+ if *indent < 1 {
+ *indent = 1
+ }
+ }
+ return nil
+}
+
+// Scan a quoted scalar.
+func (parser *Parser) scanFlowScalar(token *Token, single bool) error {
+ // Eat the left quote.
+ start_mark := parser.mark
+ parser.skip()
+
+ // Consume the content of the quoted scalar.
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ for {
+ // Check that there are no document indicators at the beginning of the line.
+ if parser.unread < 4 {
+ if err := parser.updateBuffer(4); err != nil {
+ return err
+ }
+ }
+
+ if parser.mark.Column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ isBlankOrZero(parser.buffer, parser.buffer_pos+3) {
+ return formatScannerErrorContext("while scanning a quoted scalar", start_mark,
+ "found unexpected document indicator", parser.mark)
+ }
+
+ // Check for EOF.
+ if isZeroChar(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a quoted scalar", start_mark,
+ "found unexpected end of stream", parser.mark)
+ }
+
+ // Consume non-blank characters.
+ leading_blanks := false
+ for !isBlankOrZero(parser.buffer, parser.buffer_pos) {
+ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+ // Is is an escaped single quote.
+ s = append(s, '\'')
+ parser.skip()
+ parser.skip()
+
+ } else if single && parser.buffer[parser.buffer_pos] == '\'' {
+ // It is a right single quote.
+ break
+ } else if !single && parser.buffer[parser.buffer_pos] == '"' {
+ // It is a right double quote.
+ break
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && isLineBreak(parser.buffer, parser.buffer_pos+1) {
+ // It is an escaped line break.
+ if parser.unread < 3 {
+ if err := parser.updateBuffer(3); err != nil {
+ return err
+ }
+ }
+ parser.skip()
+ parser.skipLine()
+ leading_blanks = true
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+ // It is an escape sequence.
+ code_length := 0
+
+ // Check the escape character.
+ switch parser.buffer[parser.buffer_pos+1] {
+ case '0':
+ s = append(s, 0)
+ case 'a':
+ s = append(s, '\x07')
+ case 'b':
+ s = append(s, '\x08')
+ case 't', '\t':
+ s = append(s, '\x09')
+ case 'n':
+ s = append(s, '\x0A')
+ case 'v':
+ s = append(s, '\x0B')
+ case 'f':
+ s = append(s, '\x0C')
+ case 'r':
+ s = append(s, '\x0D')
+ case 'e':
+ s = append(s, '\x1B')
+ case ' ':
+ s = append(s, '\x20')
+ case '"':
+ s = append(s, '"')
+ case '\'':
+ s = append(s, '\'')
+ case '\\':
+ s = append(s, '\\')
+ case 'N': // NEL (#x85)
+ s = append(s, '\xC2')
+ s = append(s, '\x85')
+ case '_': // #xA0
+ s = append(s, '\xC2')
+ s = append(s, '\xA0')
+ case 'L': // LS (#x2028)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA8')
+ case 'P': // PS (#x2029)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA9')
+ case 'x':
+ code_length = 2
+ case 'u':
+ code_length = 4
+ case 'U':
+ code_length = 8
+ default:
+ return formatScannerErrorContext("while scanning a quoted scalar", start_mark,
+ "found unknown escape character", parser.mark)
+ }
+
+ parser.skip()
+ parser.skip()
+
+ // Consume an arbitrary escape code.
+ if code_length > 0 {
+ var value int
+
+ // Scan the character value.
+ if parser.unread < code_length {
+ if err := parser.updateBuffer(code_length); err != nil {
+ return err
+ }
+ }
+ for k := 0; k < code_length; k++ {
+ if !isHex(parser.buffer, parser.buffer_pos+k) {
+ return formatScannerErrorContext("while scanning a quoted scalar", start_mark,
+ "did not find expected hexadecimal number", parser.mark)
+ }
+ value = (value << 4) + asHex(parser.buffer, parser.buffer_pos+k)
+ }
+
+ // Check the value and write the character.
+ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+ return formatScannerErrorContext("while scanning a quoted scalar", start_mark,
+ "found invalid Unicode character escape code", parser.mark)
+ }
+ if value <= 0x7F {
+ s = append(s, byte(value))
+ } else if value <= 0x7FF {
+ s = append(s, byte(0xC0+(value>>6)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else if value <= 0xFFFF {
+ s = append(s, byte(0xE0+(value>>12)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else {
+ s = append(s, byte(0xF0+(value>>18)))
+ s = append(s, byte(0x80+((value>>12)&0x3F)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ }
+
+ // Advance the pointer.
+ for k := 0; k < code_length; k++ {
+ parser.skip()
+ }
+ }
+ } else {
+ // It is a non-escaped non-blank character.
+ s = parser.read(s)
+ }
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ }
+
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ // Check if we are at the end of the scalar.
+ if single {
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ break
+ }
+ } else {
+ if parser.buffer[parser.buffer_pos] == '"' {
+ break
+ }
+ }
+
+ // Consume blank characters.
+ for isBlank(parser.buffer, parser.buffer_pos) || isLineBreak(parser.buffer, parser.buffer_pos) {
+ if isBlank(parser.buffer, parser.buffer_pos) {
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = parser.read(whitespaces)
+ } else {
+ parser.skip()
+ }
+ } else {
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = parser.readLine(leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = parser.readLine(trailing_breaks)
+ }
+ }
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Join the whitespaces or fold line breaks.
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if len(leading_break) > 0 && leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Eat the right quote.
+ parser.skip()
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = Token{
+ Type: SCALAR_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Value: s,
+ Style: SINGLE_QUOTED_SCALAR_STYLE,
+ }
+ if !single {
+ token.Style = DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return nil
+}
+
+// Scan a plain scalar.
+func (parser *Parser) scanPlainScalar(token *Token) error {
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ var leading_blanks bool
+ indent := parser.indent + 1
+
+ start_mark := parser.mark
+ end_mark := parser.mark
+
+ // Consume the content of the plain scalar.
+ for {
+ // Check for a document indicator.
+ if parser.unread < 4 {
+ if err := parser.updateBuffer(4); err != nil {
+ return err
+ }
+ }
+ if parser.mark.Column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ isBlankOrZero(parser.buffer, parser.buffer_pos+3) {
+ break
+ }
+
+ // Check for a comment.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ break
+ }
+
+ // Consume non-blank characters.
+ for !isBlankOrZero(parser.buffer, parser.buffer_pos) {
+
+ // Check for indicators that may end a plain scalar.
+ if (parser.buffer[parser.buffer_pos] == ':' && isBlankOrZero(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level > 0 &&
+ (parser.buffer[parser.buffer_pos] == ',' ||
+ (parser.buffer[parser.buffer_pos] == '?' && isBlankOrZero(parser.buffer, parser.buffer_pos+1)) ||
+ parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}')) {
+ break
+ }
+
+ // Check if we need to join whitespaces and breaks.
+ if leading_blanks || len(whitespaces) > 0 {
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ leading_blanks = false
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Copy the character.
+ s = parser.read(s)
+
+ end_mark = parser.mark
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Is it the end?
+ if !(isBlank(parser.buffer, parser.buffer_pos) || isLineBreak(parser.buffer, parser.buffer_pos)) {
+ break
+ }
+
+ // Consume blank characters.
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+
+ for isBlank(parser.buffer, parser.buffer_pos) || isLineBreak(parser.buffer, parser.buffer_pos) {
+ if isBlank(parser.buffer, parser.buffer_pos) {
+
+ // Check for tab characters that abuse indentation.
+ if leading_blanks && parser.mark.Column < indent && isTab(parser.buffer, parser.buffer_pos) {
+ return formatScannerErrorContext("while scanning a plain scalar", start_mark,
+ "found a tab character that violates indentation", parser.mark)
+ }
+
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = parser.read(whitespaces)
+ } else {
+ parser.skip()
+ }
+ } else {
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = parser.readLine(leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = parser.readLine(trailing_breaks)
+ }
+ }
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Check indentation level.
+ if parser.flow_level == 0 && parser.mark.Column < indent {
+ break
+ }
+ }
+
+ // Create a token.
+ *token = Token{
+ Type: SCALAR_TOKEN,
+ StartMark: start_mark,
+ EndMark: end_mark,
+ Value: s,
+ Style: PLAIN_SCALAR_STYLE,
+ }
+
+ // Note that we change the 'simple_key_allowed' flag.
+ if leading_blanks {
+ parser.simple_key_allowed = true
+ }
+ return nil
+}
+
+func (parser *Parser) scanLineComment(token_mark Mark) error {
+ if parser.newlines > 0 {
+ return nil
+ }
+
+ var start_mark Mark
+ var text []byte
+
+ for peek := 0; peek < 512; peek++ {
+ if parser.unread < peek+1 {
+ if parser.updateBuffer(peek+1) != nil {
+ break
+ }
+ }
+ if isBlank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ if parser.buffer[parser.buffer_pos+peek] == '#' {
+ seen := parser.mark.Index + peek
+ for {
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ if parser.mark.Index >= seen {
+ break
+ }
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ parser.skipLine()
+ } else if parser.mark.Index >= seen {
+ if len(text) == 0 {
+ start_mark = parser.mark
+ }
+ text = parser.read(text)
+ } else {
+ parser.skip()
+ }
+ }
+ }
+ break
+ }
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, Comment{
+ ScanMark: token_mark,
+ TokenMark: token_mark,
+ StartMark: start_mark,
+ EndMark: parser.mark,
+ Line: text,
+ })
+ }
+ return nil
+}
+
+func (parser *Parser) scanComments(scan_mark Mark) error {
+ token := parser.tokens[len(parser.tokens)-1]
+
+ if token.Type == FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
+ token = parser.tokens[len(parser.tokens)-2]
+ }
+
+ token_mark := token.StartMark
+ var start_mark Mark
+ next_indent := parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+
+ recent_empty := false
+ first_empty := parser.newlines <= 1
+
+ line := parser.mark.Line
+ column := parser.mark.Column
+
+ var text []byte
+
+ // The foot line is the place where a comment must start to
+ // still be considered as a foot of the prior content.
+ // If there's some content in the currently parsed line, then
+ // the foot is the line below it.
+ foot_line := -1
+ if scan_mark.Line > 0 {
+ foot_line = parser.mark.Line - parser.newlines + 1
+ if parser.newlines == 0 && parser.mark.Column > 1 {
+ foot_line++
+ }
+ }
+
+ peek := 0
+ for ; peek < 512; peek++ {
+ if parser.unread < peek+1 {
+ if parser.updateBuffer(peek+1) != nil {
+ break
+ }
+ }
+ column++
+ if isBlank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ c := parser.buffer[parser.buffer_pos+peek]
+ close_flow := parser.flow_level > 0 && (c == ']' || c == '}')
+ if close_flow || isBreakOrZero(parser.buffer, parser.buffer_pos+peek) {
+ // Got line break or terminator.
+ if close_flow || !recent_empty {
+ if close_flow || first_empty && (start_mark.Line == foot_line && token.Type != VALUE_TOKEN || start_mark.Column-1 < next_indent) {
+ // This is the first empty line and there were no empty lines before,
+ // so this initial part of the comment is a foot of the prior token
+ // instead of being a head for the following one. Split it up.
+ // Alternatively, this might also be the last comment inside a flow
+ // scope, so it must be a footer.
+ if len(text) > 0 {
+ if start_mark.Column-1 < next_indent {
+ // If dedented it's unrelated to the prior token.
+ token_mark = start_mark
+ }
+ parser.comments = append(parser.comments, Comment{
+ ScanMark: scan_mark,
+ TokenMark: token_mark,
+ StartMark: start_mark,
+ EndMark: Mark{parser.mark.Index + peek, line, column},
+ Foot: text,
+ })
+ scan_mark = Mark{parser.mark.Index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+ } else {
+ if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
+ text = append(text, '\n')
+ }
+ }
+ }
+ if !isLineBreak(parser.buffer, parser.buffer_pos+peek) {
+ break
+ }
+ first_empty = false
+ recent_empty = true
+ column = 0
+ line++
+ continue
+ }
+
+ if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.Column) {
+ // The comment at the different indentation is a foot of the
+ // preceding data rather than a head of the upcoming one.
+ parser.comments = append(parser.comments, Comment{
+ ScanMark: scan_mark,
+ TokenMark: token_mark,
+ StartMark: start_mark,
+ EndMark: Mark{parser.mark.Index + peek, line, column},
+ Foot: text,
+ })
+ scan_mark = Mark{parser.mark.Index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+
+ if parser.buffer[parser.buffer_pos+peek] != '#' {
+ break
+ }
+
+ if len(text) == 0 {
+ start_mark = Mark{parser.mark.Index + peek, line, column}
+ } else {
+ text = append(text, '\n')
+ }
+
+ recent_empty = false
+
+ // Consume until after the consumed comment line.
+ seen := parser.mark.Index + peek
+ for {
+ if parser.unread < 1 {
+ if err := parser.updateBuffer(1); err != nil {
+ return err
+ }
+ }
+ if isBreakOrZero(parser.buffer, parser.buffer_pos) {
+ if parser.mark.Index >= seen {
+ break
+ }
+ if parser.unread < 2 {
+ if err := parser.updateBuffer(2); err != nil {
+ return err
+ }
+ }
+ parser.skipLine()
+ } else if parser.mark.Index >= seen {
+ text = parser.read(text)
+ } else {
+ parser.skip()
+ }
+ }
+
+ peek = 0
+ column = 0
+ line = parser.mark.Line
+ next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+ }
+
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, Comment{
+ ScanMark: scan_mark,
+ TokenMark: start_mark,
+ StartMark: start_mark,
+ EndMark: Mark{parser.mark.Index + peek - 1, line, column},
+ Head: text,
+ })
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/serializer.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/serializer.go
new file mode 100644
index 00000000000..7ec160dc8d1
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/serializer.go
@@ -0,0 +1,219 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Serializer stage: Converts representation tree (Nodes) to event stream.
+// Walks the node tree and produces events for the emitter.
+
+package libyaml
+
+import (
+ "strings"
+ "unicode/utf8"
+)
+
+// node serializes a Node tree into YAML events.
+// This is the core of the serializer stage - it walks the tree and produces events.
+func (r *Representer) node(node *Node, tail string) {
+ // Zero nodes behave as nil.
+ if node.Kind == 0 && node.IsZero() {
+ r.nilv()
+ return
+ }
+
+ // If the tag was not explicitly requested, and dropping it won't change the
+ // implicit tag of the value, don't include it in the presentation.
+ tag := node.Tag
+ stag := shortTag(tag)
+ var forceQuoting bool
+ if tag != "" && node.Style&TaggedStyle == 0 {
+ if node.Kind == ScalarNode {
+ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+ tag = ""
+ } else {
+ rtag, _ := resolve("", node.Value)
+ if rtag == stag && stag != mergeTag {
+ tag = ""
+ } else if stag == strTag {
+ tag = ""
+ forceQuoting = true
+ }
+ }
+ } else {
+ var rtag string
+ switch node.Kind {
+ case MappingNode:
+ rtag = mapTag
+ case SequenceNode:
+ rtag = seqTag
+ }
+ if rtag == stag {
+ tag = ""
+ }
+ }
+ }
+
+ switch node.Kind {
+ case DocumentNode:
+ event := NewDocumentStartEvent(noVersionDirective, noTagDirective, !r.explicitStart)
+ event.HeadComment = []byte(node.HeadComment)
+ r.emit(event)
+ for _, node := range node.Content {
+ r.node(node, "")
+ }
+ event = NewDocumentEndEvent(!r.explicitEnd)
+ event.FootComment = []byte(node.FootComment)
+ r.emit(event)
+
+ case SequenceNode:
+ style := BLOCK_SEQUENCE_STYLE
+ // Use flow style if explicitly requested or if it's a simple
+ // collection (scalar-only contents that fit within line width,
+ // enabled via WithFlowSimpleCollections)
+ if node.Style&FlowStyle != 0 || r.isSimpleCollection(node) {
+ style = FLOW_SEQUENCE_STYLE
+ }
+ event := NewSequenceStartEvent([]byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+ event.HeadComment = []byte(node.HeadComment)
+ r.emit(event)
+ for _, node := range node.Content {
+ r.node(node, "")
+ }
+ event = NewSequenceEndEvent()
+ event.LineComment = []byte(node.LineComment)
+ event.FootComment = []byte(node.FootComment)
+ r.emit(event)
+
+ case MappingNode:
+ style := BLOCK_MAPPING_STYLE
+ // Use flow style if explicitly requested or if it's a simple
+ // collection (scalar-only contents that fit within line width,
+ // enabled via WithFlowSimpleCollections)
+ if node.Style&FlowStyle != 0 || r.isSimpleCollection(node) {
+ style = FLOW_MAPPING_STYLE
+ }
+ event := NewMappingStartEvent([]byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+ event.TailComment = []byte(tail)
+ event.HeadComment = []byte(node.HeadComment)
+ r.emit(event)
+
+ // The tail logic below moves the foot comment of prior keys to the following key,
+ // since the value for each key may be a nested structure and the foot needs to be
+ // processed only the entirety of the value is streamed. The last tail is processed
+ // with the mapping end event.
+ var tail string
+ for i := 0; i+1 < len(node.Content); i += 2 {
+ k := node.Content[i]
+ foot := k.FootComment
+ if foot != "" {
+ kopy := *k
+ kopy.FootComment = ""
+ k = &kopy
+ }
+ r.node(k, tail)
+ tail = foot
+
+ v := node.Content[i+1]
+ r.node(v, "")
+ }
+
+ event = NewMappingEndEvent()
+ event.TailComment = []byte(tail)
+ event.LineComment = []byte(node.LineComment)
+ event.FootComment = []byte(node.FootComment)
+ r.emit(event)
+
+ case AliasNode:
+ event := NewAliasEvent([]byte(node.Value))
+ event.HeadComment = []byte(node.HeadComment)
+ event.LineComment = []byte(node.LineComment)
+ event.FootComment = []byte(node.FootComment)
+ r.emit(event)
+
+ case ScalarNode:
+ value := node.Value
+ if !utf8.ValidString(value) {
+ if stag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if stag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", stag)
+ }
+ // It can't be represented directly as YAML so use a binary tag
+ // and represent it as base64.
+ tag = binaryTag
+ value = encodeBase64(value)
+ }
+
+ style := PLAIN_SCALAR_STYLE
+ switch {
+ case node.Style&DoubleQuotedStyle != 0:
+ style = DOUBLE_QUOTED_SCALAR_STYLE
+ case node.Style&SingleQuotedStyle != 0:
+ style = SINGLE_QUOTED_SCALAR_STYLE
+ case node.Style&LiteralStyle != 0:
+ style = LITERAL_SCALAR_STYLE
+ case node.Style&FoldedStyle != 0:
+ style = FOLDED_SCALAR_STYLE
+ case strings.Contains(value, "\n"):
+ style = LITERAL_SCALAR_STYLE
+ case forceQuoting:
+ style = r.quotePreference.ScalarStyle()
+ }
+
+ r.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+ default:
+ failf("cannot represent node with unknown kind %d", node.Kind)
+ }
+}
+
+// isSimpleCollection checks if a node contains only scalar values and would
+// fit within the line width when rendered in flow style.
+func (r *Representer) isSimpleCollection(node *Node) bool {
+ if !r.flowSimpleCollections {
+ return false
+ }
+ if node.Kind != SequenceNode && node.Kind != MappingNode {
+ return false
+ }
+ // Check all children are scalars
+ for _, child := range node.Content {
+ if child.Kind != ScalarNode {
+ return false
+ }
+ }
+ // Estimate flow style length
+ estimatedLen := r.estimateFlowLength(node)
+ width := r.lineWidth
+ if width <= 0 {
+ width = 80 // Default width if not set
+ }
+ return estimatedLen > 0 && estimatedLen <= width
+}
+
+// estimateFlowLength estimates the character length of a node in flow style.
+func (r *Representer) estimateFlowLength(node *Node) int {
+ if node.Kind == SequenceNode {
+ // [item1, item2, ...] = 2 + sum(len(items)) + 2*(len-1)
+ length := 2 // []
+ for i, child := range node.Content {
+ if i > 0 {
+ length += 2 // ", "
+ }
+ length += len(child.Value)
+ }
+ return length
+ }
+ if node.Kind == MappingNode {
+ // {key1: val1, key2: val2} = 2 + sum(key: val) + 2*(pairs-1)
+ length := 2 // {}
+ for i := 0; i < len(node.Content); i += 2 {
+ if i > 0 {
+ length += 2 // ", "
+ }
+ length += len(node.Content[i].Value) + 2 + len(node.Content[i+1].Value) // "key: val"
+ }
+ return length
+ }
+ return 0
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/writer.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/writer.go
new file mode 100644
index 00000000000..dcd51d6ce3c
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/writer.go
@@ -0,0 +1,31 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Output writer with buffering.
+// Provides write buffering for the emitter stage.
+
+package libyaml
+
+import "fmt"
+
+// Flush the output buffer.
+func (emitter *Emitter) flush() error {
+ if emitter.write_handler == nil {
+ panic("write handler not set")
+ }
+
+ // Check if the buffer is empty.
+ if emitter.buffer_pos == 0 {
+ return nil
+ }
+
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+ return WriterError{
+ Err: fmt.Errorf("write error: %w", err),
+ }
+ }
+ emitter.buffer_pos = 0
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yaml.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yaml.go
new file mode 100644
index 00000000000..f9f4f1f4938
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yaml.go
@@ -0,0 +1,834 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Core libyaml types and structures.
+// Defines Parser, Emitter, Event, Token, and related constants for YAML
+// processing.
+
+package libyaml
+
+import (
+ "fmt"
+ "io"
+ "strings"
+)
+
+// VersionDirective holds the YAML version directive data.
+type VersionDirective struct {
+ major int8 // The major version number.
+ minor int8 // The minor version number.
+}
+
+// Major returns the major version number.
+func (v *VersionDirective) Major() int { return int(v.major) }
+
+// Minor returns the minor version number.
+func (v *VersionDirective) Minor() int { return int(v.minor) }
+
+// TagDirective holds the YAML tag directive data.
+type TagDirective struct {
+ handle []byte // The tag handle.
+ prefix []byte // The tag prefix.
+}
+
+// GetHandle returns the tag handle.
+func (t *TagDirective) GetHandle() string { return string(t.handle) }
+
+// GetPrefix returns the tag prefix.
+func (t *TagDirective) GetPrefix() string { return string(t.prefix) }
+
+type Encoding int
+
+// The stream encoding.
+const (
+ // Let the parser choose the encoding.
+ ANY_ENCODING Encoding = iota
+
+ UTF8_ENCODING // The default UTF-8 encoding.
+ UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+ UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type LineBreak int
+
+// Line break types.
+const (
+ // Let the parser choose the break type.
+ ANY_BREAK LineBreak = iota
+
+ CR_BREAK // Use CR for line breaks (Mac style).
+ LN_BREAK // Use LN for line breaks (Unix style).
+ CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type QuoteStyle int
+
+// Quote style types for required quoting.
+const (
+ QuoteSingle QuoteStyle = iota // Prefer single quotes when quoting is required.
+ QuoteDouble // Prefer double quotes when quoting is required.
+ QuoteLegacy // Legacy behavior: double in representer, single in emitter.
+)
+
+// ScalarStyle returns the scalar style for this quote preference in the
+// representer/serializer context.
+// In this context, both QuoteDouble and QuoteLegacy use double quotes.
+func (q QuoteStyle) ScalarStyle() ScalarStyle {
+ if q == QuoteDouble || q == QuoteLegacy {
+ return DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return SINGLE_QUOTED_SCALAR_STYLE
+}
+
+type ErrorType int
+
+// Many bad things could happen with the parser and emitter.
+const (
+ // No error is produced.
+ NO_ERROR ErrorType = iota
+
+ MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
+ READER_ERROR // Cannot read or decode the input stream.
+ SCANNER_ERROR // Cannot scan the input stream.
+ PARSER_ERROR // Cannot parse the input stream.
+ COMPOSER_ERROR // Cannot compose a YAML document.
+ WRITER_ERROR // Cannot write to the output stream.
+ EMITTER_ERROR // Cannot emit a YAML stream.
+)
+
+// Mark holds the pointer position.
+type Mark struct {
+ Index int // The position index.
+ Line int // The position line (1-indexed).
+ Column int // The position column (0-indexed internally, displayed as 1-indexed).
+}
+
+func (m Mark) String() string {
+ var builder strings.Builder
+ if m.Line == 0 {
+ return ""
+ }
+
+ fmt.Fprintf(&builder, "line %d", m.Line)
+ if m.Column != 0 {
+ fmt.Fprintf(&builder, ", column %d", m.Column+1)
+ }
+
+ return builder.String()
+}
+
+// Node Styles
+
+type styleInt int8
+
+type ScalarStyle styleInt
+
+// Scalar styles.
+const (
+ // Let the emitter choose the style.
+ ANY_SCALAR_STYLE ScalarStyle = 0
+
+ PLAIN_SCALAR_STYLE ScalarStyle = 1 << iota // The plain scalar style.
+ SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
+ DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
+ LITERAL_SCALAR_STYLE // The literal scalar style.
+ FOLDED_SCALAR_STYLE // The folded scalar style.
+)
+
+// String returns a string representation of a [ScalarStyle].
+func (style ScalarStyle) String() string {
+ switch style {
+ case PLAIN_SCALAR_STYLE:
+ return "Plain"
+ case SINGLE_QUOTED_SCALAR_STYLE:
+ return "Single"
+ case DOUBLE_QUOTED_SCALAR_STYLE:
+ return "Double"
+ case LITERAL_SCALAR_STYLE:
+ return "Literal"
+ case FOLDED_SCALAR_STYLE:
+ return "Folded"
+ default:
+ return ""
+ }
+}
+
+type SequenceStyle styleInt
+
+// Sequence styles.
+const (
+ // Let the emitter choose the style.
+ ANY_SEQUENCE_STYLE SequenceStyle = iota
+
+ BLOCK_SEQUENCE_STYLE // The block sequence style.
+ FLOW_SEQUENCE_STYLE // The flow sequence style.
+)
+
+type MappingStyle styleInt
+
+// Mapping styles.
+const (
+ // Let the emitter choose the style.
+ ANY_MAPPING_STYLE MappingStyle = iota
+
+ BLOCK_MAPPING_STYLE // The block mapping style.
+ FLOW_MAPPING_STYLE // The flow mapping style.
+)
+
+// Tokens
+
+type TokenType int
+
+// Token types.
+const (
+ // An empty token.
+ NO_TOKEN TokenType = iota
+
+ STREAM_START_TOKEN // A STREAM-START token.
+ STREAM_END_TOKEN // A STREAM-END token.
+
+ VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+ TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
+ DOCUMENT_START_TOKEN // A DOCUMENT-START token.
+ DOCUMENT_END_TOKEN // A DOCUMENT-END token.
+
+ BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+ BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
+ BLOCK_END_TOKEN // A BLOCK-END token.
+
+ FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+ FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
+ FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
+ FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
+
+ BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+ FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
+ KEY_TOKEN // A KEY token.
+ VALUE_TOKEN // A VALUE token.
+
+ ALIAS_TOKEN // An ALIAS token.
+ ANCHOR_TOKEN // An ANCHOR token.
+ TAG_TOKEN // A TAG token.
+ SCALAR_TOKEN // A SCALAR token.
+ COMMENT_TOKEN // A COMMENT token.
+)
+
+func (tt TokenType) String() string {
+ switch tt {
+ case NO_TOKEN:
+ return "NO_TOKEN"
+ case STREAM_START_TOKEN:
+ return "STREAM_START_TOKEN"
+ case STREAM_END_TOKEN:
+ return "STREAM_END_TOKEN"
+ case VERSION_DIRECTIVE_TOKEN:
+ return "VERSION_DIRECTIVE_TOKEN"
+ case TAG_DIRECTIVE_TOKEN:
+ return "TAG_DIRECTIVE_TOKEN"
+ case DOCUMENT_START_TOKEN:
+ return "DOCUMENT_START_TOKEN"
+ case DOCUMENT_END_TOKEN:
+ return "DOCUMENT_END_TOKEN"
+ case BLOCK_SEQUENCE_START_TOKEN:
+ return "BLOCK_SEQUENCE_START_TOKEN"
+ case BLOCK_MAPPING_START_TOKEN:
+ return "BLOCK_MAPPING_START_TOKEN"
+ case BLOCK_END_TOKEN:
+ return "BLOCK_END_TOKEN"
+ case FLOW_SEQUENCE_START_TOKEN:
+ return "FLOW_SEQUENCE_START_TOKEN"
+ case FLOW_SEQUENCE_END_TOKEN:
+ return "FLOW_SEQUENCE_END_TOKEN"
+ case FLOW_MAPPING_START_TOKEN:
+ return "FLOW_MAPPING_START_TOKEN"
+ case FLOW_MAPPING_END_TOKEN:
+ return "FLOW_MAPPING_END_TOKEN"
+ case BLOCK_ENTRY_TOKEN:
+ return "BLOCK_ENTRY_TOKEN"
+ case FLOW_ENTRY_TOKEN:
+ return "FLOW_ENTRY_TOKEN"
+ case KEY_TOKEN:
+ return "KEY_TOKEN"
+ case VALUE_TOKEN:
+ return "VALUE_TOKEN"
+ case ALIAS_TOKEN:
+ return "ALIAS_TOKEN"
+ case ANCHOR_TOKEN:
+ return "ANCHOR_TOKEN"
+ case TAG_TOKEN:
+ return "TAG_TOKEN"
+ case SCALAR_TOKEN:
+ return "SCALAR_TOKEN"
+ case COMMENT_TOKEN:
+ return "COMMENT_TOKEN"
+ }
+ return ""
+}
+
+// Token holds information about a scanning token.
+type Token struct {
+ // The token type.
+ Type TokenType
+
+ // The start/end of the token.
+ StartMark, EndMark Mark
+
+ // The stream encoding (for STREAM_START_TOKEN).
+ encoding Encoding
+
+ // The alias/anchor/scalar Value or tag/tag directive handle
+ // (for ALIAS_TOKEN, ANCHOR_TOKEN, SCALAR_TOKEN, TAG_TOKEN, TAG_DIRECTIVE_TOKEN).
+ Value []byte
+
+ // The tag suffix (for TAG_TOKEN).
+ suffix []byte
+
+ // The tag directive prefix (for TAG_DIRECTIVE_TOKEN).
+ prefix []byte
+
+ // The scalar Style (for SCALAR_TOKEN).
+ Style ScalarStyle
+
+ // The version directive major/minor (for VERSION_DIRECTIVE_TOKEN).
+ major, minor int8
+}
+
+// Events
+
+type EventType int8
+
+// Event types.
+const (
+ // An empty event.
+ NO_EVENT EventType = iota
+
+ STREAM_START_EVENT // A STREAM-START event.
+ STREAM_END_EVENT // A STREAM-END event.
+ DOCUMENT_START_EVENT // A DOCUMENT-START event.
+ DOCUMENT_END_EVENT // A DOCUMENT-END event.
+ ALIAS_EVENT // An ALIAS event.
+ SCALAR_EVENT // A SCALAR event.
+ SEQUENCE_START_EVENT // A SEQUENCE-START event.
+ SEQUENCE_END_EVENT // A SEQUENCE-END event.
+ MAPPING_START_EVENT // A MAPPING-START event.
+ MAPPING_END_EVENT // A MAPPING-END event.
+ TAIL_COMMENT_EVENT
+)
+
+var eventStrings = []string{
+ NO_EVENT: "none",
+ STREAM_START_EVENT: "stream start",
+ STREAM_END_EVENT: "stream end",
+ DOCUMENT_START_EVENT: "document start",
+ DOCUMENT_END_EVENT: "document end",
+ ALIAS_EVENT: "alias",
+ SCALAR_EVENT: "scalar",
+ SEQUENCE_START_EVENT: "sequence start",
+ SEQUENCE_END_EVENT: "sequence end",
+ MAPPING_START_EVENT: "mapping start",
+ MAPPING_END_EVENT: "mapping end",
+ TAIL_COMMENT_EVENT: "tail comment",
+}
+
+func (e EventType) String() string {
+ if e < 0 || int(e) >= len(eventStrings) {
+ return fmt.Sprintf("unknown event %d", e)
+ }
+ return eventStrings[e]
+}
+
+// Event holds information about a parsing or emitting event.
+type Event struct {
+ // The event type.
+ Type EventType
+
+ // The start and end of the event.
+ StartMark, EndMark Mark
+
+ // The document encoding (for STREAM_START_EVENT).
+ encoding Encoding
+
+ // The version directive (for DOCUMENT_START_EVENT).
+ versionDirective *VersionDirective
+
+ // The list of tag directives (for DOCUMENT_START_EVENT).
+ tagDirectives []TagDirective
+
+ // The comments
+ HeadComment []byte
+ LineComment []byte
+ FootComment []byte
+ TailComment []byte
+
+ // The Anchor (for SCALAR_EVENT, SEQUENCE_START_EVENT, MAPPING_START_EVENT, ALIAS_EVENT).
+ Anchor []byte
+
+ // The Tag (for SCALAR_EVENT, SEQUENCE_START_EVENT, MAPPING_START_EVENT).
+ Tag []byte
+
+ // The scalar Value (for SCALAR_EVENT).
+ Value []byte
+
+ // Is the document start/end indicator Implicit, or the tag optional?
+ // (for DOCUMENT_START_EVENT, DOCUMENT_END_EVENT, SEQUENCE_START_EVENT, MAPPING_START_EVENT, SCALAR_EVENT).
+ Implicit bool
+
+ // Is the tag optional for any non-plain style? (for SCALAR_EVENT).
+ quoted_implicit bool
+
+ // The Style (for SCALAR_EVENT, SEQUENCE_START_EVENT, MAPPING_START_EVENT).
+ Style Style
+}
+
+func (e *Event) ScalarStyle() ScalarStyle { return ScalarStyle(e.Style) }
+func (e *Event) SequenceStyle() SequenceStyle { return SequenceStyle(e.Style) }
+func (e *Event) MappingStyle() MappingStyle { return MappingStyle(e.Style) }
+
+// GetEncoding returns the stream encoding (for STREAM_START_EVENT).
+func (e *Event) GetEncoding() Encoding { return e.encoding }
+
+// GetVersionDirective returns the version directive (for DOCUMENT_START_EVENT).
+func (e *Event) GetVersionDirective() *VersionDirective { return e.versionDirective }
+
+// GetTagDirectives returns the tag directives (for DOCUMENT_START_EVENT).
+func (e *Event) GetTagDirectives() []TagDirective { return e.tagDirectives }
+
+// Nodes
+
+const (
+ NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
+ BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
+ STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
+ INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
+ FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
+ TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+ SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+ MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+ // Not in original libyaml.
+ BINARY_TAG = "tag:yaml.org,2002:binary"
+ MERGE_TAG = "tag:yaml.org,2002:merge"
+
+ DEFAULT_SCALAR_TAG = STR_TAG // The default scalar tag is !!str.
+ DEFAULT_SEQUENCE_TAG = SEQ_TAG // The default sequence tag is !!seq.
+ DEFAULT_MAPPING_TAG = MAP_TAG // The default mapping tag is !!map.
+)
+
+type NodeType int
+
+// Node types.
+const (
+ // An empty node.
+ NO_NODE NodeType = iota
+
+ SCALAR_NODE // A scalar node.
+ SEQUENCE_NODE // A sequence node.
+ MAPPING_NODE // A mapping node.
+)
+
+// NodeItem represents an element of a sequence node.
+type NodeItem int
+
+// NodePair represents an element of a mapping node.
+type NodePair struct {
+ key int // The key of the element.
+ value int // The value of the element.
+}
+
+// parserNode represents a single node in the YAML document tree.
+type parserNode struct {
+ typ NodeType // The node type.
+ tag []byte // The node tag.
+
+ // The node data.
+
+ // The scalar parameters (for SCALAR_NODE).
+ scalar struct {
+ value []byte // The scalar value.
+ length int // The length of the scalar value.
+ style ScalarStyle // The scalar style.
+ }
+
+ // The sequence parameters (for YAML_SEQUENCE_NODE).
+ sequence struct {
+ items_data []NodeItem // The stack of sequence items.
+ style SequenceStyle // The sequence style.
+ }
+
+ // The mapping parameters (for MAPPING_NODE).
+ mapping struct {
+ pairs_data []NodePair // The stack of mapping pairs (key, value).
+ pairs_start *NodePair // The beginning of the stack.
+ pairs_end *NodePair // The end of the stack.
+ pairs_top *NodePair // The top of the stack.
+ style MappingStyle // The mapping style.
+ }
+
+ start_mark Mark // The beginning of the node.
+ end_mark Mark // The end of the node.
+}
+
+// Document structure.
+type Document struct {
+ // The document nodes.
+ nodes []parserNode
+
+ // The version directive.
+ version_directive *VersionDirective
+
+ // The list of tag directives.
+ tag_directives_data []TagDirective
+ tag_directives_start int // The beginning of the tag directives list.
+ tag_directives_end int // The end of the tag directives list.
+
+ start_implicit int // Is the document start indicator implicit?
+ end_implicit int // Is the document end indicator implicit?
+
+ // The start/end of the document.
+ start_mark, end_mark Mark
+}
+
+// ReadHandler is called when the [Parser] needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out] data A pointer to an application data specified by
+//
+// yamlParser.setInput().
+//
+// [out] buffer The buffer to write the data from the source.
+// [in] size The size of the buffer.
+// [out] size_read The actual number of bytes read from the source.
+//
+// On success, the handler should return 1. If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type ReadHandler func(parser *Parser, buffer []byte) (n int, err error)
+
+// SimpleKey holds information about a potential simple key.
+type SimpleKey struct {
+ flow_level int // What flow level is the key at?
+ required bool // Is a simple key required?
+ token_number int // The number of the token.
+ mark Mark // The position mark.
+}
+
+// ParserState represents the state of the parser.
+type ParserState int
+
+const (
+ PARSE_STREAM_START_STATE ParserState = iota
+
+ PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
+ PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
+ PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ PARSE_BLOCK_NODE_STATE // Expect a block node.
+ PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
+ PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
+ PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
+ PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
+ PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
+ PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
+ PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
+ PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
+ PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+ PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
+ PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
+ PARSE_END_STATE // Expect nothing.
+)
+
+func (ps ParserState) String() string {
+ switch ps {
+ case PARSE_STREAM_START_STATE:
+ return "PARSE_STREAM_START_STATE"
+ case PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return "PARSE_IMPLICIT_DOCUMENT_START_STATE"
+ case PARSE_DOCUMENT_START_STATE:
+ return "PARSE_DOCUMENT_START_STATE"
+ case PARSE_DOCUMENT_CONTENT_STATE:
+ return "PARSE_DOCUMENT_CONTENT_STATE"
+ case PARSE_DOCUMENT_END_STATE:
+ return "PARSE_DOCUMENT_END_STATE"
+ case PARSE_BLOCK_NODE_STATE:
+ return "PARSE_BLOCK_NODE_STATE"
+ case PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return "PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+ case PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return "PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+ case PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return "PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+ case PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return "PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+ case PARSE_BLOCK_MAPPING_KEY_STATE:
+ return "PARSE_BLOCK_MAPPING_KEY_STATE"
+ case PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return "PARSE_BLOCK_MAPPING_VALUE_STATE"
+ case PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return "PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+ case PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return "PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+ case PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return "PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+ case PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return "PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+ case PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return "PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+ case PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return "PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+ case PARSE_FLOW_MAPPING_KEY_STATE:
+ return "PARSE_FLOW_MAPPING_KEY_STATE"
+ case PARSE_FLOW_MAPPING_VALUE_STATE:
+ return "PARSE_FLOW_MAPPING_VALUE_STATE"
+ case PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return "PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+ case PARSE_END_STATE:
+ return "PARSE_END_STATE"
+ }
+ return ""
+}
+
+// AliasData holds information about aliases.
+type AliasData struct {
+ anchor []byte // The anchor.
+ index int // The node id.
+ mark Mark // The anchor mark.
+}
+
+// Parser structure holds all information about the current
+// state of the parser.
+type Parser struct {
+ lastError error
+
+ // Reader stuff
+ read_handler ReadHandler // Read handler.
+
+ input_reader io.Reader // File input data.
+ input []byte // String input data.
+ input_pos int
+
+ eof bool // EOF flag
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ unread int // The number of unread characters in the buffer.
+
+ newlines int // The number of line breaks since last non-break/non-blank character
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding Encoding // The input encoding.
+
+ offset int // The offset of the current position (in bytes).
+ mark Mark // The mark of the current position.
+
+ // Comments
+
+ HeadComment []byte // The current head comments
+ LineComment []byte // The current line comments
+ FootComment []byte // The current foot comments
+ tail_comment []byte // Foot comment that happens at the end of a block.
+ stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
+
+ comments []Comment // The folded comments for all parsed tokens
+ comments_head int
+
+ // Scanner stuff
+
+ stream_start_produced bool // Have we started to scan the input stream?
+ stream_end_produced bool // Have we reached the end of the input stream?
+
+ flow_level int // The number of unclosed '[' and '{' indicators.
+
+ tokens []Token // The tokens queue.
+ tokens_head int // The head of the tokens queue.
+ tokens_parsed int // The number of tokens fetched from the queue.
+ token_available bool // Does the tokens queue contain a token ready for dequeueing.
+
+ indent int // The current indentation level.
+ indents []int // The indentation levels stack.
+
+ simple_key_allowed bool // May a simple key occur at the current position?
+ simple_key_possible bool // Is the current simple key possible?
+ simple_key SimpleKey // The current simple key.
+ simple_key_stack []SimpleKey // The stack of simple keys.
+
+ // Parser stuff
+
+ state ParserState // The current parser state.
+ states []ParserState // The parser states stack.
+ marks []Mark // The stack of marks.
+ tag_directives []TagDirective // The list of TAG directives.
+
+ // Representer stuff
+
+ aliases []AliasData // The alias data.
+
+ document *Document // The currently parsed document.
+}
+
+type Comment struct {
+ ScanMark Mark // Position where scanning for comments started
+ TokenMark Mark // Position after which tokens will be associated with this comment
+ StartMark Mark // Position of '#' comment mark
+ EndMark Mark // Position where comment terminated
+
+ Head []byte
+ Line []byte
+ Foot []byte
+}
+
+// Emitter Definitions
+
+// WriteHandler is called when the [Emitter] needs to flush the accumulated
+// characters to the output. The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out] data A pointer to an application data specified by
+//
+// yamlEmitter.setOutput().
+//
+// @param[in] buffer The buffer with bytes to be written.
+// @param[in] size The size of the buffer.
+//
+// @returns On success, the handler should return @c 1. If the handler failed,
+// the returned value should be @c 0.
+type WriteHandler func(emitter *Emitter, buffer []byte) error
+
+type EmitterState int
+
+// The emitter states.
+const (
+ // Expect STREAM-START.
+ EMIT_STREAM_START_STATE EmitterState = iota
+
+ EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
+ EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
+ EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
+ EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
+ EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
+ EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
+ EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
+ EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
+ EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
+ EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
+ EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+ EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
+ EMIT_END_STATE // Expect nothing.
+)
+
+// Emitter holds all information about the current state of the emitter.
+type Emitter struct {
+ // Writer stuff
+
+ write_handler WriteHandler // Write handler.
+
+ output_buffer *[]byte // String output data.
+ output_writer io.Writer // File output data.
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ encoding Encoding // The stream encoding.
+
+ // Emitter stuff
+
+ canonical bool // If the output is in the canonical style?
+ BestIndent int // The number of indentation spaces.
+ best_width int // The preferred width of the output lines.
+ unicode bool // Allow unescaped non-ASCII characters?
+ line_break LineBreak // The preferred line break.
+ quotePreference QuoteStyle // Preferred quote style when quoting is required.
+
+ state EmitterState // The current emitter state.
+ states []EmitterState // The stack of states.
+
+ events []Event // The event queue.
+ events_head int // The head of the event queue.
+
+ indents []int // The stack of indentation levels.
+
+ tag_directives []TagDirective // The list of tag directives.
+
+ indent int // The current indentation level.
+
+ CompactSequenceIndent bool // Is '- ' is considered part of the indentation for sequence elements?
+
+ flow_level int // The current flow level.
+
+ root_context bool // Is it the document root context?
+ sequence_context bool // Is it a sequence context?
+ mapping_context bool // Is it a mapping context?
+ simple_key_context bool // Is it a simple mapping key context?
+
+ line int // The current line.
+ column int // The current column.
+ whitespace bool // If the last character was a whitespace?
+ indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
+ OpenEnded bool // If an explicit document end is required?
+
+ space_above bool // Is there's an empty line above?
+ foot_indent int // The indent used to write the foot comment above, or -1 if none.
+
+ // Anchor analysis.
+ anchor_data struct {
+ anchor []byte // The anchor value.
+ alias bool // Is it an alias?
+ }
+
+ // Tag analysis.
+ tag_data struct {
+ handle []byte // The tag handle.
+ suffix []byte // The tag suffix.
+ }
+
+ // Scalar analysis.
+ scalar_data struct {
+ value []byte // The scalar value.
+ multiline bool // Does the scalar contain line breaks?
+ flow_plain_allowed bool // Can the scalar be expressed in the flow plain style?
+ block_plain_allowed bool // Can the scalar be expressed in the block plain style?
+ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
+ block_allowed bool // Can the scalar be expressed in the literal or folded styles?
+ style ScalarStyle // The output style.
+ }
+
+ // Comments
+ HeadComment []byte
+ LineComment []byte
+ FootComment []byte
+ TailComment []byte
+
+ key_line_comment []byte
+
+ // Representer stuff
+
+ opened bool // If the stream was already opened?
+ closed bool // If the stream was already closed?
+
+ // The information associated with the document nodes.
+ anchors *struct {
+ references int // The number of references.
+ anchor int // The anchor id.
+ serialized bool // If the node has been emitted?
+ }
+
+ last_anchor_id int // The last assigned anchor id.
+
+ document *Document // The currently emitted document.
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yamldatatest_loader.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yamldatatest_loader.go
new file mode 100644
index 00000000000..5ca2ff0eab5
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yamldatatest_loader.go
@@ -0,0 +1,192 @@
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// YAML test data loading utilities.
+// Provides helper functions for loading and processing YAML test data,
+// including scalar coercion.
+
+package libyaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// coerceScalar converts a YAML scalar string to an appropriate Go type
+func coerceScalar(value string) any {
+ // Try bool and null
+ switch value {
+ case "true":
+ return true
+ case "false":
+ return false
+ case "null":
+ return nil
+ }
+
+ // Try hex int (0x or 0X prefix) - needed for test data byte arrays
+ var intVal int
+ if _, err := fmt.Sscanf(strings.ToLower(value), "0x%x", &intVal); err == nil {
+ return intVal
+ }
+
+ // Try float (must check before int because %d will parse "1.5" as "1")
+ if strings.Contains(value, ".") {
+ var floatVal float64
+ if _, err := fmt.Sscanf(value, "%f", &floatVal); err == nil {
+ return floatVal
+ }
+ }
+
+ // Try decimal int - use int64 to handle large values on 32-bit systems
+ var int64Val int64
+ if _, err := fmt.Sscanf(value, "%d", &int64Val); err == nil {
+ // Return as int if it fits, otherwise int64
+ if int64Val == int64(int(int64Val)) {
+ return int(int64Val)
+ }
+ return int64Val
+ }
+
+ // Default to string
+ return value
+}
+
+// LoadYAML parses YAML data using the native libyaml Parser.
+// This function is exported so it can be used by other packages for data-driven testing.
+// It returns a generic interface{} which is typically:
+// - map[string]interface{} for YAML mappings
+// - []interface{} for YAML sequences
+// - scalar values, resolved according to the following rules:
+// - Booleans: "true" and "false" are returned as bool (true/false).
+// - Nulls: "null" is returned as nil.
+// - Floats: values containing "." are parsed as float64.
+// - Decimal integers: values matching integer format are parsed as int.
+// - All other values are returned as string.
+//
+// This scalar resolution behavior matches the implementation in coerceScalar.
+func LoadYAML(data []byte) (any, error) {
+ parser := NewParser()
+ parser.SetInputString(data)
+ defer parser.Delete()
+
+ type stackEntry struct {
+ container any // map[string]interface{} or []interface{}
+ key string // for maps: current key waiting for value
+ }
+
+ var stack []stackEntry
+ var root any
+
+ for {
+ var event Event
+ if err := parser.Parse(&event); err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ return nil, err
+ }
+
+ switch event.Type {
+ case STREAM_END_EVENT:
+ // End of stream, we're done
+ return root, nil
+
+ case STREAM_START_EVENT, DOCUMENT_START_EVENT:
+ // Structural markers, no action needed
+
+ case MAPPING_START_EVENT:
+ newMap := make(map[string]any)
+ stack = append(stack, stackEntry{container: newMap})
+
+ case MAPPING_END_EVENT:
+ if len(stack) > 0 {
+ popped := stack[len(stack)-1]
+ stack = stack[:len(stack)-1]
+
+ // Add completed map to parent or set as root
+ if len(stack) == 0 {
+ root = popped.container
+ } else {
+ parent := &stack[len(stack)-1]
+ if m, ok := parent.container.(map[string]any); ok {
+ m[parent.key] = popped.container
+ parent.key = "" // Reset key after use
+ } else if s, ok := parent.container.([]any); ok {
+ parent.container = append(s, popped.container)
+ }
+ }
+ }
+
+ case SEQUENCE_START_EVENT:
+ newSlice := make([]any, 0)
+ stack = append(stack, stackEntry{container: newSlice})
+
+ case SEQUENCE_END_EVENT:
+ if len(stack) > 0 {
+ popped := stack[len(stack)-1]
+ stack = stack[:len(stack)-1]
+
+ // Add completed slice to parent or set as root
+ if len(stack) == 0 {
+ root = popped.container
+ } else {
+ parent := &stack[len(stack)-1]
+ if m, ok := parent.container.(map[string]any); ok {
+ m[parent.key] = popped.container
+ parent.key = "" // Reset key after use
+ } else if s, ok := parent.container.([]any); ok {
+ parent.container = append(s, popped.container)
+ }
+ }
+ }
+
+ case SCALAR_EVENT:
+ value := string(event.Value)
+ // Only coerce plain (unquoted) scalars
+ isQuoted := ScalarStyle(event.Style) != PLAIN_SCALAR_STYLE
+
+ if len(stack) == 0 {
+ // Scalar at root level
+ if isQuoted {
+ root = value
+ } else {
+ root = coerceScalar(value)
+ }
+ } else {
+ parent := &stack[len(stack)-1]
+ if m, ok := parent.container.(map[string]any); ok {
+ if parent.key == "" {
+ // This scalar is a key - keep as string, don't coerce
+ parent.key = value
+ } else {
+ // This scalar is a value
+ if isQuoted {
+ m[parent.key] = value
+ } else {
+ m[parent.key] = coerceScalar(value)
+ }
+ parent.key = ""
+ }
+ } else if s, ok := parent.container.([]any); ok {
+ // Add to sequence
+ if isQuoted {
+ parent.container = append(s, value)
+ } else {
+ parent.container = append(s, coerceScalar(value))
+ }
+ }
+ }
+
+ case DOCUMENT_END_EVENT:
+ // Document end marker, continue processing
+
+ case ALIAS_EVENT, TAIL_COMMENT_EVENT:
+ // For now, skip aliases and comments (not used in test data)
+ }
+ }
+
+ return root, nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yamlprivate.go b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yamlprivate.go
new file mode 100644
index 00000000000..d23af7d9fac
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/internal/libyaml/yamlprivate.go
@@ -0,0 +1,249 @@
+// Copyright 2006-2010 Kirill Simonov
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0 AND MIT
+
+// Internal constants and buffer sizes.
+// Defines buffer sizes, stack sizes, and other internal configuration
+// constants for libyaml.
+
+package libyaml
+
+const (
+ // The size of the input raw buffer.
+ input_raw_buffer_size = 512
+
+ // The size of the input buffer.
+ // It should be possible to decode the whole raw buffer.
+ input_buffer_size = input_raw_buffer_size * 3
+
+ // The size of the output buffer.
+ output_buffer_size = 128
+
+ // The size of other stacks and queues.
+ initial_stack_size = 16
+ initial_queue_size = 16
+ initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func isAlpha(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' ||
+ b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a flow indicator as
+// defined by spec production [23] c-flow-indicator ::=
+// c-collect-entry | c-sequence-start | c-sequence-end |
+// c-mapping-start | c-mapping-end
+func isFlowIndicator(b []byte, i int) bool {
+ return b[i] == '[' || b[i] == ']' ||
+ b[i] == '{' || b[i] == '}' || b[i] == ','
+}
+
+// Check if the character at the specified position is valid for anchor names
+// as defined by spec production [102] ns-anchor-char ::= ns-char -
+// c-flow-indicator.
+// This includes all printable characters except: CR, LF, BOM, space, tab, '[',
+// ']', '{', '}', ','.
+// We further limit it to ascii chars only, which is a subset of the spec
+// production but is usually what most people expect.
+func isAnchorChar(b []byte, i int) bool {
+ if isColon(b, i) {
+ // [Go] we exclude colons from anchor/alias names.
+ //
+ // A colon is a valid anchor character according to the YAML 1.2 specification,
+ // but it can lead to ambiguity.
+ // https://github.com/yaml/go-yaml/issues/109
+ //
+ // Also, it would have been a breaking change to support it, as go.yaml.in/yaml/v3 ignores it.
+ // Supporting it could lead to unexpected behavior.
+ return false
+ }
+
+ return isPrintable(b, i) &&
+ !isLineBreak(b, i) &&
+ !isBlank(b, i) &&
+ !isBOM(b, i) &&
+ !isFlowIndicator(b, i) &&
+ isASCII(b, i)
+}
+
+// isColon checks whether the character at the specified position is a colon.
+func isColon(b []byte, i int) bool {
+ return b[i] == ':'
+}
+
+// Check if the character at the specified position is valid in a tag URI.
+//
+// The set of valid characters is:
+//
+// '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+// '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%'.
+//
+// If verbatim is true, flow indicators (',', '[', ']', '{', '}') are also
+// allowed.
+func isTagURIChar(b []byte, i int, verbatim bool) bool {
+ c := b[i]
+ // isAlpha covers: 0-9, A-Z, a-z, _, -
+ if isAlpha(b, i) {
+ return true
+ }
+ // Check special URI characters
+ switch c {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%':
+ return true
+ case ',', '[', ']', '{', '}':
+ return verbatim
+ }
+ return false
+}
+
+// Check if the character at the specified position is a digit.
+func isDigit(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func asDigit(b []byte, i int) int {
+ return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func isHex(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' ||
+ b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func asHex(b []byte, i int) int {
+ bi := b[i]
+ if bi >= 'A' && bi <= 'F' {
+ return int(bi) - 'A' + 10
+ }
+ if bi >= 'a' && bi <= 'f' {
+ return int(bi) - 'a' + 10
+ }
+ return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func isASCII(b []byte, i int) bool {
+ return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func isPrintable(b []byte, i int) bool {
+ return ((b[i] == 0x0A) || // . == #x0A
+ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+ (b[i] > 0xC2 && b[i] < 0xED) ||
+ (b[i] == 0xED && b[i+1] < 0xA0) ||
+ (b[i] == 0xEE) ||
+ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func isZeroChar(b []byte, i int) bool {
+ return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func isBOM(b []byte, i int) bool {
+ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func isSpace(b []byte, i int) bool {
+ return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func isTab(b []byte, i int) bool {
+ return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func isBlank(b []byte, i int) bool {
+ // return isSpace(b, i) || isTab(b, i)
+ return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func isLineBreak(b []byte, i int) bool {
+ return (b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func isCRLF(b []byte, i int) bool {
+ return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func isBreakOrZero(b []byte, i int) bool {
+ // return isLineBreak(b, i) || isZeroChar(b, i)
+ return (
+ // isBreak:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ // isZeroChar:
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func isSpaceOrZero(b []byte, i int) bool {
+ // return isSpace(b, i) || isBreakOrZero(b, i)
+ return (
+ // isSpace:
+ b[i] == ' ' ||
+ // isBreakOrZero:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func isBlankOrZero(b []byte, i int) bool {
+ // return isBlank(b, i) || isBreakOrZero(b, i)
+ return (
+ // isBlank:
+ b[i] == ' ' || b[i] == '\t' ||
+ // isBreakOrZero:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+ // Don't replace these by a switch without first
+ // confirming that it is being inlined.
+ if b&0x80 == 0x00 {
+ return 1
+ }
+ if b&0xE0 == 0xC0 {
+ return 2
+ }
+ if b&0xF0 == 0xE0 {
+ return 3
+ }
+ if b&0xF8 == 0xF0 {
+ return 4
+ }
+ return 0
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/loader.go b/hack/tools/vendor/go.yaml.in/yaml/v4/loader.go
new file mode 100644
index 00000000000..aa9757fff1d
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/loader.go
@@ -0,0 +1,231 @@
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// This file contains the Loader API for reading YAML documents.
+//
+// Primary functions:
+// - Load: Decode YAML document(s) into a value (use WithAll for multi-doc)
+// - NewLoader: Create a streaming loader from io.Reader
+
+package yaml
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "reflect"
+
+ "go.yaml.in/yaml/v4/internal/libyaml"
+)
+
+// Load decodes YAML document(s) with the given options.
+//
+// By default, Load requires exactly one document in the input.
+// If zero documents are found, it returns an error.
+// If multiple documents are found, it returns an error.
+//
+// Use WithAllDocuments() to load all documents into a slice:
+//
+// var configs []Config
+// yaml.Load(multiDocYAML, &configs, yaml.WithAllDocuments())
+//
+// When WithAllDocuments is used, out must be a pointer to a slice.
+// Each document is decoded into the slice element type.
+// Zero documents results in an empty slice (no error).
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary. The out parameter
+// must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.LoadErrors is returned with details for all
+// missed values.
+//
+// Struct fields are only loaded if they are exported (have an upper case
+// first letter), and are loaded using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options control the loading and dumping behavior.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// var t T
+// yaml.Load([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Dump for the format of tags and a list of
+// supported tag options.
+func Load(in []byte, out any, opts ...Option) error {
+ o, err := libyaml.ApplyOptions(opts...)
+ if err != nil {
+ return err
+ }
+
+ if o.AllDocuments {
+ // Multi-document mode: out must be pointer to slice
+ return loadAll(in, out, o)
+ }
+
+ // Single-document mode: exactly one document required
+ return loadSingle(in, out, o)
+}
+
+// loadAll loads all documents into a slice
+func loadAll(in []byte, out any, opts *libyaml.Options) error {
+ outVal := reflect.ValueOf(out)
+ if outVal.Kind() != reflect.Pointer || outVal.IsNil() {
+ return &LoadErrors{Errors: []*libyaml.ConstructError{{
+ Err: errors.New("yaml: WithAllDocuments requires a non-nil pointer to a slice"),
+ }}}
+ }
+
+ sliceVal := outVal.Elem()
+ if sliceVal.Kind() != reflect.Slice {
+ return &LoadErrors{Errors: []*libyaml.ConstructError{{
+ Err: errors.New("yaml: WithAllDocuments requires a pointer to a slice"),
+ }}}
+ }
+
+ // Create a new slice (clear existing content)
+ sliceVal.Set(reflect.MakeSlice(sliceVal.Type(), 0, 0))
+
+ l, err := NewLoader(bytes.NewReader(in), func(o *libyaml.Options) error {
+ *o = *opts // Copy options
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ elemType := sliceVal.Type().Elem()
+ for {
+ // Create new element of slice's element type
+ elemPtr := reflect.New(elemType)
+ err := l.Load(elemPtr.Interface())
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ // Append decoded element to slice
+ sliceVal.Set(reflect.Append(sliceVal, elemPtr.Elem()))
+ }
+
+ return nil
+}
+
+// loadSingle loads exactly one document (strict)
+func loadSingle(in []byte, out any, opts *libyaml.Options) error {
+ l, err := NewLoader(bytes.NewReader(in), func(o *libyaml.Options) error {
+ *o = *opts // Copy options
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ // Load first document
+ err = l.Load(out)
+ if err == io.EOF {
+ return &LoadErrors{Errors: []*libyaml.ConstructError{{
+ Err: errors.New("yaml: no documents in stream"),
+ }}}
+ }
+ if err != nil {
+ return err
+ }
+
+ // Check for additional documents
+ var dummy any
+ err = l.Load(&dummy)
+ if err != io.EOF {
+ if err != nil {
+ // Some other error occurred
+ return err
+ }
+ // Successfully loaded a second document - this is an error in strict mode
+ return &LoadErrors{Errors: []*libyaml.ConstructError{{
+ Err: errors.New("yaml: expected single document, found multiple"),
+ }}}
+ }
+
+ return nil
+}
+
+// A Loader reads and decodes YAML values from an input stream with configurable
+// options.
+type Loader struct {
+ composer *libyaml.Composer
+ decoder *libyaml.Constructor
+ opts *libyaml.Options
+ docCount int
+}
+
+// NewLoader returns a new Loader that reads from r with the given options.
+//
+// The Loader introduces its own buffering and may read data from r beyond the
+// YAML values requested.
+func NewLoader(r io.Reader, opts ...Option) (*Loader, error) {
+ o, err := libyaml.ApplyOptions(opts...)
+ if err != nil {
+ return nil, err
+ }
+ c := libyaml.NewComposerFromReader(r)
+ c.SetStreamNodes(o.StreamNodes)
+ return &Loader{
+ composer: c,
+ decoder: libyaml.NewConstructor(o),
+ opts: o,
+ }, nil
+}
+
+// Load reads the next YAML-encoded document from its input and stores it
+// in the value pointed to by v.
+//
+// Returns io.EOF when there are no more documents to read.
+// If WithSingleDocument option was set and a document was already read,
+// subsequent calls return io.EOF.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as v
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary. The v parameter
+// must not be nil.
+//
+// Struct fields are only loaded if they are exported (have an upper case
+// first letter), and are loaded using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options control the loading and dumping behavior.
+//
+// See the documentation of the package-level Load function for more details
+// about YAML to Go conversion and tag options.
+func (l *Loader) Load(v any) (err error) {
+ defer handleErr(&err)
+ if l.opts.SingleDocument && l.docCount > 0 {
+ return io.EOF
+ }
+ node := l.composer.Parse() // *libyaml.Node
+ if node == nil {
+ return io.EOF
+ }
+ l.docCount++
+
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Pointer && !out.IsNil() {
+ out = out.Elem()
+ }
+ l.decoder.Construct(node, out) // Pass libyaml.Node directly
+ if len(l.decoder.TypeErrors) > 0 {
+ typeErrors := l.decoder.TypeErrors
+ l.decoder.TypeErrors = nil
+ return &LoadErrors{Errors: typeErrors}
+ }
+ return nil
+}
diff --git a/hack/tools/vendor/go.yaml.in/yaml/v4/yaml.go b/hack/tools/vendor/go.yaml.in/yaml/v4/yaml.go
new file mode 100644
index 00000000000..684d660d294
--- /dev/null
+++ b/hack/tools/vendor/go.yaml.in/yaml/v4/yaml.go
@@ -0,0 +1,732 @@
+// Copyright 2011-2019 Canonical Ltd
+// Copyright 2025 The go-yaml Project Contributors
+// SPDX-License-Identifier: Apache-2.0
+
+// Package yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+// https://github.com/yaml/go-yaml
+//
+// This file contains:
+// - Version presets (V2, V3, V4)
+// - Options API (WithIndent, WithKnownFields, etc.)
+// - Type and constant re-exports from internal/libyaml
+// - Helper functions for struct field handling
+// - Classic APIs (Decoder, Encoder, Unmarshal, Marshal)
+//
+// For the main API, see:
+// - loader.go: Load, Loader
+// - dumper.go: Dump, Dumper
+
+package yaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "sync"
+
+ "go.yaml.in/yaml/v4/internal/libyaml"
+)
+
+//-----------------------------------------------------------------------------
+// Version presets
+//-----------------------------------------------------------------------------
+
+// Usage:
+// yaml.Dump(&data, yaml.V3)
+// yaml.Dump(&data, yaml.V3, yaml.WithIndent(2), yaml.WithCompactSeqIndent())
+
+// V2 defaults:
+var V2 = Options(
+ WithIndent(2),
+ WithCompactSeqIndent(false),
+ WithLineWidth(80),
+ WithUnicode(true),
+ WithUniqueKeys(true),
+ WithQuotePreference(QuoteLegacy),
+)
+
+// V3 defaults:
+var V3 = Options(
+ WithIndent(4),
+ WithCompactSeqIndent(false),
+ WithLineWidth(80),
+ WithUnicode(true),
+ WithUniqueKeys(true),
+ WithQuotePreference(QuoteLegacy),
+)
+
+// V4 defaults:
+var V4 = Options(
+ WithIndent(2),
+ WithCompactSeqIndent(true),
+ WithLineWidth(80),
+ WithUnicode(true),
+ WithUniqueKeys(true),
+ WithQuotePreference(QuoteSingle),
+)
+
+//-----------------------------------------------------------------------------
+// Options
+//-----------------------------------------------------------------------------
+
+// Option allows configuring YAML loading and dumping operations.
+// Re-exported from internal/libyaml.
+type Option = libyaml.Option
+
+var (
+ // WithIndent sets indentation spaces (2-9).
+ // See internal/libyaml.WithIndent.
+ WithIndent = libyaml.WithIndent
+ // WithCompactSeqIndent configures '- ' as part of indentation.
+ // See internal/libyaml.WithCompactSeqIndent.
+ WithCompactSeqIndent = libyaml.WithCompactSeqIndent
+ // WithKnownFields enables strict field checking during loading.
+ // See internal/libyaml.WithKnownFields.
+ WithKnownFields = libyaml.WithKnownFields
+ // WithSingleDocument only processes first document in stream.
+ // See internal/libyaml.WithSingleDocument.
+ WithSingleDocument = libyaml.WithSingleDocument
+ // WithStreamNodes enables stream boundary nodes when loading.
+ // See internal/libyaml.WithStreamNodes.
+ WithStreamNodes = libyaml.WithStreamNodes
+ // WithAllDocuments enables multi-document mode for Load and Dump.
+ // See internal/libyaml.WithAllDocuments.
+ WithAllDocuments = libyaml.WithAllDocuments
+ // WithLineWidth sets preferred line width for output.
+ // See internal/libyaml.WithLineWidth.
+ WithLineWidth = libyaml.WithLineWidth
+ // WithUnicode controls non-ASCII characters in output.
+ // See internal/libyaml.WithUnicode.
+ WithUnicode = libyaml.WithUnicode
+ // WithUniqueKeys enables duplicate key detection.
+ // See internal/libyaml.WithUniqueKeys.
+ WithUniqueKeys = libyaml.WithUniqueKeys
+ // WithCanonical forces canonical YAML output format.
+ // See internal/libyaml.WithCanonical.
+ WithCanonical = libyaml.WithCanonical
+ // WithLineBreak sets line ending style for output.
+ // See internal/libyaml.WithLineBreak.
+ WithLineBreak = libyaml.WithLineBreak
+ // WithExplicitStart controls document start markers (---).
+ // See internal/libyaml.WithExplicitStart.
+ WithExplicitStart = libyaml.WithExplicitStart
+ // WithExplicitEnd controls document end markers (...).
+ // See internal/libyaml.WithExplicitEnd.
+ WithExplicitEnd = libyaml.WithExplicitEnd
+ // WithFlowSimpleCollections controls flow style for simple collections.
+ // See internal/libyaml.WithFlowSimpleCollections.
+ WithFlowSimpleCollections = libyaml.WithFlowSimpleCollections
+ // WithQuotePreference sets preferred quote style when quoting is required.
+ // See internal/libyaml.WithQuotePreference.
+ WithQuotePreference = libyaml.WithQuotePreference
+)
+
+// Options combines multiple options into a single Option.
+// This is useful for creating option presets or combining version defaults
+// with custom options.
+//
+// Example:
+//
+// opts := yaml.Options(yaml.V4, yaml.WithIndent(3))
+// yaml.Dump(&data, opts)
+func Options(opts ...Option) Option {
+ return libyaml.CombineOptions(opts...)
+}
+
+// OptsYAML parses a YAML string containing option settings and returns
+// an Option that can be combined with other options using Options().
+//
+// The YAML string can specify any of these fields:
+// - indent (int)
+// - compact-seq-indent (bool)
+// - line-width (int)
+// - unicode (bool)
+// - canonical (bool)
+// - line-break (string: ln, cr, crln)
+// - explicit-start (bool)
+// - explicit-end (bool)
+// - flow-simple-coll (bool)
+// - known-fields (bool)
+// - single-document (bool)
+// - unique-keys (bool)
+//
+// Only fields specified in the YAML will override other options when
+// combined. Unspecified fields won't affect other options.
+//
+// Example:
+//
+// opts, err := yaml.OptsYAML(`
+// indent: 3
+// known-fields: true
+// `)
+// yaml.Dump(&data, yaml.Options(V4, opts))
+func OptsYAML(yamlStr string) (Option, error) {
+ var cfg struct {
+ Indent *int `yaml:"indent"`
+ CompactSeqIndent *bool `yaml:"compact-seq-indent"`
+ LineWidth *int `yaml:"line-width"`
+ Unicode *bool `yaml:"unicode"`
+ Canonical *bool `yaml:"canonical"`
+ LineBreak *string `yaml:"line-break"`
+ ExplicitStart *bool `yaml:"explicit-start"`
+ ExplicitEnd *bool `yaml:"explicit-end"`
+ FlowSimpleCollections *bool `yaml:"flow-simple-coll"`
+ KnownFields *bool `yaml:"known-fields"`
+ SingleDocument *bool `yaml:"single-document"`
+ UniqueKeys *bool `yaml:"unique-keys"`
+ }
+ if err := Load([]byte(yamlStr), &cfg, WithKnownFields()); err != nil {
+ return nil, err
+ }
+
+ // Build options only for fields that were set
+ var optList []Option
+ if cfg.Indent != nil {
+ optList = append(optList, WithIndent(*cfg.Indent))
+ }
+ if cfg.CompactSeqIndent != nil {
+ optList = append(optList, WithCompactSeqIndent(*cfg.CompactSeqIndent))
+ }
+ if cfg.LineWidth != nil {
+ optList = append(optList, WithLineWidth(*cfg.LineWidth))
+ }
+ if cfg.Unicode != nil {
+ optList = append(optList, WithUnicode(*cfg.Unicode))
+ }
+ if cfg.ExplicitStart != nil {
+ optList = append(optList, WithExplicitStart(*cfg.ExplicitStart))
+ }
+ if cfg.ExplicitEnd != nil {
+ optList = append(optList, WithExplicitEnd(*cfg.ExplicitEnd))
+ }
+ if cfg.FlowSimpleCollections != nil {
+ optList = append(optList, WithFlowSimpleCollections(*cfg.FlowSimpleCollections))
+ }
+ if cfg.KnownFields != nil {
+ optList = append(optList, WithKnownFields(*cfg.KnownFields))
+ }
+ if cfg.SingleDocument != nil && *cfg.SingleDocument {
+ optList = append(optList, WithSingleDocument())
+ }
+ if cfg.UniqueKeys != nil {
+ optList = append(optList, WithUniqueKeys(*cfg.UniqueKeys))
+ }
+ if cfg.Canonical != nil {
+ optList = append(optList, WithCanonical(*cfg.Canonical))
+ }
+ if cfg.LineBreak != nil {
+ switch *cfg.LineBreak {
+ case "ln":
+ optList = append(optList, WithLineBreak(LineBreakLN))
+ case "cr":
+ optList = append(optList, WithLineBreak(LineBreakCR))
+ case "crln":
+ optList = append(optList, WithLineBreak(LineBreakCRLN))
+ default:
+ return nil, errors.New("yaml: invalid line-break value (use ln, cr, or crln)")
+ }
+ }
+
+ return Options(optList...), nil
+}
+
+//-----------------------------------------------------------------------------
+// Type and constant re-exports
+//-----------------------------------------------------------------------------
+
+type (
+ // Node represents a YAML node in the document tree.
+ // See internal/libyaml.Node.
+ Node = libyaml.Node
+ // Kind identifies the type of a YAML node.
+ // See internal/libyaml.Kind.
+ Kind = libyaml.Kind
+ // Style controls the presentation of a YAML node.
+ // See internal/libyaml.Style.
+ Style = libyaml.Style
+ // Marshaler is implemented by types with custom YAML marshaling.
+ // See internal/libyaml.Marshaler.
+ Marshaler = libyaml.Marshaler
+ // IsZeroer is implemented by types that can report if they're zero.
+ // See internal/libyaml.IsZeroer.
+ IsZeroer = libyaml.IsZeroer
+)
+
+// Unmarshaler is the interface implemented by types
+// that can unmarshal a YAML description of themselves.
+type Unmarshaler interface {
+ UnmarshalYAML(node *Node) error
+}
+
+// Re-export stream-related types
+type (
+ VersionDirective = libyaml.StreamVersionDirective
+ TagDirective = libyaml.StreamTagDirective
+ Encoding = libyaml.Encoding
+)
+
+// Re-export encoding constants
+const (
+ EncodingAny = libyaml.ANY_ENCODING
+ EncodingUTF8 = libyaml.UTF8_ENCODING
+ EncodingUTF16LE = libyaml.UTF16LE_ENCODING
+ EncodingUTF16BE = libyaml.UTF16BE_ENCODING
+)
+
+// Re-export error types
+type (
+
+ // LoadError represents an error encountered while decoding a YAML document.
+ //
+ // It contains details about the location in the document where the error
+ // occurred, as well as a descriptive message.
+ LoadError = libyaml.ConstructError
+
+ // LoadErrors is returned when one or more fields cannot be properly decoded.
+ //
+ // It contains multiple *[LoadError] instances with details about each error.
+ LoadErrors = libyaml.LoadErrors
+
+ // TypeError is an obsolete error type retained for compatibility.
+ //
+ // Deprecated: Use [LoadErrors] instead.
+ //
+ //nolint:staticcheck // we are using deprecated TypeError for compatibility
+ TypeError = libyaml.TypeError
+)
+
+// Re-export Kind constants
+const (
+ DocumentNode = libyaml.DocumentNode
+ SequenceNode = libyaml.SequenceNode
+ MappingNode = libyaml.MappingNode
+ ScalarNode = libyaml.ScalarNode
+ AliasNode = libyaml.AliasNode
+ StreamNode = libyaml.StreamNode
+)
+
+// Re-export Style constants
+const (
+ TaggedStyle = libyaml.TaggedStyle
+ DoubleQuotedStyle = libyaml.DoubleQuotedStyle
+ SingleQuotedStyle = libyaml.SingleQuotedStyle
+ LiteralStyle = libyaml.LiteralStyle
+ FoldedStyle = libyaml.FoldedStyle
+ FlowStyle = libyaml.FlowStyle
+)
+
+// LineBreak represents the line ending style for YAML output.
+type LineBreak = libyaml.LineBreak
+
+// Line break constants for different platforms.
+const (
+ LineBreakLN = libyaml.LN_BREAK // Unix-style \n (default)
+ LineBreakCR = libyaml.CR_BREAK // Old Mac-style \r
+ LineBreakCRLN = libyaml.CRLN_BREAK // Windows-style \r\n
+)
+
+// QuoteStyle represents the quote style to use when quoting is required.
+type QuoteStyle = libyaml.QuoteStyle
+
+// Quote style constants for required quoting.
+const (
+ QuoteSingle = libyaml.QuoteSingle // Prefer single quotes (v4 default)
+ QuoteDouble = libyaml.QuoteDouble // Prefer double quotes
+ QuoteLegacy = libyaml.QuoteLegacy // Legacy v2/v3 behavior
+)
+
+//-----------------------------------------------------------------------------
+// Helper functions
+//-----------------------------------------------------------------------------
+
+// The code in this section was copied from mgo/bson.
+
+var (
+ structMap = make(map[reflect.Type]*structInfo)
+ fieldMapMutex sync.RWMutex
+ unmarshalerType reflect.Type
+)
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+ FieldsMap map[string]fieldInfo
+ FieldsList []fieldInfo
+
+ // InlineMap is the number of the field in the struct that
+ // contains an ,inline map, or -1 if there's none.
+ InlineMap int
+
+ // InlineUnmarshalers holds indexes to inlined fields that
+ // contain unmarshaler values.
+ InlineUnmarshalers [][]int
+}
+
+type fieldInfo struct {
+ Key string
+ Num int
+ OmitEmpty bool
+ Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
+
+ // Inline holds the field index if the field is part of an inlined struct.
+ Inline []int
+}
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+ fieldMapMutex.RLock()
+ sinfo, found := structMap[st]
+ fieldMapMutex.RUnlock()
+ if found {
+ return sinfo, nil
+ }
+
+ n := st.NumField()
+ fieldsMap := make(map[string]fieldInfo)
+ fieldsList := make([]fieldInfo, 0, n)
+ inlineMap := -1
+ inlineUnmarshalers := [][]int(nil)
+ for i := 0; i != n; i++ {
+ field := st.Field(i)
+ if field.PkgPath != "" && !field.Anonymous {
+ continue // Private field
+ }
+
+ info := fieldInfo{Num: i}
+
+ tag := field.Tag.Get("yaml")
+ if tag == "" && !strings.Contains(string(field.Tag), ":") {
+ tag = string(field.Tag)
+ }
+ if tag == "-" {
+ continue
+ }
+
+ inline := false
+ fields := strings.Split(tag, ",")
+ if len(fields) > 1 {
+ for _, flag := range fields[1:] {
+ switch flag {
+ case "omitempty":
+ info.OmitEmpty = true
+ case "flow":
+ info.Flow = true
+ case "inline":
+ inline = true
+ default:
+ return nil, fmt.Errorf("unsupported flag %q in tag %q of type %s", flag, tag, st)
+ }
+ }
+ tag = fields[0]
+ }
+
+ if inline {
+ switch field.Type.Kind() {
+ case reflect.Map:
+ if inlineMap >= 0 {
+ return nil, errors.New("multiple ,inline maps in struct " + st.String())
+ }
+ if field.Type.Key() != reflect.TypeOf("") {
+ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
+ }
+ inlineMap = info.Num
+ case reflect.Struct, reflect.Pointer:
+ ftype := field.Type
+ for ftype.Kind() == reflect.Pointer {
+ ftype = ftype.Elem()
+ }
+ if ftype.Kind() != reflect.Struct {
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ if reflect.PointerTo(ftype).Implements(unmarshalerType) {
+ inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
+ } else {
+ sinfo, err := getStructInfo(ftype)
+ if err != nil {
+ return nil, err
+ }
+ for _, index := range sinfo.InlineUnmarshalers {
+ inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
+ }
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
+ }
+ }
+ default:
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ continue
+ }
+
+ if tag != "" {
+ info.Key = tag
+ } else {
+ info.Key = strings.ToLower(field.Name)
+ }
+
+ if _, found = fieldsMap[info.Key]; found {
+ msg := "duplicated key '" + info.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+
+ info.Id = len(fieldsList)
+ fieldsList = append(fieldsList, info)
+ fieldsMap[info.Key] = info
+ }
+
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ InlineUnmarshalers: inlineUnmarshalers,
+ }
+
+ fieldMapMutex.Lock()
+ structMap[st] = sinfo
+ fieldMapMutex.Unlock()
+ return sinfo, nil
+}
+
+var noWriter io.Writer
+
+func handleErr(err *error) {
+ if v := recover(); v != nil {
+ if e, ok := v.(*libyaml.YAMLError); ok {
+ *err = e.Err
+ } else {
+ panic(v)
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Classic APIs
+//-----------------------------------------------------------------------------
+
+// A Decoder reads and decodes YAML values from an input stream.
+type Decoder struct {
+ composer *libyaml.Composer
+ knownFields bool
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ composer: libyaml.NewComposerFromReader(r),
+ }
+}
+
+// KnownFields ensures that the keys in decoded mappings to
+// exist as fields in the struct being decoded into.
+func (dec *Decoder) KnownFields(enable bool) {
+ dec.knownFields = enable
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v any) (err error) {
+ d := libyaml.NewConstructor(libyaml.DefaultOptions)
+ d.KnownFields = dec.knownFields
+ defer handleErr(&err)
+ node := dec.composer.Parse()
+ if node == nil {
+ return io.EOF
+ }
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Pointer && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.Construct(node, out)
+ if len(d.TypeErrors) > 0 {
+ return &LoadErrors{Errors: d.TypeErrors}
+ }
+ return nil
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+ encoder *libyaml.Representer
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ encoder: libyaml.NewRepresenter(w, libyaml.DefaultOptions),
+ }
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v any) (err error) {
+ defer handleErr(&err)
+ e.encoder.MarshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// SetIndent changes the used indentation used when encoding.
+func (e *Encoder) SetIndent(spaces int) {
+ if spaces < 0 {
+ panic("yaml: cannot indent to a negative number of spaces")
+ }
+ e.encoder.Indent = spaces
+}
+
+// CompactSeqIndent makes it so that '- ' is considered part of the indentation.
+func (e *Encoder) CompactSeqIndent() {
+ e.encoder.Emitter.CompactSequenceIndent = true
+}
+
+// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation.
+func (e *Encoder) DefaultSeqIndent() {
+ e.encoder.Emitter.CompactSequenceIndent = false
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+ defer handleErr(&err)
+ e.encoder.Finish()
+ return nil
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.LoadErrors is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshaling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// var t T
+// yaml.Construct([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+func Unmarshal(in []byte, out any) (err error) {
+ return unmarshal(in, out, V3)
+}
+
+func unmarshal(in []byte, out any, opts ...Option) (err error) {
+ defer handleErr(&err)
+ o, err := libyaml.ApplyOptions(opts...)
+ if err != nil {
+ return err
+ }
+
+ // Check if out implements yaml.Unmarshaler
+ if u, ok := out.(Unmarshaler); ok {
+ p := libyaml.NewComposer(in)
+ defer p.Destroy()
+ node := p.Parse()
+ if node != nil {
+ return u.UnmarshalYAML(node)
+ }
+ return nil
+ }
+
+ return libyaml.Construct(in, out, o)
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshaled if they are exported (have an upper case
+// first letter), and are marshaled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshaling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+// `(...) yaml:"[][,[,]]" (...)`
+//
+// The following flags are currently supported:
+//
+// omitempty Only include the field if it's not set to the zero
+// value for the type or to empty slices or maps.
+// Zero valued structs will be omitted if all their public
+// fields are zero, unless they implement an IsZero
+// method (see the IsZeroer interface type), in which
+// case the field will be excluded if IsZero returns true.
+//
+// flow Marshal using a flow style (useful for structs,
+// sequences and maps).
+//
+// inline Inline the field, which must be a struct or a map,
+// causing all of its fields or keys to be processed as if
+// they were part of the outer struct. For maps, keys must
+// not conflict with the yaml keys of other struct fields.
+// See doc/inline-tags.md for detailed examples and use cases.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+func Marshal(in any) (out []byte, err error) {
+ defer handleErr(&err)
+ e := libyaml.NewRepresenter(noWriter, libyaml.DefaultOptions)
+ defer e.Destroy()
+ e.MarshalDoc("", reflect.ValueOf(in))
+ e.Finish()
+ out = e.Out
+ return out, err
+}
diff --git a/hack/tools/vendor/golang.org/x/tools/cmd/stringer/stringer.go b/hack/tools/vendor/golang.org/x/tools/cmd/stringer/stringer.go
new file mode 100644
index 00000000000..7ff0ee8d0c8
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/cmd/stringer/stringer.go
@@ -0,0 +1,715 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
+// interface. Given the name of a (signed or unsigned) integer type T that has constants
+// defined, stringer will create a new self-contained Go source file implementing
+//
+// func (t T) String() string
+//
+// The file is created in the same package and directory as the package that defines T.
+// It has helpful defaults designed for use with go generate.
+//
+// Stringer works best with constants that are consecutive values such as created using iota,
+// but creates good code regardless. In the future it might also provide custom support for
+// constant sets that are bit patterns.
+//
+// For example, given this snippet,
+//
+// package painkiller
+//
+// type Pill int
+//
+// const (
+// Placebo Pill = iota
+// Aspirin
+// Ibuprofen
+// Paracetamol
+// Acetaminophen = Paracetamol
+// )
+//
+// running this command
+//
+// stringer -type=Pill
+//
+// in the same directory will create the file pill_string.go, in package painkiller,
+// containing a definition of
+//
+// func (Pill) String() string
+//
+// That method will translate the value of a Pill constant to the string representation
+// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will
+// print the string "Aspirin".
+//
+// Typically this process would be run using go generate, like this:
+//
+// //go:generate stringer -type=Pill
+//
+// If multiple constants have the same value, the lexically first matching name will
+// be used (in the example, Acetaminophen will print as "Paracetamol").
+//
+// With no arguments, it processes the package in the current directory.
+// Otherwise, the arguments must name a single directory holding a Go package
+// or a set of Go source files that represent a single Go package.
+//
+// The -type flag accepts a comma-separated list of types so a single run can
+// generate methods for multiple types. The default output file is t_string.go,
+// where t is the lower-cased name of the first type listed. It can be overridden
+// with the -output flag.
+//
+// Types can also be declared in tests, in which case type declarations in the
+// non-test package or its test variant are preferred over types defined in the
+// package with suffix "_test".
+// The default output file for type declarations in tests is t_string_test.go with t picked as above.
+//
+// The -linecomment flag tells stringer to generate the text of any line comment, trimmed
+// of leading spaces, instead of the constant name. For instance, if the constants above had a
+// Pill prefix, one could write
+//
+// PillAspirin // Aspirin
+//
+// to suppress it in the output.
+//
+// The -trimprefix flag specifies a prefix to remove from the constant names
+// when generating the string representations. For instance, -trimprefix=Pill
+// would be an alternative way to ensure that PillAspirin.String() == "Aspirin".
+package main // import "golang.org/x/tools/cmd/stringer"
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/constant"
+ "go/format"
+ "go/token"
+ "go/types"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "golang.org/x/tools/go/packages"
+)
+
+var (
+ typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
+ output = flag.String("output", "", "output file name; default srcdir/_string.go")
+ trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
+ linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
+ buildTags = flag.String("tags", "", "comma-separated list of build tags to apply")
+)
+
+// Usage is a replacement usage function for the flags package.
+func Usage() {
+ fmt.Fprintf(os.Stderr, "Usage of stringer:\n")
+ fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
+ fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n")
+ fmt.Fprintf(os.Stderr, "For more information, see:\n")
+ fmt.Fprintf(os.Stderr, "\thttps://pkg.go.dev/golang.org/x/tools/cmd/stringer\n")
+ fmt.Fprintf(os.Stderr, "Flags:\n")
+ flag.PrintDefaults()
+}
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("stringer: ")
+ flag.Usage = Usage
+ flag.Parse()
+ if len(*typeNames) == 0 {
+ flag.Usage()
+ os.Exit(2)
+ }
+ types := strings.Split(*typeNames, ",")
+ var tags []string
+ if len(*buildTags) > 0 {
+ tags = strings.Split(*buildTags, ",")
+ }
+
+ // We accept either one directory or a list of files. Which do we have?
+ args := flag.Args()
+ if len(args) == 0 {
+ // Default: process whole package in current directory.
+ args = []string{"."}
+ }
+
+ // Parse the package once.
+ var dir string
+ // TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc).
+ if len(args) == 1 && isDirectory(args[0]) {
+ dir = args[0]
+ } else {
+ if len(tags) != 0 {
+ log.Fatal("-tags option applies only to directories, not when files are specified")
+ }
+ dir = filepath.Dir(args[0])
+ }
+
+ // For each type, generate code in the first package where the type is declared.
+ // The order of packages is as follows:
+ // package x
+ // package x compiled for tests
+ // package x_test
+ //
+ // Each package pass could result in a separate generated file.
+ // These files must have the same package and test/not-test nature as the types
+ // from which they were generated.
+ //
+ // Types will be excluded when generated, to avoid repetitions.
+ pkgs := loadPackages(args, tags, *trimprefix, *linecomment, nil /* logf */)
+ sort.Slice(pkgs, func(i, j int) bool {
+ // Put x_test packages last.
+ iTest := strings.HasSuffix(pkgs[i].name, "_test")
+ jTest := strings.HasSuffix(pkgs[j].name, "_test")
+ if iTest != jTest {
+ return !iTest
+ }
+
+ return len(pkgs[i].files) < len(pkgs[j].files)
+ })
+ for _, pkg := range pkgs {
+ g := Generator{
+ pkg: pkg,
+ }
+
+ // Print the header and package clause.
+ g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
+ g.Printf("\n")
+ g.Printf("package %s", g.pkg.name)
+ g.Printf("\n")
+ g.Printf("import \"strconv\"\n") // Used by all methods.
+
+ // Run generate for types that can be found. Keep the rest for the remainingTypes iteration.
+ var foundTypes, remainingTypes []string
+ for _, typeName := range types {
+ values := findValues(typeName, pkg)
+ if len(values) > 0 {
+ g.generate(typeName, values)
+ foundTypes = append(foundTypes, typeName)
+ } else {
+ remainingTypes = append(remainingTypes, typeName)
+ }
+ }
+ if len(foundTypes) == 0 {
+ // This package didn't have any of the relevant types, skip writing a file.
+ continue
+ }
+ if len(remainingTypes) > 0 && output != nil && *output != "" {
+ log.Fatalf("cannot write to single file (-output=%q) when matching types are found in multiple packages", *output)
+ }
+ types = remainingTypes
+
+ // Format the output.
+ src := g.format()
+
+ // Write to file.
+ outputName := *output
+ if outputName == "" {
+ // Type names will be unique across packages since only the first
+ // match is picked.
+ // So there won't be collisions between a package compiled for tests
+ // and the separate package of tests (package foo_test).
+ outputName = filepath.Join(dir, baseName(pkg, foundTypes[0]))
+ }
+ err := os.WriteFile(outputName, src, 0o644)
+ if err != nil {
+ log.Fatalf("writing output: %s", err)
+ }
+ }
+
+ if len(types) > 0 {
+ log.Fatalf("no values defined for types: %s", strings.Join(types, ","))
+ }
+}
+
+// baseName that will put the generated code together with pkg.
+func baseName(pkg *Package, typename string) string {
+ suffix := "string.go"
+ if pkg.hasTestFiles {
+ suffix = "string_test.go"
+ }
+ return fmt.Sprintf("%s_%s", strings.ToLower(typename), suffix)
+}
+
+// isDirectory reports whether the named file is a directory.
+func isDirectory(name string) bool {
+ info, err := os.Stat(name)
+ if err != nil {
+ log.Fatal(err)
+ }
+ return info.IsDir()
+}
+
+// Generator holds the state of the analysis. Primarily used to buffer
+// the output for format.Source.
+type Generator struct {
+ buf bytes.Buffer // Accumulated output.
+ pkg *Package // Package we are scanning.
+
+ logf func(format string, args ...any) // test logging hook; nil when not testing
+}
+
+func (g *Generator) Printf(format string, args ...any) {
+ fmt.Fprintf(&g.buf, format, args...)
+}
+
+// File holds a single parsed file and associated data.
+type File struct {
+ pkg *Package // Package to which this file belongs.
+ file *ast.File // Parsed AST.
+ // These fields are reset for each type being generated.
+ typeName string // Name of the constant type.
+ values []Value // Accumulator for constant values of that type.
+
+ trimPrefix string
+ lineComment bool
+}
+
+type Package struct {
+ name string
+ defs map[*ast.Ident]types.Object
+ files []*File
+ hasTestFiles bool
+}
+
+// loadPackages analyzes the single package constructed from the patterns and tags.
+// loadPackages exits if there is an error.
+//
+// Returns all variants (such as tests) of the package.
+//
+// logf is a test logging hook. It can be nil when not testing.
+func loadPackages(
+ patterns, tags []string,
+ trimPrefix string, lineComment bool,
+ logf func(format string, args ...any),
+) []*Package {
+ cfg := &packages.Config{
+ Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedFiles,
+ // Tests are included, let the caller decide how to fold them in.
+ Tests: true,
+ BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))},
+ Logf: logf,
+ }
+ pkgs, err := packages.Load(cfg, patterns...)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if len(pkgs) == 0 {
+ log.Fatalf("error: no packages matching %v", strings.Join(patterns, " "))
+ }
+
+ out := make([]*Package, len(pkgs))
+ for i, pkg := range pkgs {
+ p := &Package{
+ name: pkg.Name,
+ defs: pkg.TypesInfo.Defs,
+ files: make([]*File, len(pkg.Syntax)),
+ }
+
+ for j, file := range pkg.Syntax {
+ p.files[j] = &File{
+ file: file,
+ pkg: p,
+
+ trimPrefix: trimPrefix,
+ lineComment: lineComment,
+ }
+ }
+
+ // Keep track of test files, since we might want to generated
+ // code that ends up in that kind of package.
+ // Can be replaced once https://go.dev/issue/38445 lands.
+ for _, f := range pkg.GoFiles {
+ if strings.HasSuffix(f, "_test.go") {
+ p.hasTestFiles = true
+ break
+ }
+ }
+
+ out[i] = p
+ }
+ return out
+}
+
+func findValues(typeName string, pkg *Package) []Value {
+ values := make([]Value, 0, 100)
+ for _, file := range pkg.files {
+ // Set the state for this run of the walker.
+ file.typeName = typeName
+ file.values = nil
+ if file.file != nil {
+ ast.Inspect(file.file, file.genDecl)
+ values = append(values, file.values...)
+ }
+ }
+ return values
+}
+
+// generate produces the String method for the named type.
+func (g *Generator) generate(typeName string, values []Value) {
+ // Generate code that will fail if the constants change value.
+ g.Printf("func _() {\n")
+ g.Printf("\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n")
+ g.Printf("\t// Re-run the stringer command to generate them again.\n")
+ g.Printf("\tvar x [1]struct{}\n")
+ for _, v := range values {
+ g.Printf("\t_ = x[%s - %s]\n", v.originalName, v.str)
+ }
+ g.Printf("}\n")
+ runs := splitIntoRuns(values)
+ // The decision of which pattern to use depends on the number of
+ // runs in the numbers. If there's only one, it's easy. For more than
+ // one, there's a tradeoff between complexity and size of the data
+ // and code vs. the simplicity of a map. A map takes more space,
+ // but so does the code. The decision here (crossover at 10) is
+ // arbitrary, but considers that for large numbers of runs the cost
+ // of the linear scan in the switch might become important, and
+ // rather than use yet another algorithm such as binary search,
+ // we punt and use a map. In any case, the likelihood of a map
+ // being necessary for any realistic example other than bitmasks
+ // is very low. And bitmasks probably deserve their own analysis,
+ // to be done some other day.
+ switch {
+ case len(runs) == 1:
+ g.buildOneRun(runs, typeName)
+ case len(runs) <= 10:
+ g.buildMultipleRuns(runs, typeName)
+ default:
+ g.buildMap(runs, typeName)
+ }
+}
+
+// splitIntoRuns breaks the values into runs of contiguous sequences.
+// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
+// The input slice is known to be non-empty.
+func splitIntoRuns(values []Value) [][]Value {
+ // We use stable sort so the lexically first name is chosen for equal elements.
+ sort.Stable(byValue(values))
+ // Remove duplicates. Stable sort has put the one we want to print first,
+ // so use that one. The String method won't care about which named constant
+ // was the argument, so the first name for the given value is the only one to keep.
+ // We need to do this because identical values would cause the switch or map
+ // to fail to compile.
+ j := 1
+ for i := 1; i < len(values); i++ {
+ if values[i].value != values[i-1].value {
+ values[j] = values[i]
+ j++
+ }
+ }
+ values = values[:j]
+ runs := make([][]Value, 0, 10)
+ for len(values) > 0 {
+ // One contiguous sequence per outer loop.
+ i := 1
+ for i < len(values) && values[i].value == values[i-1].value+1 {
+ i++
+ }
+ runs = append(runs, values[:i])
+ values = values[i:]
+ }
+ return runs
+}
+
+// format returns the gofmt-ed contents of the Generator's buffer.
+func (g *Generator) format() []byte {
+ src, err := format.Source(g.buf.Bytes())
+ if err != nil {
+ // Should never happen, but can arise when developing this code.
+ // The user can compile the output to see the error.
+ log.Printf("warning: internal error: invalid Go generated: %s", err)
+ log.Printf("warning: compile the package to analyze the error")
+ return g.buf.Bytes()
+ }
+ return src
+}
+
+// Value represents a declared constant.
+type Value struct {
+ originalName string // The name of the constant.
+ name string // The name with trimmed prefix.
+ // The value is stored as a bit pattern alone. The boolean tells us
+ // whether to interpret it as an int64 or a uint64; the only place
+ // this matters is when sorting.
+ // Much of the time the str field is all we need; it is printed
+ // by Value.String.
+ value uint64 // Will be converted to int64 when needed.
+ signed bool // Whether the constant is a signed type.
+ str string // The string representation given by the "go/constant" package.
+}
+
+func (v *Value) String() string {
+ return v.str
+}
+
+// byValue lets us sort the constants into increasing order.
+// We take care in the Less method to sort in signed or unsigned order,
+// as appropriate.
+type byValue []Value
+
+func (b byValue) Len() int { return len(b) }
+func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byValue) Less(i, j int) bool {
+ if b[i].signed {
+ return int64(b[i].value) < int64(b[j].value)
+ }
+ return b[i].value < b[j].value
+}
+
+// genDecl processes one declaration clause.
+func (f *File) genDecl(node ast.Node) bool {
+ decl, ok := node.(*ast.GenDecl)
+ if !ok || decl.Tok != token.CONST {
+ // We only care about const declarations.
+ return true
+ }
+ // The name of the type of the constants we are declaring.
+ // Can change if this is a multi-element declaration.
+ typ := ""
+ // Loop over the elements of the declaration. Each element is a ValueSpec:
+ // a list of names possibly followed by a type, possibly followed by values.
+ // If the type and value are both missing, we carry down the type (and value,
+ // but the "go/types" package takes care of that).
+ for _, spec := range decl.Specs {
+ vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
+ if vspec.Type == nil && len(vspec.Values) > 0 {
+ // "X = 1". With no type but a value. If the constant is untyped,
+ // skip this vspec and reset the remembered type.
+ typ = ""
+
+ // If this is a simple type conversion, remember the type.
+ // We don't mind if this is actually a call; a qualified call won't
+ // be matched (that will be SelectorExpr, not Ident), and only unusual
+ // situations will result in a function call that appears to be
+ // a type conversion.
+ ce, ok := vspec.Values[0].(*ast.CallExpr)
+ if !ok {
+ continue
+ }
+ id, ok := ce.Fun.(*ast.Ident)
+ if !ok {
+ continue
+ }
+ typ = id.Name
+ }
+ if vspec.Type != nil {
+ // "X T". We have a type. Remember it.
+ ident, ok := vspec.Type.(*ast.Ident)
+ if !ok {
+ continue
+ }
+ typ = ident.Name
+ }
+ if typ != f.typeName {
+ // This is not the type we're looking for.
+ continue
+ }
+ // We now have a list of names (from one line of source code) all being
+ // declared with the desired type.
+ // Grab their names and actual values and store them in f.values.
+ for _, name := range vspec.Names {
+ if name.Name == "_" {
+ continue
+ }
+ // This dance lets the type checker find the values for us. It's a
+ // bit tricky: look up the object declared by the name, find its
+ // types.Const, and extract its value.
+ obj, ok := f.pkg.defs[name]
+ if !ok {
+ log.Fatalf("no value for constant %s", name)
+ }
+ info := obj.Type().Underlying().(*types.Basic).Info()
+ if info&types.IsInteger == 0 {
+ log.Fatalf("can't handle non-integer constant type %s", typ)
+ }
+ value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
+ if value.Kind() != constant.Int {
+ log.Fatalf("can't happen: constant is not an integer %s", name)
+ }
+ i64, isInt := constant.Int64Val(value)
+ u64, isUint := constant.Uint64Val(value)
+ if !isInt && !isUint {
+ log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
+ }
+ if !isInt {
+ u64 = uint64(i64)
+ }
+ v := Value{
+ originalName: name.Name,
+ value: u64,
+ signed: info&types.IsUnsigned == 0,
+ str: value.String(),
+ }
+ if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 {
+ v.name = strings.TrimSpace(c.Text())
+ } else {
+ v.name = strings.TrimPrefix(v.originalName, f.trimPrefix)
+ }
+ f.values = append(f.values, v)
+ }
+ }
+ return false
+}
+
+// Helpers
+
+// usize returns the number of bits of the smallest unsigned integer
+// type that will hold n. Used to create the smallest possible slice of
+// integers to use as indexes into the concatenated strings.
+func usize(n int) int {
+ switch {
+ case n < 1<<8:
+ return 8
+ case n < 1<<16:
+ return 16
+ default:
+ // 2^32 is enough constants for anyone.
+ return 32
+ }
+}
+
+// declareIndexAndNameVars declares the index slices and concatenated names
+// strings representing the runs of values.
+func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
+ var indexes, names []string
+ for i, run := range runs {
+ index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
+ if len(run) != 1 {
+ indexes = append(indexes, index)
+ }
+ names = append(names, name)
+ }
+ g.Printf("const (\n")
+ for _, name := range names {
+ g.Printf("\t%s\n", name)
+ }
+ g.Printf(")\n\n")
+
+ if len(indexes) > 0 {
+ g.Printf("var (")
+ for _, index := range indexes {
+ g.Printf("\t%s\n", index)
+ }
+ g.Printf(")\n\n")
+ }
+}
+
+// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
+func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
+ index, name := g.createIndexAndNameDecl(run, typeName, "")
+ g.Printf("const %s\n", name)
+ g.Printf("var %s\n", index)
+}
+
+// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
+func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
+ b := new(bytes.Buffer)
+ indexes := make([]int, len(run))
+ for i := range run {
+ b.WriteString(run[i].name)
+ indexes[i] = b.Len()
+ }
+ nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String())
+ nameLen := b.Len()
+ b.Reset()
+ fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
+ for i, v := range indexes {
+ if i > 0 {
+ fmt.Fprintf(b, ", ")
+ }
+ fmt.Fprintf(b, "%d", v)
+ }
+ fmt.Fprintf(b, "}")
+ return b.String(), nameConst
+}
+
+// declareNameVars declares the concatenated names string representing all the values in the runs.
+func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
+ g.Printf("const _%s_name%s = \"", typeName, suffix)
+ for _, run := range runs {
+ for i := range run {
+ g.Printf("%s", run[i].name)
+ }
+ }
+ g.Printf("\"\n")
+}
+
+// buildOneRun generates the variables and String method for a single run of contiguous values.
+func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
+ values := runs[0]
+ g.Printf("\n")
+ g.declareIndexAndNameVar(values, typeName)
+ g.Printf(stringOneRun, typeName, values[0].String())
+}
+
+// Arguments to format are:
+//
+// [1]: type name
+// [2]: lowest defined value for type, as a string
+const stringOneRun = `func (i %[1]s) String() string {
+ idx := int(i) - %[2]s
+ if i < %[2]s || idx >= len(_%[1]s_index)-1 {
+ return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _%[1]s_name[_%[1]s_index[idx] : _%[1]s_index[idx+1]]
+}
+`
+
+// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
+// For this pattern, a single Printf format won't do.
+func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
+ g.Printf("\n")
+ g.declareIndexAndNameVars(runs, typeName)
+ g.Printf("func (i %s) String() string {\n", typeName)
+ g.Printf("\tswitch {\n")
+ for i, values := range runs {
+ if len(values) == 1 {
+ g.Printf("\tcase i == %s:\n", &values[0])
+ g.Printf("\t\treturn _%s_name_%d\n", typeName, i)
+ continue
+ }
+ if values[0].value == 0 && !values[0].signed {
+ // For an unsigned lower bound of 0, "0 <= i" would be redundant.
+ g.Printf("\tcase i <= %s:\n", &values[len(values)-1])
+ } else {
+ g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1])
+ }
+ if values[0].value != 0 {
+ g.Printf("\t\ti -= %s\n", &values[0])
+ }
+ g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n",
+ typeName, i, typeName, i, typeName, i)
+ }
+ g.Printf("\tdefault:\n")
+ g.Printf("\t\treturn \"%s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n", typeName)
+ g.Printf("\t}\n")
+ g.Printf("}\n")
+}
+
+// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
+// It's a rare situation but has simple code.
+func (g *Generator) buildMap(runs [][]Value, typeName string) {
+ g.Printf("\n")
+ g.declareNameVars(runs, typeName, "")
+ g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName)
+ n := 0
+ for _, values := range runs {
+ for _, value := range values {
+ g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name))
+ n += len(value.name)
+ }
+ }
+ g.Printf("}\n\n")
+ g.Printf(stringMap, typeName)
+}
+
+// Argument to format is the type name.
+const stringMap = `func (i %[1]s) String() string {
+ if str, ok := _%[1]s_map[i]; ok {
+ return str
+ }
+ return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")"
+}
+`
diff --git a/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/inline/doc.go b/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/inline/doc.go
new file mode 100644
index 00000000000..a3e98cb6572
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/inline/doc.go
@@ -0,0 +1,109 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package inline defines an analyzer that inlines calls to functions
+and uses of constants marked with a "//go:fix inline" directive.
+
+# Analyzer inline
+
+inline: apply fixes based on 'go:fix inline' comment directives
+
+The inline analyzer inlines functions and constants that are marked for inlining.
+
+## Functions
+
+Given a function that is marked for inlining, like this one:
+
+ //go:fix inline
+ func Square(x int) int { return Pow(x, 2) }
+
+this analyzer will recommend that calls to the function elsewhere, in the same
+or other packages, should be inlined.
+
+Inlining can be used to move off of a deprecated function:
+
+ // Deprecated: prefer Pow(x, 2).
+ //go:fix inline
+ func Square(x int) int { return Pow(x, 2) }
+
+It can also be used to move off of an obsolete package,
+as when the import path has changed or a higher major version is available:
+
+ package pkg
+
+ import pkg2 "pkg/v2"
+
+ //go:fix inline
+ func F() { pkg2.F(nil) }
+
+Replacing a call pkg.F() by pkg2.F(nil) can have no effect on the program,
+so this mechanism provides a low-risk way to update large numbers of calls.
+We recommend, where possible, expressing the old API in terms of the new one
+to enable automatic migration.
+
+The inliner takes care to avoid behavior changes, even subtle ones,
+such as changes to the order in which argument expressions are
+evaluated. When it cannot safely eliminate all parameter variables,
+it may introduce a "binding declaration" of the form
+
+ var params = args
+
+to evaluate argument expressions in the correct order and bind them to
+parameter variables. Since the resulting code transformation may be
+stylistically suboptimal, such inlinings may be disabled by specifying
+the -inline.allow_binding_decl=false flag to the analyzer driver.
+
+(In cases where it is not safe to "reduce" a call—that is, to replace
+a call f(x) by the body of function f, suitably substituted—the
+inliner machinery is capable of replacing f by a function literal,
+func(){...}(). However, the inline analyzer discards all such
+"literalizations" unconditionally, again on grounds of style.)
+
+## Constants
+
+Given a constant that is marked for inlining, like this one:
+
+ //go:fix inline
+ const Ptr = Pointer
+
+this analyzer will recommend that uses of Ptr should be replaced with Pointer.
+
+As with functions, inlining can be used to replace deprecated constants and
+constants in obsolete packages.
+
+A constant definition can be marked for inlining only if it refers to another
+named constant.
+
+The "//go:fix inline" comment must appear before a single const declaration on its own,
+as above; before a const declaration that is part of a group, as in this case:
+
+ const (
+ C = 1
+ //go:fix inline
+ Ptr = Pointer
+ )
+
+or before a group, applying to every constant in the group:
+
+ //go:fix inline
+ const (
+ Ptr = Pointer
+ Val = Value
+ )
+
+The proposal https://go.dev/issue/32816 introduces the "//go:fix inline" directives.
+
+You can use this command to apply inline fixes en masse:
+
+ $ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...
+
+# Analyzer gofixdirective
+
+gofixdirective: validate uses of //go:fix comment directives
+
+The gofixdirective analyzer checks "//go:fix inline" directives for correctness.
+See the documentation for the gofix analyzer for more about "/go:fix inline".
+*/
+package inline
diff --git a/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/inline/inline.go b/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/inline/inline.go
new file mode 100644
index 00000000000..efa2dcaf89d
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/inline/inline.go
@@ -0,0 +1,624 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+import (
+ "fmt"
+ "go/ast"
+ "go/types"
+ "slices"
+ "strings"
+
+ _ "embed"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/analysis/passes/internal/gofixdirective"
+ "golang.org/x/tools/go/ast/edge"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/go/types/typeutil"
+ "golang.org/x/tools/internal/analysis/analyzerutil"
+ typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
+ "golang.org/x/tools/internal/astutil"
+ "golang.org/x/tools/internal/moreiters"
+ "golang.org/x/tools/internal/packagepath"
+ "golang.org/x/tools/internal/refactor"
+ "golang.org/x/tools/internal/refactor/inline"
+ "golang.org/x/tools/internal/typesinternal"
+ "golang.org/x/tools/internal/typesinternal/typeindex"
+)
+
+//go:embed doc.go
+var doc string
+
+var Analyzer = &analysis.Analyzer{
+ Name: "inline",
+ Doc: analyzerutil.MustExtractDoc(doc, "inline"),
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline",
+ Run: run,
+ FactTypes: []analysis.Fact{
+ (*goFixInlineFuncFact)(nil),
+ (*goFixInlineConstFact)(nil),
+ (*goFixInlineAliasFact)(nil),
+ },
+ Requires: []*analysis.Analyzer{
+ inspect.Analyzer,
+ typeindexanalyzer.Analyzer,
+ },
+}
+
+var (
+ allowBindingDecl bool
+ lazyEdits bool
+)
+
+func init() {
+ Analyzer.Flags.BoolVar(&allowBindingDecl, "allow_binding_decl", false,
+ "permit inlinings that require a 'var params = args' declaration")
+ Analyzer.Flags.BoolVar(&lazyEdits, "lazy_edits", false,
+ "compute edits lazily (only meaningful to gopls driver)")
+}
+
+// analyzer holds the state for this analysis.
+type analyzer struct {
+ pass *analysis.Pass
+ root inspector.Cursor
+ index *typeindex.Index
+ // memoization of repeated calls for same file.
+ fileContent map[string][]byte
+ // memoization of fact imports (nil => no fact)
+ inlinableFuncs map[*types.Func]*inline.Callee
+ inlinableConsts map[*types.Const]*goFixInlineConstFact
+ inlinableAliases map[*types.TypeName]*goFixInlineAliasFact
+}
+
+func run(pass *analysis.Pass) (any, error) {
+ a := &analyzer{
+ pass: pass,
+ root: pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Root(),
+ index: pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index),
+ fileContent: make(map[string][]byte),
+ inlinableFuncs: make(map[*types.Func]*inline.Callee),
+ inlinableConsts: make(map[*types.Const]*goFixInlineConstFact),
+ inlinableAliases: make(map[*types.TypeName]*goFixInlineAliasFact),
+ }
+ gofixdirective.Find(pass, a.root, a)
+ a.inline()
+ return nil, nil
+}
+
+// HandleFunc exports a fact for functions marked with go:fix.
+func (a *analyzer) HandleFunc(decl *ast.FuncDecl) {
+ content, err := a.readFile(decl)
+ if err != nil {
+ a.pass.Reportf(decl.Doc.Pos(), "invalid inlining candidate: cannot read source file: %v", err)
+ return
+ }
+ callee, err := inline.AnalyzeCallee(discard, a.pass.Fset, a.pass.Pkg, a.pass.TypesInfo, decl, content)
+ if err != nil {
+ a.pass.Reportf(decl.Doc.Pos(), "invalid inlining candidate: %v", err)
+ return
+ }
+ fn := a.pass.TypesInfo.Defs[decl.Name].(*types.Func)
+ a.pass.ExportObjectFact(fn, &goFixInlineFuncFact{callee})
+ a.inlinableFuncs[fn] = callee
+}
+
+// HandleAlias exports a fact for aliases marked with go:fix.
+func (a *analyzer) HandleAlias(spec *ast.TypeSpec) {
+ // Remember that this is an inlinable alias.
+ typ := &goFixInlineAliasFact{}
+ lhs := a.pass.TypesInfo.Defs[spec.Name].(*types.TypeName)
+ a.inlinableAliases[lhs] = typ
+ // Create a fact only if the LHS is exported and defined at top level.
+ // We create a fact even if the RHS is non-exported,
+ // so we can warn about uses in other packages.
+ if lhs.Exported() && typesinternal.IsPackageLevel(lhs) {
+ a.pass.ExportObjectFact(lhs, typ)
+ }
+}
+
+// HandleConst exports a fact for constants marked with go:fix.
+func (a *analyzer) HandleConst(nameIdent, rhsIdent *ast.Ident) {
+ lhs := a.pass.TypesInfo.Defs[nameIdent].(*types.Const)
+ rhs := a.pass.TypesInfo.Uses[rhsIdent].(*types.Const) // must be so in a well-typed program
+ con := &goFixInlineConstFact{
+ RHSName: rhs.Name(),
+ RHSPkgName: rhs.Pkg().Name(),
+ RHSPkgPath: rhs.Pkg().Path(),
+ }
+ if rhs.Pkg() == a.pass.Pkg {
+ con.rhsObj = rhs
+ }
+ a.inlinableConsts[lhs] = con
+ // Create a fact only if the LHS is exported and defined at top level.
+ // We create a fact even if the RHS is non-exported,
+ // so we can warn about uses in other packages.
+ if lhs.Exported() && typesinternal.IsPackageLevel(lhs) {
+ a.pass.ExportObjectFact(lhs, con)
+ }
+}
+
+// inline inlines each static call to an inlinable function
+// and each reference to an inlinable constant or type alias.
+func (a *analyzer) inline() {
+ for cur := range a.root.Preorder((*ast.CallExpr)(nil), (*ast.Ident)(nil)) {
+ switch n := cur.Node().(type) {
+ case *ast.CallExpr:
+ a.inlineCall(n, cur)
+
+ case *ast.Ident:
+ switch t := a.pass.TypesInfo.Uses[n].(type) {
+ case *types.TypeName:
+ a.inlineAlias(t, cur)
+ case *types.Const:
+ a.inlineConst(t, cur)
+ }
+ }
+ }
+}
+
+// If call is a call to an inlinable func, suggest inlining its use at cur.
+func (a *analyzer) inlineCall(call *ast.CallExpr, cur inspector.Cursor) {
+ if fn := typeutil.StaticCallee(a.pass.TypesInfo, call); fn != nil {
+ // Inlinable?
+ callee, ok := a.inlinableFuncs[fn]
+ if !ok {
+ var fact goFixInlineFuncFact
+ if a.pass.ImportObjectFact(fn, &fact) {
+ callee = fact.Callee
+ a.inlinableFuncs[fn] = callee
+ }
+ }
+ if callee == nil {
+ return // nope
+ }
+
+ if a.withinTestOf(cur, fn) {
+ return // don't inline a function from within its own test
+ }
+
+ // Compute the edits.
+ //
+ // Ordinarily the analyzer reports a fix containing
+ // edits. However, the algorithm is somewhat expensive
+ // (unnecessarily so: see go.dev/issue/75773) so
+ // to reduce costs in gopls, we omit the edits,
+ // meaning that gopls must compute them on demand
+ // (based on the Diagnostic.Category) when they are
+ // requested via a code action.
+ //
+ // This does mean that the following categories of
+ // caller-dependent obstacles to inlining will be
+ // reported when the gopls user requests the fix,
+ // rather than by quietly suppressing the diagnostic:
+ // - shadowing problems
+ // - callee imports inaccessible "internal" packages
+ // - callee refers to nonexported symbols
+ // - callee uses too-new Go features
+ // - inlining call from a cgo file
+ var edits []analysis.TextEdit
+ if !lazyEdits {
+ // Inline the call.
+ caller := &inline.Caller{
+ Fset: a.pass.Fset,
+ Types: a.pass.Pkg,
+ Info: a.pass.TypesInfo,
+ File: astutil.EnclosingFile(cur),
+ Call: call,
+ CountUses: func(pkgname *types.PkgName) int {
+ return moreiters.Len(a.index.Uses(pkgname))
+ },
+ }
+ res, err := inline.Inline(caller, callee, &inline.Options{Logf: discard})
+ if err != nil {
+ a.pass.Reportf(call.Lparen, "%v", err)
+ return
+ }
+
+ if res.Literalized {
+ // Users are not fond of inlinings that literalize
+ // f(x) to func() { ... }(), so avoid them.
+ //
+ // (Unfortunately the inliner is very timid,
+ // and often literalizes when it cannot prove that
+ // reducing the call is safe; the user of this tool
+ // has no indication of what the problem is.)
+ return
+ }
+ if res.BindingDecl && !allowBindingDecl {
+ // When applying fix en masse, users are similarly
+ // unenthusiastic about inlinings that cannot
+ // entirely eliminate the parameters and
+ // insert a 'var params = args' declaration.
+ // The flag allows them to decline such fixes.
+ return
+ }
+ edits = res.Edits
+ }
+
+ a.pass.Report(analysis.Diagnostic{
+ Pos: call.Pos(),
+ End: call.End(),
+ Message: fmt.Sprintf("Call of %v should be inlined", callee),
+ Category: "inline_call", // keep consistent with gopls/internal/golang.fixInlineCall
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: fmt.Sprintf("Inline call of %v", callee),
+ TextEdits: edits, // within gopls, this is nil => compute fix's edits lazily
+ }},
+ })
+ }
+}
+
+// withinTestOf reports whether cur is within a dedicated test
+// function for the inlinable target function.
+// A call within its dedicated test should not be inlined.
+func (a *analyzer) withinTestOf(cur inspector.Cursor, target *types.Func) bool {
+ curFuncDecl, ok := moreiters.First(cur.Enclosing((*ast.FuncDecl)(nil)))
+ if !ok {
+ return false // not in a function
+ }
+ funcDecl := curFuncDecl.Node().(*ast.FuncDecl)
+ if funcDecl.Recv != nil {
+ return false // not a test func
+ }
+ if strings.TrimSuffix(a.pass.Pkg.Path(), "_test") != target.Pkg().Path() {
+ return false // different package
+ }
+ if !strings.HasSuffix(a.pass.Fset.File(funcDecl.Pos()).Name(), "_test.go") {
+ return false // not a test file
+ }
+
+ // Computed expected SYMBOL portion of "TestSYMBOL_comment"
+ // for the target symbol.
+ symbol := target.Name()
+ if recv := target.Signature().Recv(); recv != nil {
+ _, named := typesinternal.ReceiverNamed(recv)
+ symbol = named.Obj().Name() + "_" + symbol
+ }
+
+ // TODO(adonovan): use a proper Test function parser.
+ fname := funcDecl.Name.Name
+ for _, pre := range []string{"Test", "Example", "Bench"} {
+ if fname == pre+symbol || strings.HasPrefix(fname, pre+symbol+"_") {
+ return true
+ }
+ }
+
+ return false
+}
+
+// If tn is the TypeName of an inlinable alias, suggest inlining its use at cur.
+func (a *analyzer) inlineAlias(tn *types.TypeName, curId inspector.Cursor) {
+ inalias, ok := a.inlinableAliases[tn]
+ if !ok {
+ var fact goFixInlineAliasFact
+ if a.pass.ImportObjectFact(tn, &fact) {
+ inalias = &fact
+ a.inlinableAliases[tn] = inalias
+ }
+ }
+ if inalias == nil {
+ return // nope
+ }
+
+ alias := tn.Type().(*types.Alias)
+ // Remember the names of the alias's type params. When we check for shadowing
+ // later, we'll ignore these because they won't appear in the replacement text.
+ typeParamNames := map[*types.TypeName]bool{}
+ for tp := range alias.TypeParams().TypeParams() {
+ typeParamNames[tp.Obj()] = true
+ }
+ rhs := alias.Rhs()
+ curPath := a.pass.Pkg.Path()
+ curFile := astutil.EnclosingFile(curId)
+ id := curId.Node().(*ast.Ident)
+
+ // Find the complete identifier, which may take any of these forms:
+ // Id
+ // Id[T]
+ // Id[K, V]
+ // pkg.Id
+ // pkg.Id[T]
+ // pkg.Id[K, V]
+ var expr ast.Expr = id
+ if curId.ParentEdgeKind() == edge.SelectorExpr_Sel {
+ curId = curId.Parent()
+ expr = curId.Node().(ast.Expr)
+ }
+ // If expr is part of an IndexExpr or IndexListExpr, we'll need that node.
+ // Given C[int], TypeOf(C) is generic but TypeOf(C[int]) is instantiated.
+ switch curId.ParentEdgeKind() {
+ case edge.IndexExpr_X:
+ curId = curId.Parent()
+ expr = curId.Node().(*ast.IndexExpr)
+ case edge.IndexListExpr_X:
+ curId = curId.Parent()
+ expr = curId.Node().(*ast.IndexListExpr)
+ }
+
+ fieldType := curId
+ if fieldType.ParentEdgeKind() == edge.StarExpr_X {
+ fieldType = fieldType.Parent()
+ }
+ if fieldType.ParentEdgeKind() == edge.Field_Type {
+ field := fieldType.Parent().Node().(*ast.Field)
+ if len(field.Names) == 0 {
+ identicalName := false
+ if rhs, ok := alias.Rhs().(*types.Named); ok {
+ identicalName = alias.Obj().Name() == rhs.Obj().Name()
+ }
+ if !identicalName {
+ // Type is embedded, inlining the alias will cause
+ // the field name to be changed, which might break
+ // programs in terms of backwards compatibility.
+ return
+ }
+ }
+ }
+
+ t := a.pass.TypesInfo.TypeOf(expr).(*types.Alias) // type of entire identifier
+ if targs := t.TypeArgs(); targs.Len() > 0 {
+ // Instantiate the alias with the type args from this use.
+ // For example, given type A = M[K, V], compute the type of the use
+ // A[int, Foo] as M[int, Foo].
+ // Don't validate instantiation: it can't panic unless we have a bug,
+ // in which case seeing the stack trace via telemetry would be helpful.
+ instAlias, _ := types.Instantiate(nil, alias, slices.Collect(targs.Types()), false)
+ rhs = instAlias.(*types.Alias).Rhs()
+ }
+
+ // We have an identifier A here (n), possibly qualified by a package
+ // identifier (sel.n), and an inlinable "type A = rhs" elsewhere.
+ //
+ // We can replace A with rhs if no name in rhs is shadowed at n's position,
+ // and every package in rhs is importable by the current package.
+ var (
+ importPrefixes = map[string]string{curPath: ""} // from pkg path to prefix
+ edits []analysis.TextEdit
+ )
+ for _, tn := range typenames(rhs) {
+ // Ignore the type parameters of the alias: they won't appear in the result.
+ if typeParamNames[tn] {
+ continue
+ }
+ var pkgPath, pkgName string
+ if pkg := tn.Pkg(); pkg != nil {
+ pkgPath = pkg.Path()
+ pkgName = pkg.Name()
+ }
+ if pkgPath == "" || pkgPath == curPath {
+ // The name is in the current package or the universe scope, so no import
+ // is required. Check that it is not shadowed (that is, that the type
+ // it refers to in rhs is the same one it refers to at n).
+ scope := a.pass.TypesInfo.Scopes[curFile].Innermost(id.Pos()) // n's scope
+ _, obj := scope.LookupParent(tn.Name(), id.Pos()) // what qn.name means in n's scope
+ if obj != tn {
+ return
+ }
+ } else if !packagepath.CanImport(a.pass.Pkg.Path(), pkgPath) {
+ // If this package can't see the package of this part of rhs, we can't inline.
+ return
+ } else if _, ok := importPrefixes[pkgPath]; !ok {
+ // Use AddImport to add pkgPath if it's not there already. Associate the prefix it assigns
+ // with the prefix it assigns
+ // with the package path for use by the TypeString qualifier below.
+ prefix, eds := refactor.AddImport(
+ a.pass.TypesInfo, curFile, pkgName, pkgPath, tn.Name(), id.Pos())
+ importPrefixes[pkgPath] = strings.TrimSuffix(prefix, ".")
+ edits = append(edits, eds...)
+ }
+ }
+
+ // To get the replacement text, render the alias RHS using the package prefixes
+ // we assigned above.
+ newText := types.TypeString(rhs, func(p *types.Package) string {
+ if p == a.pass.Pkg {
+ return ""
+ }
+ if prefix, ok := importPrefixes[p.Path()]; ok {
+ return prefix
+ }
+ panic(fmt.Sprintf("in %q, package path %q has no import prefix", rhs, p.Path()))
+ })
+ a.reportInline("type alias", "Type alias", expr, edits, newText)
+}
+
+// typenames returns the TypeNames for types within t (including t itself) that have
+// them: basic types, named types and alias types.
+// The same name may appear more than once.
+func typenames(t types.Type) []*types.TypeName {
+ var tns []*types.TypeName
+
+ var visit func(types.Type)
+ visit = func(t types.Type) {
+ if hasName, ok := t.(interface{ Obj() *types.TypeName }); ok {
+ tns = append(tns, hasName.Obj())
+ }
+ switch t := t.(type) {
+ case *types.Basic:
+ tns = append(tns, types.Universe.Lookup(t.Name()).(*types.TypeName))
+ case *types.Named:
+ for t := range t.TypeArgs().Types() {
+ visit(t)
+ }
+ case *types.Alias:
+ for t := range t.TypeArgs().Types() {
+ visit(t)
+ }
+ case *types.TypeParam:
+ tns = append(tns, t.Obj())
+ case *types.Pointer:
+ visit(t.Elem())
+ case *types.Slice:
+ visit(t.Elem())
+ case *types.Array:
+ visit(t.Elem())
+ case *types.Chan:
+ visit(t.Elem())
+ case *types.Map:
+ visit(t.Key())
+ visit(t.Elem())
+ case *types.Struct:
+ for field := range t.Fields() {
+ visit(field.Type())
+ }
+ case *types.Signature:
+ // Ignore the receiver: although it may be present, it has no meaning
+ // in a type expression.
+ // Ditto for receiver type params.
+ // Also, function type params cannot appear in a type expression.
+ if t.TypeParams() != nil {
+ panic("Signature.TypeParams in type expression")
+ }
+ visit(t.Params())
+ visit(t.Results())
+ case *types.Interface:
+ for etyp := range t.EmbeddedTypes() {
+ visit(etyp)
+ }
+ for method := range t.ExplicitMethods() {
+ visit(method.Type())
+ }
+ case *types.Tuple:
+ for v := range t.Variables() {
+ visit(v.Type())
+ }
+ case *types.Union:
+ panic("Union in type expression")
+ default:
+ panic(fmt.Sprintf("unknown type %T", t))
+ }
+ }
+
+ visit(t)
+
+ return tns
+}
+
+// If con is an inlinable constant, suggest inlining its use at cur.
+func (a *analyzer) inlineConst(con *types.Const, cur inspector.Cursor) {
+ incon, ok := a.inlinableConsts[con]
+ if !ok {
+ var fact goFixInlineConstFact
+ if a.pass.ImportObjectFact(con, &fact) {
+ incon = &fact
+ a.inlinableConsts[con] = incon
+ }
+ }
+ if incon == nil {
+ return // nope
+ }
+
+ // If n is qualified by a package identifier, we'll need the full selector expression.
+ curFile := astutil.EnclosingFile(cur)
+ n := cur.Node().(*ast.Ident)
+
+ // We have an identifier A here (n), possibly qualified by a package identifier (sel.X,
+ // where sel is the parent of n), // and an inlinable "const A = B" elsewhere (incon).
+ // Consider replacing A with B.
+
+ // Check that the expression we are inlining (B) means the same thing
+ // (refers to the same object) in n's scope as it does in A's scope.
+ // If the RHS is not in the current package, AddImport will handle
+ // shadowing, so we only need to worry about when both expressions
+ // are in the current package.
+ if a.pass.Pkg.Path() == incon.RHSPkgPath {
+ // incon.rhsObj is the object referred to by B in the definition of A.
+ scope := a.pass.TypesInfo.Scopes[curFile].Innermost(n.Pos()) // n's scope
+ _, obj := scope.LookupParent(incon.RHSName, n.Pos()) // what "B" means in n's scope
+ if obj == nil {
+ // Should be impossible: if code at n can refer to the LHS,
+ // it can refer to the RHS.
+ panic(fmt.Sprintf("no object for inlinable const %s RHS %s", n.Name, incon.RHSName))
+ }
+ if obj != incon.rhsObj {
+ // "B" means something different here than at the inlinable const's scope.
+ return
+ }
+ } else if !packagepath.CanImport(a.pass.Pkg.Path(), incon.RHSPkgPath) {
+ // If this package can't see the RHS's package, we can't inline.
+ return
+ }
+ var (
+ importPrefix string
+ edits []analysis.TextEdit
+ )
+ if incon.RHSPkgPath != a.pass.Pkg.Path() {
+ importPrefix, edits = refactor.AddImport(
+ a.pass.TypesInfo, curFile, incon.RHSPkgName, incon.RHSPkgPath, incon.RHSName, n.Pos())
+ }
+ // If n is qualified by a package identifier, we'll need the full selector expression.
+ var expr ast.Expr = n
+ if cur.ParentEdgeKind() == edge.SelectorExpr_Sel {
+ expr = cur.Parent().Node().(ast.Expr)
+ }
+ a.reportInline("constant", "Constant", expr, edits, importPrefix+incon.RHSName)
+}
+
+// reportInline reports a diagnostic for fixing an inlinable name.
+func (a *analyzer) reportInline(kind, capKind string, ident ast.Expr, edits []analysis.TextEdit, newText string) {
+ edits = append(edits, analysis.TextEdit{
+ Pos: ident.Pos(),
+ End: ident.End(),
+ NewText: []byte(newText),
+ })
+ name := astutil.Format(a.pass.Fset, ident)
+ a.pass.Report(analysis.Diagnostic{
+ Pos: ident.Pos(),
+ End: ident.End(),
+ Message: fmt.Sprintf("%s %s should be inlined", capKind, name),
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: fmt.Sprintf("Inline %s %s", kind, name),
+ TextEdits: edits,
+ }},
+ })
+}
+
+func (a *analyzer) readFile(node ast.Node) ([]byte, error) {
+ filename := a.pass.Fset.File(node.Pos()).Name()
+ content, ok := a.fileContent[filename]
+ if !ok {
+ var err error
+ content, err = a.pass.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ a.fileContent[filename] = content
+ }
+ return content, nil
+}
+
+// A goFixInlineFuncFact is exported for each function marked "//go:fix inline".
+// It holds information about the callee to support inlining.
+type goFixInlineFuncFact struct{ Callee *inline.Callee }
+
+func (f *goFixInlineFuncFact) String() string { return "goFixInline " + f.Callee.String() }
+func (*goFixInlineFuncFact) AFact() {}
+
+// A goFixInlineConstFact is exported for each constant marked "//go:fix inline".
+// It holds information about an inlinable constant. Gob-serializable.
+type goFixInlineConstFact struct {
+ // Information about "const LHSName = RHSName".
+ RHSName string
+ RHSPkgPath string
+ RHSPkgName string
+ rhsObj types.Object // for current package
+}
+
+func (c *goFixInlineConstFact) String() string {
+ return fmt.Sprintf("goFixInline const %q.%s", c.RHSPkgPath, c.RHSName)
+}
+
+func (*goFixInlineConstFact) AFact() {}
+
+// A goFixInlineAliasFact is exported for each type alias marked "//go:fix inline".
+// It holds no information; its mere existence demonstrates that an alias is inlinable.
+type goFixInlineAliasFact struct{}
+
+func (c *goFixInlineAliasFact) String() string { return "goFixInline alias" }
+func (*goFixInlineAliasFact) AFact() {}
+
+func discard(string, ...any) {}
diff --git a/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/internal/gofixdirective/gofixdirective.go b/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/internal/gofixdirective/gofixdirective.go
new file mode 100644
index 00000000000..949df4bfeac
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/go/analysis/passes/internal/gofixdirective/gofixdirective.go
@@ -0,0 +1,143 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gofixdirective searches for and validates go:fix directives. The
+// go/analysis/passes/inline package uses findgofix to perform inlining.
+// The go/analysis/passes/gofix package uses findgofix to check for problems
+// with go:fix directives.
+//
+// gofixdirective is separate from gofix to avoid depending on refactor/inline,
+// which is large.
+package gofixdirective
+
+// This package is tested by go/analysis/passes/inline.
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/ast/inspector"
+ internalastutil "golang.org/x/tools/internal/astutil"
+)
+
+// A Handler handles language entities with go:fix directives.
+type Handler interface {
+ HandleFunc(*ast.FuncDecl)
+ HandleAlias(*ast.TypeSpec)
+ HandleConst(name, rhs *ast.Ident)
+}
+
+// Find finds functions and constants annotated with an appropriate "//go:fix"
+// comment (the syntax proposed by #32816), and calls handler methods for each one.
+// h may be nil.
+func Find(pass *analysis.Pass, root inspector.Cursor, h Handler) {
+ for cur := range root.Preorder((*ast.FuncDecl)(nil), (*ast.GenDecl)(nil)) {
+ switch decl := cur.Node().(type) {
+ case *ast.FuncDecl:
+ findFunc(decl, h)
+
+ case *ast.GenDecl:
+ if decl.Tok != token.CONST && decl.Tok != token.TYPE {
+ continue
+ }
+ declInline := hasFixInline(decl.Doc)
+ // Accept inline directives on the entire decl as well as individual specs.
+ for _, spec := range decl.Specs {
+ switch spec := spec.(type) {
+ case *ast.TypeSpec: // Tok == TYPE
+ findAlias(pass, spec, declInline, h)
+
+ case *ast.ValueSpec: // Tok == CONST
+ findConst(pass, spec, declInline, h)
+ }
+ }
+ }
+ }
+}
+
+func findFunc(decl *ast.FuncDecl, h Handler) {
+ if !hasFixInline(decl.Doc) {
+ return
+ }
+ if h != nil {
+ h.HandleFunc(decl)
+ }
+}
+
+func findAlias(pass *analysis.Pass, spec *ast.TypeSpec, declInline bool, h Handler) {
+ if !declInline && !hasFixInline(spec.Doc) {
+ return
+ }
+ if !spec.Assign.IsValid() {
+ pass.Reportf(spec.Pos(), "invalid //go:fix inline directive: not a type alias")
+ return
+ }
+
+ // Disallow inlines of type expressions containing array types.
+ // Given an array type like [N]int where N is a named constant, go/types provides
+ // only the value of the constant as an int64. So inlining A in this code:
+ //
+ // const N = 5
+ // type A = [N]int
+ //
+ // would result in [5]int, breaking the connection with N.
+ for n := range ast.Preorder(spec.Type) {
+ if ar, ok := n.(*ast.ArrayType); ok && ar.Len != nil {
+ // Make an exception when the array length is a literal int.
+ if lit, ok := ast.Unparen(ar.Len).(*ast.BasicLit); ok && lit.Kind == token.INT {
+ continue
+ }
+ pass.Reportf(spec.Pos(), "invalid //go:fix inline directive: array types not supported")
+ return
+ }
+ }
+ if h != nil {
+ h.HandleAlias(spec)
+ }
+}
+
+func findConst(pass *analysis.Pass, spec *ast.ValueSpec, declInline bool, h Handler) {
+ specInline := hasFixInline(spec.Doc)
+ if declInline || specInline {
+ for i, nameIdent := range spec.Names {
+ if i >= len(spec.Values) {
+ // Possible following an iota.
+ break
+ }
+ var rhsIdent *ast.Ident
+ switch val := spec.Values[i].(type) {
+ case *ast.Ident:
+ // Constants defined with the predeclared iota cannot be inlined.
+ if pass.TypesInfo.Uses[val] == builtinIota {
+ pass.Reportf(val.Pos(), "invalid //go:fix inline directive: const value is iota")
+ return
+ }
+ rhsIdent = val
+ case *ast.SelectorExpr:
+ rhsIdent = val.Sel
+ default:
+ pass.Reportf(val.Pos(), "invalid //go:fix inline directive: const value is not the name of another constant")
+ return
+ }
+ if h != nil {
+ h.HandleConst(nameIdent, rhsIdent)
+ }
+ }
+ }
+}
+
+// hasFixInline reports the presence of a "//go:fix inline" directive
+// in the comments.
+func hasFixInline(cg *ast.CommentGroup) bool {
+ for _, d := range internalastutil.Directives(cg) {
+ if d.Tool == "go" && d.Name == "fix" && d.Args == "inline" {
+ return true
+ }
+ }
+ return false
+}
+
+var builtinIota = types.Universe.Lookup("iota")
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/astutil/free/free.go b/hack/tools/vendor/golang.org/x/tools/internal/astutil/free/free.go
new file mode 100644
index 00000000000..2c4d2c4e52f
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/astutil/free/free.go
@@ -0,0 +1,418 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package free defines utilities for computing the free variables of
+// a syntax tree without type information. This is inherently
+// heuristic because of the T{f: x} ambiguity, in which f may or may
+// not be a lexical reference depending on whether T is a struct type.
+package free
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+// Copied, with considerable changes, from go/parser/resolver.go
+// at af53bd2c03.
+
+// Names computes an approximation to the set of free names of the AST
+// at node n based solely on syntax.
+//
+// In the absence of composite literals, the set of free names is exact. Composite
+// literals introduce an ambiguity that can only be resolved with type information:
+// whether F is a field name or a value in `T{F: ...}`.
+// If includeComplitIdents is true, this function conservatively assumes
+// T is not a struct type, so freeishNames overapproximates: the resulting
+// set may contain spurious entries that are not free lexical references
+// but are references to struct fields.
+// If includeComplitIdents is false, this function assumes that T *is*
+// a struct type, so freeishNames underapproximates: the resulting set
+// may omit names that are free lexical references.
+//
+// TODO(adonovan): includeComplitIdents is a crude hammer: the caller
+// may have partial or heuristic information about whether a given T
+// is struct type. Replace includeComplitIdents with a hook to query
+// the caller.
+//
+// The code is based on go/parser.resolveFile, but heavily simplified. Crucial
+// differences are:
+// - Instead of resolving names to their objects, this function merely records
+// whether they are free.
+// - Labels are ignored: they do not refer to values.
+// - This is never called on ImportSpecs, so the function panics if it sees one.
+func Names(n ast.Node, includeComplitIdents bool) map[string]bool {
+ v := &freeVisitor{
+ free: make(map[string]bool),
+ includeComplitIdents: includeComplitIdents,
+ }
+ // Begin with a scope, even though n might not be a form that establishes a scope.
+ // For example, n might be:
+ // x := ...
+ // Then we need to add the first x to some scope.
+ v.openScope()
+ ast.Walk(v, n)
+ v.closeScope()
+ if v.scope != nil {
+ panic("unbalanced scopes")
+ }
+ return v.free
+}
+
+// A freeVisitor holds state for a free-name analysis.
+type freeVisitor struct {
+ scope *scope // the current innermost scope
+ free map[string]bool // free names seen so far
+ includeComplitIdents bool // include identifier key in composite literals
+}
+
+// scope contains all the names defined in a lexical scope.
+// It is like ast.Scope, but without deprecation warnings.
+type scope struct {
+ names map[string]bool
+ outer *scope
+}
+
+func (s *scope) defined(name string) bool {
+ for ; s != nil; s = s.outer {
+ if s.names[name] {
+ return true
+ }
+ }
+ return false
+}
+
+func (v *freeVisitor) Visit(n ast.Node) ast.Visitor {
+ switch n := n.(type) {
+
+ // Expressions.
+ case *ast.Ident:
+ v.use(n)
+
+ case *ast.FuncLit:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFuncType(nil, n.Type)
+ v.walkBody(n.Body)
+
+ case *ast.SelectorExpr:
+ v.walk(n.X)
+ // Skip n.Sel: it cannot be free.
+
+ case *ast.StructType:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFieldList(n.Fields)
+
+ case *ast.FuncType:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFuncType(nil, n)
+
+ case *ast.CompositeLit:
+ v.walk(n.Type)
+ for _, e := range n.Elts {
+ if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+ if ident, _ := kv.Key.(*ast.Ident); ident != nil {
+ // It is not possible from syntax alone to know whether
+ // an identifier used as a composite literal key is
+ // a struct field (if n.Type is a struct) or a value
+ // (if n.Type is a map, slice or array).
+ if v.includeComplitIdents {
+ // Over-approximate by treating both cases as potentially
+ // free names.
+ v.use(ident)
+ } else {
+ // Under-approximate by ignoring potentially free names.
+ }
+ } else {
+ v.walk(kv.Key)
+ }
+ v.walk(kv.Value)
+ } else {
+ v.walk(e)
+ }
+ }
+
+ case *ast.InterfaceType:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFieldList(n.Methods)
+
+ // Statements
+ case *ast.AssignStmt:
+ walkSlice(v, n.Rhs)
+ if n.Tok == token.DEFINE {
+ v.shortVarDecl(n.Lhs)
+ } else {
+ walkSlice(v, n.Lhs)
+ }
+
+ case *ast.LabeledStmt:
+ // Ignore labels.
+ v.walk(n.Stmt)
+
+ case *ast.BranchStmt:
+ // Ignore labels.
+
+ case *ast.BlockStmt:
+ v.openScope()
+ defer v.closeScope()
+ walkSlice(v, n.List)
+
+ case *ast.IfStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Init)
+ v.walk(n.Cond)
+ v.walk(n.Body)
+ v.walk(n.Else)
+
+ case *ast.CaseClause:
+ walkSlice(v, n.List)
+ v.openScope()
+ defer v.closeScope()
+ walkSlice(v, n.Body)
+
+ case *ast.SwitchStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Init)
+ v.walk(n.Tag)
+ v.walkBody(n.Body)
+
+ case *ast.TypeSwitchStmt:
+ v.openScope()
+ defer v.closeScope()
+ if n.Init != nil {
+ v.walk(n.Init)
+ }
+ v.walk(n.Assign)
+ // We can use walkBody here because we don't track label scopes.
+ v.walkBody(n.Body)
+
+ case *ast.CommClause:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Comm)
+ walkSlice(v, n.Body)
+
+ case *ast.SelectStmt:
+ v.walkBody(n.Body)
+
+ case *ast.ForStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Init)
+ v.walk(n.Cond)
+ v.walk(n.Post)
+ v.walk(n.Body)
+
+ case *ast.RangeStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.X)
+ var lhs []ast.Expr
+ if n.Key != nil {
+ lhs = append(lhs, n.Key)
+ }
+ if n.Value != nil {
+ lhs = append(lhs, n.Value)
+ }
+ if len(lhs) > 0 {
+ if n.Tok == token.DEFINE {
+ v.shortVarDecl(lhs)
+ } else {
+ walkSlice(v, lhs)
+ }
+ }
+ v.walk(n.Body)
+
+ // Declarations
+ case *ast.GenDecl:
+ switch n.Tok {
+ case token.CONST, token.VAR:
+ for _, spec := range n.Specs {
+ spec := spec.(*ast.ValueSpec)
+ walkSlice(v, spec.Values)
+ v.walk(spec.Type)
+ v.declare(spec.Names...)
+ }
+
+ case token.TYPE:
+ for _, spec := range n.Specs {
+ spec := spec.(*ast.TypeSpec)
+ // Go spec: The scope of a type identifier declared inside a
+ // function begins at the identifier in the TypeSpec and ends
+ // at the end of the innermost containing block.
+ v.declare(spec.Name)
+ if spec.TypeParams != nil {
+ v.openScope()
+ defer v.closeScope()
+ v.walkTypeParams(spec.TypeParams)
+ }
+ v.walk(spec.Type)
+ }
+
+ case token.IMPORT:
+ panic("encountered import declaration in free analysis")
+ }
+
+ case *ast.FuncDecl:
+ if n.Recv == nil && n.Name.Name != "init" { // package-level function
+ v.declare(n.Name)
+ }
+ v.openScope()
+ defer v.closeScope()
+ v.walkTypeParams(n.Type.TypeParams)
+ v.walkFuncType(n.Recv, n.Type)
+ v.walkBody(n.Body)
+
+ default:
+ return v
+ }
+
+ return nil
+}
+
+func (v *freeVisitor) openScope() {
+ v.scope = &scope{map[string]bool{}, v.scope}
+}
+
+func (v *freeVisitor) closeScope() {
+ v.scope = v.scope.outer
+}
+
+func (v *freeVisitor) walk(n ast.Node) {
+ if n != nil {
+ ast.Walk(v, n)
+ }
+}
+
+func (v *freeVisitor) walkFuncType(recv *ast.FieldList, typ *ast.FuncType) {
+ // First use field types...
+ v.walkRecvFieldType(recv)
+ v.walkFieldTypes(typ.Params)
+ v.walkFieldTypes(typ.Results)
+
+ // ...then declare field names.
+ v.declareFieldNames(recv)
+ v.declareFieldNames(typ.Params)
+ v.declareFieldNames(typ.Results)
+}
+
+// A receiver field is not like a param or result field because
+// "func (recv R[T]) method()" uses R but declares T.
+func (v *freeVisitor) walkRecvFieldType(list *ast.FieldList) {
+ if list == nil {
+ return
+ }
+ for _, f := range list.List { // valid => len=1
+ typ := f.Type
+ if ptr, ok := typ.(*ast.StarExpr); ok {
+ typ = ptr.X
+ }
+
+ // Analyze receiver type as Base[Index, ...]
+ var (
+ base ast.Expr
+ indices []ast.Expr
+ )
+ switch typ := typ.(type) {
+ case *ast.IndexExpr: // B[T]
+ base, indices = typ.X, []ast.Expr{typ.Index}
+ case *ast.IndexListExpr: // B[K, V]
+ base, indices = typ.X, typ.Indices
+ default: // B
+ base = typ
+ }
+ for _, expr := range indices {
+ if id, ok := expr.(*ast.Ident); ok {
+ v.declare(id)
+ }
+ }
+ v.walk(base)
+ }
+}
+
+// walkTypeParams is like walkFieldList, but declares type parameters eagerly so
+// that they may be resolved in the constraint expressions held in the field
+// Type.
+func (v *freeVisitor) walkTypeParams(list *ast.FieldList) {
+ v.declareFieldNames(list)
+ v.walkFieldTypes(list) // constraints
+}
+
+func (v *freeVisitor) walkBody(body *ast.BlockStmt) {
+ if body == nil {
+ return
+ }
+ walkSlice(v, body.List)
+}
+
+func (v *freeVisitor) walkFieldList(list *ast.FieldList) {
+ if list == nil {
+ return
+ }
+ v.walkFieldTypes(list) // .Type may contain references
+ v.declareFieldNames(list) // .Names declares names
+}
+
+func (v *freeVisitor) shortVarDecl(lhs []ast.Expr) {
+ // Go spec: A short variable declaration may redeclare variables provided
+ // they were originally declared in the same block with the same type, and
+ // at least one of the non-blank variables is new.
+ //
+ // However, it doesn't matter to free analysis whether a variable is declared
+ // fresh or redeclared.
+ for _, x := range lhs {
+ // In a well-formed program each expr must be an identifier,
+ // but be forgiving.
+ if id, ok := x.(*ast.Ident); ok {
+ v.declare(id)
+ }
+ }
+}
+
+func walkSlice[S ~[]E, E ast.Node](r *freeVisitor, list S) {
+ for _, e := range list {
+ r.walk(e)
+ }
+}
+
+// walkFieldTypes resolves the types of the walkFieldTypes in list.
+// The companion method declareFieldList declares the names of the walkFieldTypes.
+func (v *freeVisitor) walkFieldTypes(list *ast.FieldList) {
+ if list != nil {
+ for _, f := range list.List {
+ v.walk(f.Type)
+ }
+ }
+}
+
+// declareFieldNames declares the names of the fields in list.
+// (Names in a FieldList always establish new bindings.)
+// The companion method resolveFieldList resolves the types of the fields.
+func (v *freeVisitor) declareFieldNames(list *ast.FieldList) {
+ if list != nil {
+ for _, f := range list.List {
+ v.declare(f.Names...)
+ }
+ }
+}
+
+// use marks ident as free if it is not in scope.
+func (v *freeVisitor) use(ident *ast.Ident) {
+ if s := ident.Name; s != "_" && !v.scope.defined(s) {
+ v.free[s] = true
+ }
+}
+
+// declare adds each non-blank ident to the current scope.
+func (v *freeVisitor) declare(idents ...*ast.Ident) {
+ for _, id := range idents {
+ if id.Name != "_" {
+ v.scope.names[id.Name] = true
+ }
+ }
+}
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/callee.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/callee.go
new file mode 100644
index 00000000000..815c8c0bba0
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/callee.go
@@ -0,0 +1,925 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+// This file defines the analysis of the callee function.
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "go/types"
+ "slices"
+ "strings"
+
+ "golang.org/x/tools/go/types/typeutil"
+ "golang.org/x/tools/internal/typeparams"
+ "golang.org/x/tools/internal/typesinternal"
+)
+
+// A Callee holds information about an inlinable function. Gob-serializable.
+type Callee struct {
+ impl gobCallee
+}
+
+func (callee *Callee) String() string { return callee.impl.Name }
+
+type gobCallee struct {
+ Content []byte // file content, compacted to a single func decl
+
+ // results of type analysis (does not reach go/types data structures)
+ PkgPath string // package path of declaring package
+ Name string // user-friendly name for error messages
+ GoVersion string // version of Go effective in callee file
+ Unexported []string // names of free objects that are unexported
+ FreeRefs []freeRef // locations of references to free objects
+ FreeObjs []object // descriptions of free objects
+ ValidForCallStmt bool // function body is "return expr" where expr is f() or <-ch
+ NumResults int // number of results (according to type, not ast.FieldList)
+ Params []*paramInfo // information about parameters (incl. receiver)
+ TypeParams []*paramInfo // information about type parameters
+ Results []*paramInfo // information about result variables
+ Effects []int // order in which parameters are evaluated (see calleefx)
+ HasDefer bool // uses defer
+ HasBareReturn bool // uses bare return in non-void function
+ Returns [][]returnOperandFlags // metadata about result expressions for each return
+ Labels []string // names of all control labels
+ Falcon falconResult // falcon constraint system
+}
+
+// returnOperandFlags records metadata about a single result expression in a return
+// statement.
+type returnOperandFlags int
+
+const (
+ nonTrivialResult returnOperandFlags = 1 << iota // return operand has non-trivial conversion to result type
+ untypedNilResult // return operand is nil literal
+)
+
+// A freeRef records a reference to a free object. Gob-serializable.
+// (This means free relative to the FuncDecl as a whole, i.e. excluding parameters.)
+type freeRef struct {
+ Offset int // byte offset of the reference relative to the FuncDecl
+ Object int // index into Callee.freeObjs
+}
+
+// An object abstracts a free types.Object referenced by the callee. Gob-serializable.
+type object struct {
+ Name string // Object.Name()
+ Kind string // one of {var,func,const,type,pkgname,nil,builtin}
+ PkgPath string // path of object's package (or imported package if kind="pkgname")
+ PkgName string // name of object's package (or imported package if kind="pkgname")
+ // TODO(rfindley): should we also track LocalPkgName here? Do we want to
+ // preserve the local package name?
+ ValidPos bool // Object.Pos().IsValid()
+ Shadow shadowMap // shadowing info for the object's refs
+}
+
+// AnalyzeCallee analyzes a function that is a candidate for inlining
+// and returns a Callee that describes it. The Callee object, which is
+// serializable, can be passed to one or more subsequent calls to
+// Inline, each with a different Caller.
+//
+// This design allows separate analysis of callers and callees in the
+// golang.org/x/tools/go/analysis framework: the inlining information
+// about a callee can be recorded as a "fact".
+//
+// The content should be the actual input to the compiler, not the
+// apparent source file according to any //line directives that
+// may be present within it.
+func AnalyzeCallee(logf func(string, ...any), fset *token.FileSet, pkg *types.Package, info *types.Info, decl *ast.FuncDecl, content []byte) (*Callee, error) {
+ checkInfoFields(info)
+
+ // The client is expected to have determined that the callee
+ // is a function with a declaration (not a built-in or var).
+ fn := info.Defs[decl.Name].(*types.Func)
+ sig := fn.Type().(*types.Signature)
+
+ logf("analyzeCallee %v @ %v", fn, fset.PositionFor(decl.Pos(), false))
+
+ // Create user-friendly name ("pkg.Func" or "(pkg.T).Method")
+ var name string
+ if sig.Recv() == nil {
+ name = fmt.Sprintf("%s.%s", fn.Pkg().Name(), fn.Name())
+ } else {
+ name = fmt.Sprintf("(%s).%s", types.TypeString(sig.Recv().Type(), (*types.Package).Name), fn.Name())
+ }
+
+ if decl.Body == nil {
+ return nil, fmt.Errorf("cannot inline function %s as it has no body", name)
+ }
+
+ // Record the file's Go goVersion so that we don't
+ // inline newer code into file using an older dialect.
+ //
+ // Using the file version is overly conservative.
+ // A more precise solution would be for the type checker to
+ // record which language features the callee actually needs;
+ // see https://go.dev/issue/75726.
+ //
+ // We don't have the ast.File handy, so instead of a
+ // lookup we must scan the entire FileVersions map.
+ var goVersion string
+ for file, v := range info.FileVersions {
+ if file.Pos() < decl.Pos() && decl.Pos() < file.End() {
+ goVersion = v
+ break
+ }
+ }
+
+ // Record the location of all free references in the FuncDecl.
+ // (Parameters are not free by this definition.)
+ var (
+ fieldObjs = fieldObjs(sig)
+ freeObjIndex = make(map[types.Object]int)
+ freeObjs []object
+ freeRefs []freeRef // free refs that may need renaming
+ unexported []string // free refs to unexported objects, for later error checks
+ )
+ var f func(n ast.Node, stack []ast.Node) bool
+ var stack []ast.Node
+ stack = append(stack, decl.Type) // for scope of function itself
+ visit := func(n ast.Node, stack []ast.Node) { ast.PreorderStack(n, stack, f) }
+ f = func(n ast.Node, stack []ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.SelectorExpr:
+ // Check selections of free fields/methods.
+ if sel, ok := info.Selections[n]; ok &&
+ !within(sel.Obj().Pos(), decl) &&
+ !n.Sel.IsExported() {
+ sym := fmt.Sprintf("(%s).%s", info.TypeOf(n.X), n.Sel.Name)
+ unexported = append(unexported, sym)
+ }
+
+ // Don't recur into SelectorExpr.Sel.
+ visit(n.X, stack)
+ return false
+
+ case *ast.CompositeLit:
+ // Check for struct literals that refer to unexported fields,
+ // whether keyed or unkeyed. (Logic assumes well-typedness.)
+ litType := typeparams.Deref(info.TypeOf(n))
+ if s, ok := typeparams.CoreType(litType).(*types.Struct); ok {
+ if n.Type != nil {
+ visit(n.Type, stack)
+ }
+ for i, elt := range n.Elts {
+ var field *types.Var
+ var value ast.Expr
+ if kv, ok := elt.(*ast.KeyValueExpr); ok {
+ field = info.Uses[kv.Key.(*ast.Ident)].(*types.Var)
+ value = kv.Value
+ } else {
+ field = s.Field(i)
+ value = elt
+ }
+ if !within(field.Pos(), decl) && !field.Exported() {
+ sym := fmt.Sprintf("(%s).%s", litType, field.Name())
+ unexported = append(unexported, sym)
+ }
+
+ // Don't recur into KeyValueExpr.Key.
+ visit(value, stack)
+ }
+ return false
+ }
+
+ case *ast.Ident:
+ if obj, ok := info.Uses[n]; ok {
+ // Methods and fields are handled by SelectorExpr and CompositeLit.
+ if isField(obj) || isMethod(obj) {
+ panic(obj)
+ }
+ // Inv: id is a lexical reference.
+
+ // A reference to an unexported package-level declaration
+ // cannot be inlined into another package.
+ if !n.IsExported() &&
+ obj.Pkg() != nil && obj.Parent() == obj.Pkg().Scope() {
+ unexported = append(unexported, n.Name)
+ }
+
+ // Record free reference (incl. self-reference).
+ if obj == fn || !within(obj.Pos(), decl) {
+ objidx, ok := freeObjIndex[obj]
+ if !ok {
+ objidx = len(freeObjIndex)
+ var pkgPath, pkgName string
+ if pn, ok := obj.(*types.PkgName); ok {
+ pkgPath = pn.Imported().Path()
+ pkgName = pn.Imported().Name()
+ } else if obj.Pkg() != nil {
+ pkgPath = obj.Pkg().Path()
+ pkgName = obj.Pkg().Name()
+ }
+ freeObjs = append(freeObjs, object{
+ Name: obj.Name(),
+ Kind: objectKind(obj),
+ PkgName: pkgName,
+ PkgPath: pkgPath,
+ ValidPos: obj.Pos().IsValid(),
+ })
+ freeObjIndex[obj] = objidx
+ }
+
+ freeObjs[objidx].Shadow = freeObjs[objidx].Shadow.add(info, fieldObjs, obj.Name(), stack)
+
+ freeRefs = append(freeRefs, freeRef{
+ Offset: int(n.Pos() - decl.Pos()),
+ Object: objidx,
+ })
+ }
+ }
+ }
+ return true
+ }
+ visit(decl, stack)
+
+ // Analyze callee body for "return expr" form,
+ // where expr is f() or <-ch. These forms are
+ // safe to inline as a standalone statement.
+ validForCallStmt := false
+ if len(decl.Body.List) != 1 {
+ // not just a return statement
+ } else if ret, ok := decl.Body.List[0].(*ast.ReturnStmt); ok && len(ret.Results) == 1 {
+ validForCallStmt = func() bool {
+ switch expr := ast.Unparen(ret.Results[0]).(type) {
+ case *ast.CallExpr: // f(x)
+ callee := typeutil.Callee(info, expr)
+ if callee == nil {
+ return false // conversion T(x)
+ }
+
+ // The only non-void built-in functions that may be
+ // called as a statement are copy and recover
+ // (though arguably a call to recover should never
+ // be inlined as that changes its behavior).
+ if builtin, ok := callee.(*types.Builtin); ok {
+ return builtin.Name() == "copy" ||
+ builtin.Name() == "recover"
+ }
+
+ return true // ordinary call f()
+
+ case *ast.UnaryExpr: // <-x
+ return expr.Op == token.ARROW // channel receive <-ch
+ }
+
+ // No other expressions are valid statements.
+ return false
+ }()
+ }
+
+ // Record information about control flow in the callee
+ // (but not any nested functions).
+ var (
+ hasDefer = false
+ hasBareReturn = false
+ returnInfo [][]returnOperandFlags
+ labels []string
+ )
+ ast.Inspect(decl.Body, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.FuncLit:
+ return false // prune traversal
+ case *ast.DeferStmt:
+ hasDefer = true
+ case *ast.LabeledStmt:
+ labels = append(labels, n.Label.Name)
+ case *ast.ReturnStmt:
+
+ // Are implicit assignment conversions
+ // to result variables all trivial?
+ var resultInfo []returnOperandFlags
+ if len(n.Results) > 0 {
+ argInfo := func(i int) (ast.Expr, types.Type) {
+ expr := n.Results[i]
+ return expr, info.TypeOf(expr)
+ }
+ if len(n.Results) == 1 && sig.Results().Len() > 1 {
+ // Spread return: return f() where f.Results > 1.
+ tuple := info.TypeOf(n.Results[0]).(*types.Tuple)
+ argInfo = func(i int) (ast.Expr, types.Type) {
+ return nil, tuple.At(i).Type()
+ }
+ }
+ for i := range sig.Results().Len() {
+ expr, typ := argInfo(i)
+ var flags returnOperandFlags
+ if typ == types.Typ[types.UntypedNil] { // untyped nil is preserved by go/types
+ flags |= untypedNilResult
+ }
+ if !trivialConversion(info.Types[expr].Value, typ, sig.Results().At(i).Type()) {
+ flags |= nonTrivialResult
+ }
+ resultInfo = append(resultInfo, flags)
+ }
+ } else if sig.Results().Len() > 0 {
+ hasBareReturn = true
+ }
+ returnInfo = append(returnInfo, resultInfo)
+ }
+ return true
+ })
+
+ // Reject attempts to inline cgo-generated functions.
+ for _, obj := range freeObjs {
+ // There are others (iconst fconst sconst fpvar macro)
+ // but this is probably sufficient.
+ if strings.HasPrefix(obj.Name, "_Cfunc_") ||
+ strings.HasPrefix(obj.Name, "_Ctype_") ||
+ strings.HasPrefix(obj.Name, "_Cvar_") {
+ return nil, fmt.Errorf("cannot inline cgo-generated functions")
+ }
+ }
+
+ // Compact content to just the FuncDecl.
+ //
+ // As a space optimization, we don't retain the complete
+ // callee file content; all we need is "package _; func f() { ... }".
+ // This reduces the size of analysis facts.
+ //
+ // Offsets in the callee information are "relocatable"
+ // since they are all relative to the FuncDecl.
+
+ content = append([]byte("package _\n"),
+ content[offsetOf(fset, decl.Pos()):offsetOf(fset, decl.End())]...)
+ // Sanity check: re-parse the compacted content.
+ if _, _, err := parseCompact(content); err != nil {
+ return nil, err
+ }
+
+ params, results, effects, falcon := analyzeParams(logf, fset, info, decl)
+ tparams := analyzeTypeParams(logf, fset, info, decl)
+ return &Callee{gobCallee{
+ Content: content,
+ PkgPath: pkg.Path(),
+ Name: name,
+ GoVersion: goVersion,
+ Unexported: unexported,
+ FreeObjs: freeObjs,
+ FreeRefs: freeRefs,
+ ValidForCallStmt: validForCallStmt,
+ NumResults: sig.Results().Len(),
+ Params: params,
+ TypeParams: tparams,
+ Results: results,
+ Effects: effects,
+ HasDefer: hasDefer,
+ HasBareReturn: hasBareReturn,
+ Returns: returnInfo,
+ Labels: labels,
+ Falcon: falcon,
+ }}, nil
+}
+
+// parseCompact parses a Go source file of the form "package _\n func f() { ... }"
+// and returns the sole function declaration.
+func parseCompact(content []byte) (*token.FileSet, *ast.FuncDecl, error) {
+ fset := token.NewFileSet()
+ const mode = parser.ParseComments | parser.SkipObjectResolution | parser.AllErrors
+ f, err := parser.ParseFile(fset, "callee.go", content, mode)
+ if err != nil {
+ return nil, nil, fmt.Errorf("internal error: cannot compact file: %v", err)
+ }
+ return fset, f.Decls[0].(*ast.FuncDecl), nil
+}
+
+// A paramInfo records information about a callee receiver, parameter, or result variable.
+type paramInfo struct {
+ Name string // parameter name (may be blank, or even "")
+ Index int // index within signature
+ IsResult bool // false for receiver or parameter, true for result variable
+ IsInterface bool // parameter has a (non-type parameter) interface type
+ Assigned bool // parameter appears on left side of an assignment statement
+ Escapes bool // parameter has its address taken
+ Refs []refInfo // information about references to parameter within body
+ Shadow shadowMap // shadowing info for the above refs; see [shadowMap]
+ FalconType string // name of this parameter's type (if basic) in the falcon system
+}
+
+type refInfo struct {
+ Offset int // FuncDecl-relative byte offset of parameter ref within body
+ Assignable bool // ref appears in context of assignment to known type
+ IfaceAssignment bool // ref is being assigned to an interface
+ AffectsInference bool // ref type may affect type inference
+ // IsSelectionOperand indicates whether the parameter reference is the
+ // operand of a selection (param.f). If so, and param's argument is itself
+ // a receiver parameter (a common case), we don't need to desugar (&v or *ptr)
+ // the selection: if param.Method is a valid selection, then so is param.fieldOrMethod.
+ IsSelectionOperand bool
+}
+
+// analyzeParams computes information about parameters of the function declared by decl,
+// including a simple "address taken" escape analysis.
+//
+// It returns two new arrays, one of the receiver and parameters, and
+// the other of the result variables of the function.
+//
+// The input must be well-typed.
+func analyzeParams(logf func(string, ...any), fset *token.FileSet, info *types.Info, decl *ast.FuncDecl) (params, results []*paramInfo, effects []int, _ falconResult) {
+ sig := signature(fset, info, decl)
+
+ paramInfos := make(map[*types.Var]*paramInfo)
+ {
+ newParamInfo := func(param *types.Var, isResult bool) *paramInfo {
+ info := ¶mInfo{
+ Name: param.Name(),
+ IsResult: isResult,
+ Index: len(paramInfos),
+ IsInterface: isNonTypeParamInterface(param.Type()),
+ }
+ paramInfos[param] = info
+ return info
+ }
+ if sig.Recv() != nil {
+ params = append(params, newParamInfo(sig.Recv(), false))
+ }
+ for v := range sig.Params().Variables() {
+ params = append(params, newParamInfo(v, false))
+ }
+ for v := range sig.Results().Variables() {
+ results = append(results, newParamInfo(v, true))
+ }
+ }
+
+ // Search function body for operations &x, x.f(), and x = y
+ // where x is a parameter, and record it.
+ escape(info, decl, func(v *types.Var, escapes bool) {
+ if info := paramInfos[v]; info != nil {
+ if escapes {
+ info.Escapes = true
+ } else {
+ info.Assigned = true
+ }
+ }
+ })
+
+ // Record locations of all references to parameters.
+ // And record the set of intervening definitions for each parameter.
+ //
+ // TODO(adonovan): combine this traversal with the one that computes
+ // FreeRefs. The tricky part is that calleefx needs this one first.
+ fieldObjs := fieldObjs(sig)
+ var stack []ast.Node
+ stack = append(stack, decl.Type) // for scope of function itself
+ ast.PreorderStack(decl.Body, stack, func(n ast.Node, stack []ast.Node) bool {
+ if id, ok := n.(*ast.Ident); ok {
+ if v, ok := info.Uses[id].(*types.Var); ok {
+ if pinfo, ok := paramInfos[v]; ok {
+ // Record ref information, and any intervening (shadowing) names.
+ //
+ // If the parameter v has an interface type, and the reference id
+ // appears in a context where assignability rules apply, there may be
+ // an implicit interface-to-interface widening. In that case it is
+ // not necessary to insert an explicit conversion from the argument
+ // to the parameter's type.
+ //
+ // Contrapositively, if param is not an interface type, then the
+ // assignment may lose type information, for example in the case that
+ // the substituted expression is an untyped constant or unnamed type.
+ stack = append(stack, n) // (the two calls below want n)
+ assignable, ifaceAssign, affectsInference := analyzeAssignment(info, stack)
+ ref := refInfo{
+ Offset: int(n.Pos() - decl.Pos()),
+ Assignable: assignable,
+ IfaceAssignment: ifaceAssign,
+ AffectsInference: affectsInference,
+ IsSelectionOperand: isSelectionOperand(stack),
+ }
+ pinfo.Refs = append(pinfo.Refs, ref)
+ pinfo.Shadow = pinfo.Shadow.add(info, fieldObjs, pinfo.Name, stack)
+ }
+ }
+ }
+ return true
+ })
+
+ // Compute subset and order of parameters that are strictly evaluated.
+ // (Depends on Refs computed above.)
+ effects = calleefx(info, decl.Body, paramInfos)
+ logf("effects list = %v", effects)
+
+ falcon := falcon(logf, fset, paramInfos, info, decl)
+
+ return params, results, effects, falcon
+}
+
+// analyzeTypeParams computes information about the type parameters of the function declared by decl.
+func analyzeTypeParams(_ logger, fset *token.FileSet, info *types.Info, decl *ast.FuncDecl) []*paramInfo {
+ sig := signature(fset, info, decl)
+ paramInfos := make(map[*types.TypeName]*paramInfo)
+ var params []*paramInfo
+ collect := func(tpl *types.TypeParamList) {
+ for tparam := range tpl.TypeParams() {
+ typeName := tparam.Obj()
+ info := ¶mInfo{Name: typeName.Name()}
+ params = append(params, info)
+ paramInfos[typeName] = info
+ }
+ }
+ collect(sig.RecvTypeParams())
+ collect(sig.TypeParams())
+
+ // Find references.
+ // We don't care about most of the properties that matter for parameter references:
+ // a type is immutable, cannot have its address taken, and does not undergo conversions.
+ // TODO(jba): can we nevertheless combine this with the traversal in analyzeParams?
+ var stack []ast.Node
+ stack = append(stack, decl.Type) // for scope of function itself
+ ast.PreorderStack(decl.Body, stack, func(n ast.Node, stack []ast.Node) bool {
+ if id, ok := n.(*ast.Ident); ok {
+ if v, ok := info.Uses[id].(*types.TypeName); ok {
+ if pinfo, ok := paramInfos[v]; ok {
+ ref := refInfo{Offset: int(n.Pos() - decl.Pos())}
+ pinfo.Refs = append(pinfo.Refs, ref)
+ pinfo.Shadow = pinfo.Shadow.add(info, nil, pinfo.Name, stack)
+ }
+ }
+ }
+ return true
+ })
+ return params
+}
+
+func signature(fset *token.FileSet, info *types.Info, decl *ast.FuncDecl) *types.Signature {
+ fnobj, ok := info.Defs[decl.Name]
+ if !ok {
+ panic(fmt.Sprintf("%s: no func object for %q",
+ fset.PositionFor(decl.Name.Pos(), false), decl.Name)) // ill-typed?
+ }
+ return fnobj.Type().(*types.Signature)
+}
+
+// -- callee helpers --
+
+// analyzeAssignment looks at the given stack, and analyzes certain
+// attributes of the innermost expression.
+//
+// In all cases we 'fail closed' when we cannot detect (or for simplicity
+// choose not to detect) the condition in question, meaning we err on the side
+// of the more restrictive rule. This is noted for each result below.
+//
+// - assignable reports whether the expression is used in a position where
+// assignability rules apply, such as in an actual assignment, as call
+// argument, or in a send to a channel. Defaults to 'false'. If assignable
+// is false, the other two results are irrelevant.
+// - ifaceAssign reports whether that assignment is to an interface type.
+// This is important as we want to preserve the concrete type in that
+// assignment. Defaults to 'true'. Notably, if the assigned type is a type
+// parameter, we assume that it could have interface type.
+// - affectsInference is (somewhat vaguely) defined as whether or not the
+// type of the operand may affect the type of the surrounding syntax,
+// through type inference. It is infeasible to completely reverse engineer
+// type inference, so we over approximate: if the expression is an argument
+// to a call to a generic function (but not method!) that uses type
+// parameters, assume that unification of that argument may affect the
+// inferred types.
+func analyzeAssignment(info *types.Info, stack []ast.Node) (assignable, ifaceAssign, affectsInference bool) {
+ remaining, parent, expr := exprContext(stack)
+ if parent == nil {
+ return false, false, false
+ }
+
+ // TODO(golang/go#70638): simplify when types.Info records implicit conversions.
+
+ // Types do not need to match for assignment to a variable.
+ if assign, ok := parent.(*ast.AssignStmt); ok {
+ for i, v := range assign.Rhs {
+ if v == expr {
+ if i >= len(assign.Lhs) {
+ return false, false, false // ill typed
+ }
+ // Check to see if the assignment is to an interface type.
+ if i < len(assign.Lhs) {
+ // TODO: We could handle spread calls here, but in current usage expr
+ // is an ident.
+ if id, _ := assign.Lhs[i].(*ast.Ident); id != nil && info.Defs[id] != nil {
+ // Types must match for a defining identifier in a short variable
+ // declaration.
+ return false, false, false
+ }
+ // In all other cases, types should be known.
+ typ := info.TypeOf(assign.Lhs[i])
+ return true, typ == nil || types.IsInterface(typ), false
+ }
+ // Default:
+ return assign.Tok == token.ASSIGN, true, false
+ }
+ }
+ }
+
+ // Types do not need to match for an initializer with known type.
+ if spec, ok := parent.(*ast.ValueSpec); ok && spec.Type != nil {
+ if slices.Contains(spec.Values, expr) {
+ typ := info.TypeOf(spec.Type)
+ return true, typ == nil || types.IsInterface(typ), false
+ }
+ }
+
+ // Types do not need to match for index expressions.
+ if ix, ok := parent.(*ast.IndexExpr); ok {
+ if ix.Index == expr {
+ typ := info.TypeOf(ix.X)
+ if typ == nil {
+ return true, true, false
+ }
+ m, _ := typeparams.CoreType(typ).(*types.Map)
+ return true, m == nil || types.IsInterface(m.Key()), false
+ }
+ }
+
+ // Types do not need to match for composite literal keys, values, or
+ // fields.
+ if kv, ok := parent.(*ast.KeyValueExpr); ok {
+ var under types.Type
+ if len(remaining) > 0 {
+ if complit, ok := remaining[len(remaining)-1].(*ast.CompositeLit); ok {
+ if typ := info.TypeOf(complit); typ != nil {
+ // Unpointer to allow for pointers to slices or arrays, which are
+ // permitted as the types of nested composite literals without a type
+ // name.
+ under = typesinternal.Unpointer(typeparams.CoreType(typ))
+ }
+ }
+ }
+ if kv.Key == expr { // M{expr: ...}: assign to map key
+ m, _ := under.(*types.Map)
+ return true, m == nil || types.IsInterface(m.Key()), false
+ }
+ if kv.Value == expr {
+ switch under := under.(type) {
+ case interface{ Elem() types.Type }: // T{...: expr}: assign to map/array/slice element
+ return true, types.IsInterface(under.Elem()), false
+ case *types.Struct: // Struct{k: expr}
+ if id, _ := kv.Key.(*ast.Ident); id != nil {
+ for field := range under.Fields() {
+ if info.Uses[id] == field {
+ return true, types.IsInterface(field.Type()), false
+ }
+ }
+ }
+ default:
+ return true, true, false
+ }
+ }
+ }
+ if lit, ok := parent.(*ast.CompositeLit); ok {
+ for i, v := range lit.Elts {
+ if v == expr {
+ typ := info.TypeOf(lit)
+ if typ == nil {
+ return true, true, false
+ }
+ // As in the KeyValueExpr case above, unpointer to handle pointers to
+ // array/slice literals.
+ under := typesinternal.Unpointer(typeparams.CoreType(typ))
+ switch under := under.(type) {
+ case interface{ Elem() types.Type }: // T{expr}: assign to map/array/slice element
+ return true, types.IsInterface(under.Elem()), false
+ case *types.Struct: // Struct{expr}: assign to unkeyed struct field
+ if i < under.NumFields() {
+ return true, types.IsInterface(under.Field(i).Type()), false
+ }
+ }
+ return true, true, false
+ }
+ }
+ }
+
+ // Types do not need to match for values sent to a channel.
+ if send, ok := parent.(*ast.SendStmt); ok {
+ if send.Value == expr {
+ typ := info.TypeOf(send.Chan)
+ if typ == nil {
+ return true, true, false
+ }
+ ch, _ := typeparams.CoreType(typ).(*types.Chan)
+ return true, ch == nil || types.IsInterface(ch.Elem()), false
+ }
+ }
+
+ // Types do not need to match for an argument to a call, unless the
+ // corresponding parameter has type parameters, as in that case the
+ // argument type may affect inference.
+ if call, ok := parent.(*ast.CallExpr); ok {
+ if _, ok := isConversion(info, call); ok {
+ return false, false, false // redundant conversions are handled at the call site
+ }
+ // Ordinary call. Could be a call of a func, builtin, or function value.
+ for i, arg := range call.Args {
+ if arg == expr {
+ typ := info.TypeOf(call.Fun)
+ if typ == nil {
+ return true, true, false
+ }
+ sig, _ := typeparams.CoreType(typ).(*types.Signature)
+ if sig != nil {
+ // Find the relevant parameter type, accounting for variadics.
+ paramType := paramTypeAtIndex(sig, call, i)
+ ifaceAssign := paramType == nil || types.IsInterface(paramType)
+ affectsInference := false
+ switch callee := typeutil.Callee(info, call).(type) {
+ case *types.Builtin:
+ // Consider this litmus test:
+ //
+ // func f(x int64) any { return max(x) }
+ // func main() { fmt.Printf("%T", f(42)) }
+ //
+ // If we lose the implicit conversion from untyped int
+ // to int64, the type inferred for the max(x) call changes,
+ // resulting in a different dynamic behavior: it prints
+ // int, not int64.
+ //
+ // Inferred result type affected:
+ // new
+ // complex, real, imag
+ // min, max
+ //
+ // Dynamic behavior change:
+ // append -- dynamic type of append([]any(nil), x)[0]
+ // delete(m, x) -- dynamic key type where m is map[any]unit
+ // panic -- dynamic type of panic value
+ //
+ // Unaffected:
+ // recover
+ // make
+ // len, cap
+ // clear
+ // close
+ // copy
+ // print, println -- only uses underlying types (?)
+ //
+ // The dynamic type cases are all covered by
+ // the ifaceAssign logic.
+ switch callee.Name() {
+ case "new", "complex", "real", "imag", "min", "max":
+ affectsInference = true
+ }
+
+ case *types.Func:
+ // Only standalone (non-method) functions have type
+ // parameters affected by the call arguments.
+ if sig2 := callee.Signature(); sig2.Recv() == nil {
+ originParamType := paramTypeAtIndex(sig2, call, i)
+ affectsInference = originParamType == nil || new(typeparams.Free).Has(originParamType)
+ }
+ }
+ return true, ifaceAssign, affectsInference
+ }
+ }
+ }
+ }
+
+ return false, false, false
+}
+
+// paramTypeAtIndex returns the effective parameter type at the given argument
+// index in call, if valid.
+func paramTypeAtIndex(sig *types.Signature, call *ast.CallExpr, index int) types.Type {
+ if plen := sig.Params().Len(); sig.Variadic() && index >= plen-1 && !call.Ellipsis.IsValid() {
+ if s, ok := sig.Params().At(plen - 1).Type().(*types.Slice); ok {
+ return s.Elem()
+ }
+ } else if index < plen {
+ return sig.Params().At(index).Type()
+ }
+ return nil // ill typed
+}
+
+// exprContext returns the innermost parent->child expression nodes for the
+// given outer-to-inner stack, after stripping parentheses, along with the
+// remaining stack up to the parent node.
+//
+// If no such context exists, returns (nil, nil, nil).
+func exprContext(stack []ast.Node) (remaining []ast.Node, parent ast.Node, expr ast.Expr) {
+ expr, _ = stack[len(stack)-1].(ast.Expr)
+ if expr == nil {
+ return nil, nil, nil
+ }
+ i := len(stack) - 2
+ for ; i >= 0; i-- {
+ if pexpr, ok := stack[i].(*ast.ParenExpr); ok {
+ expr = pexpr
+ } else {
+ parent = stack[i]
+ break
+ }
+ }
+ if parent == nil {
+ return nil, nil, nil
+ }
+ // inv: i is the index of parent in the stack.
+ return stack[:i], parent, expr
+}
+
+// isSelectionOperand reports whether the innermost node of stack is operand
+// (x) of a selection x.f.
+func isSelectionOperand(stack []ast.Node) bool {
+ _, parent, expr := exprContext(stack)
+ if parent == nil {
+ return false
+ }
+ sel, ok := parent.(*ast.SelectorExpr)
+ return ok && sel.X == expr
+}
+
+// A shadowMap records information about shadowing at any of the parameter's
+// references within the callee decl.
+//
+// For each name shadowed at a reference to the parameter within the callee
+// body, shadow map records the 1-based index of the callee decl parameter
+// causing the shadowing, or -1, if the shadowing is not due to a callee decl.
+// A value of zero (or missing) indicates no shadowing. By convention,
+// self-shadowing is excluded from the map.
+//
+// For example, in the following callee
+//
+// func f(a, b int) int {
+// c := 2 + b
+// return a + c
+// }
+//
+// the shadow map of a is {b: 2, c: -1}, because b is shadowed by the 2nd
+// parameter. The shadow map of b is {a: 1}, because c is not shadowed at the
+// use of b.
+type shadowMap map[string]int
+
+// add returns the [shadowMap] augmented by the set of names
+// locally shadowed at the location of the reference in the callee
+// (identified by the stack). The name of the reference itself is
+// excluded.
+//
+// These shadowed names may not be used in a replacement expression
+// for the reference.
+func (s shadowMap) add(info *types.Info, paramIndexes map[types.Object]int, exclude string, stack []ast.Node) shadowMap {
+ for _, n := range stack {
+ if scope := scopeFor(info, n); scope != nil {
+ for _, name := range scope.Names() {
+ if name != exclude {
+ if s == nil {
+ s = make(shadowMap)
+ }
+ obj := scope.Lookup(name)
+ if idx, ok := paramIndexes[obj]; ok {
+ s[name] = idx + 1
+ } else {
+ s[name] = -1
+ }
+ }
+ }
+ }
+ }
+ return s
+}
+
+// fieldObjs returns a map of each types.Object defined by the given signature
+// to its index in the parameter list. Parameters with missing or blank name
+// are skipped.
+func fieldObjs(sig *types.Signature) map[types.Object]int {
+ m := make(map[types.Object]int)
+ for i := range sig.Params().Len() {
+ if p := sig.Params().At(i); p.Name() != "" && p.Name() != "_" {
+ m[p] = i
+ }
+ }
+ return m
+}
+
+func isField(obj types.Object) bool {
+ if v, ok := obj.(*types.Var); ok && v.IsField() {
+ return true
+ }
+ return false
+}
+
+func isMethod(obj types.Object) bool {
+ if f, ok := obj.(*types.Func); ok && f.Type().(*types.Signature).Recv() != nil {
+ return true
+ }
+ return false
+}
+
+// -- serialization --
+
+var (
+ _ gob.GobEncoder = (*Callee)(nil)
+ _ gob.GobDecoder = (*Callee)(nil)
+)
+
+func (callee *Callee) GobEncode() ([]byte, error) {
+ var out bytes.Buffer
+ if err := gob.NewEncoder(&out).Encode(callee.impl); err != nil {
+ return nil, err
+ }
+ return out.Bytes(), nil
+}
+
+func (callee *Callee) GobDecode(data []byte) error {
+ return gob.NewDecoder(bytes.NewReader(data)).Decode(&callee.impl)
+}
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/calleefx.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/calleefx.go
new file mode 100644
index 00000000000..001bf61e93e
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/calleefx.go
@@ -0,0 +1,349 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+// This file defines the analysis of callee effects.
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/internal/typesinternal"
+)
+
+const (
+ rinf = -1 // R∞: arbitrary read from memory
+ winf = -2 // W∞: arbitrary write to memory (or unknown control)
+)
+
+// calleefx returns a list of parameter indices indicating the order
+// in which parameters are first referenced during evaluation of the
+// callee, relative both to each other and to other effects of the
+// callee (if any), such as arbitrary reads (rinf) and arbitrary
+// effects (winf), including unknown control flow. Each parameter
+// that is referenced appears once in the list.
+//
+// For example, the effects list of this function:
+//
+// func f(x, y, z int) int {
+// return y + x + g() + z
+// }
+//
+// is [1 0 -2 2], indicating reads of y and x, followed by the unknown
+// effects of the g() call, and finally the read of parameter z. This
+// information is used during inlining to ascertain when it is safe
+// for parameter references to be replaced by their corresponding
+// argument expressions. Such substitutions are permitted only when
+// they do not cause "write" operations (those with effects) to
+// commute with "read" operations (those that have no effect but are
+// not pure). Impure operations may be reordered with other impure
+// operations, and pure operations may be reordered arbitrarily.
+//
+// The analysis ignores the effects of runtime panics, on the
+// assumption that well-behaved programs shouldn't encounter them.
+func calleefx(info *types.Info, body *ast.BlockStmt, paramInfos map[*types.Var]*paramInfo) []int {
+ // This traversal analyzes the callee's statements (in syntax
+ // form, though one could do better with SSA) to compute the
+ // sequence of events of the following kinds:
+ //
+ // 1 read of a parameter variable.
+ // 2. reads from other memory.
+ // 3. writes to memory
+
+ var effects []int // indices of parameters, or rinf/winf (-ve)
+ seen := make(map[int]bool)
+ effect := func(i int) {
+ if !seen[i] {
+ seen[i] = true
+ effects = append(effects, i)
+ }
+ }
+
+ // unknown is called for statements of unknown effects (or control).
+ unknown := func() {
+ effect(winf)
+
+ // Ensure that all remaining parameters are "seen"
+ // after we go into the unknown (unless they are
+ // unreferenced by the function body). This lets us
+ // not bother implementing the complete traversal into
+ // control structures.
+ //
+ // TODO(adonovan): add them in a deterministic order.
+ // (This is not a bug but determinism is good.)
+ for _, pinfo := range paramInfos {
+ if !pinfo.IsResult && len(pinfo.Refs) > 0 {
+ effect(pinfo.Index)
+ }
+ }
+ }
+
+ var visitExpr func(n ast.Expr)
+ var visitStmt func(n ast.Stmt) bool
+ visitExpr = func(n ast.Expr) {
+ switch n := n.(type) {
+ case *ast.Ident:
+ if v, ok := info.Uses[n].(*types.Var); ok && !v.IsField() {
+ // Use of global?
+ if v.Parent() == v.Pkg().Scope() {
+ effect(rinf) // read global var
+ }
+
+ // Use of parameter?
+ if pinfo, ok := paramInfos[v]; ok && !pinfo.IsResult {
+ effect(pinfo.Index) // read parameter var
+ }
+
+ // Use of local variables is ok.
+ }
+
+ case *ast.BasicLit:
+ // no effect
+
+ case *ast.FuncLit:
+ // A func literal has no read or write effect
+ // until called, and (most) function calls are
+ // considered to have arbitrary effects.
+ // So, no effect.
+
+ case *ast.CompositeLit:
+ for _, elt := range n.Elts {
+ visitExpr(elt) // note: visits KeyValueExpr
+ }
+
+ case *ast.ParenExpr:
+ visitExpr(n.X)
+
+ case *ast.SelectorExpr:
+ if seln, ok := info.Selections[n]; ok {
+ visitExpr(n.X)
+
+ // See types.SelectionKind for background.
+ switch seln.Kind() {
+ case types.MethodExpr:
+ // A method expression T.f acts like a
+ // reference to a func decl,
+ // so it doesn't read x until called.
+
+ case types.MethodVal, types.FieldVal:
+ // A field or method value selection x.f
+ // reads x if the selection indirects a pointer.
+
+ if indirectSelection(seln) {
+ effect(rinf)
+ }
+ }
+ } else {
+ // qualified identifier: treat like unqualified
+ visitExpr(n.Sel)
+ }
+
+ case *ast.IndexExpr:
+ if tv := info.Types[n.Index]; tv.IsType() {
+ // no effect (G[T] instantiation)
+ } else {
+ visitExpr(n.X)
+ visitExpr(n.Index)
+ switch tv.Type.Underlying().(type) {
+ case *types.Slice, *types.Pointer: // []T, *[n]T (not string, [n]T)
+ effect(rinf) // indirect read of slice/array element
+ }
+ }
+
+ case *ast.IndexListExpr:
+ // no effect (M[K,V] instantiation)
+
+ case *ast.SliceExpr:
+ visitExpr(n.X)
+ visitExpr(n.Low)
+ visitExpr(n.High)
+ visitExpr(n.Max)
+
+ case *ast.TypeAssertExpr:
+ visitExpr(n.X)
+
+ case *ast.CallExpr:
+ if info.Types[n.Fun].IsType() {
+ // conversion T(x)
+ visitExpr(n.Args[0])
+ } else {
+ // call f(args)
+ visitExpr(n.Fun)
+ for i, arg := range n.Args {
+ if i == 0 && info.Types[arg].IsType() {
+ continue // new(T), make(T, n)
+ }
+ visitExpr(arg)
+ }
+
+ // The pure built-ins have no effects beyond
+ // those of their operands (not even memory reads).
+ // All other calls have unknown effects.
+ if !typesinternal.CallsPureBuiltin(info, n) {
+ unknown() // arbitrary effects
+ }
+ }
+
+ case *ast.StarExpr:
+ visitExpr(n.X)
+ effect(rinf) // *ptr load or store depends on state of heap
+
+ case *ast.UnaryExpr: // + - ! ^ & ~ <-
+ visitExpr(n.X)
+ if n.Op == token.ARROW {
+ unknown() // effect: channel receive
+ }
+
+ case *ast.BinaryExpr:
+ visitExpr(n.X)
+ visitExpr(n.Y)
+
+ case *ast.KeyValueExpr:
+ visitExpr(n.Key) // may be a struct field
+ visitExpr(n.Value)
+
+ case *ast.BadExpr:
+ // no effect
+
+ case nil:
+ // optional subtree
+
+ default:
+ // type syntax: unreachable given traversal
+ panic(n)
+ }
+ }
+
+ // visitStmt's result indicates the continuation:
+ // false for return, true for the next statement.
+ //
+ // We could treat return as an unknown, but this way
+ // yields definite effects for simple sequences like
+ // {S1; S2; return}, so unreferenced parameters are
+ // not spuriously added to the effects list, and thus
+ // not spuriously disqualified from elimination.
+ visitStmt = func(n ast.Stmt) bool {
+ switch n := n.(type) {
+ case *ast.DeclStmt:
+ decl := n.Decl.(*ast.GenDecl)
+ for _, spec := range decl.Specs {
+ switch spec := spec.(type) {
+ case *ast.ValueSpec:
+ for _, v := range spec.Values {
+ visitExpr(v)
+ }
+
+ case *ast.TypeSpec:
+ // no effect
+ }
+ }
+
+ case *ast.LabeledStmt:
+ return visitStmt(n.Stmt)
+
+ case *ast.ExprStmt:
+ visitExpr(n.X)
+
+ case *ast.SendStmt:
+ visitExpr(n.Chan)
+ visitExpr(n.Value)
+ unknown() // effect: channel send
+
+ case *ast.IncDecStmt:
+ visitExpr(n.X)
+ unknown() // effect: variable increment
+
+ case *ast.AssignStmt:
+ for _, lhs := range n.Lhs {
+ visitExpr(lhs)
+ }
+ for _, rhs := range n.Rhs {
+ visitExpr(rhs)
+ }
+ for _, lhs := range n.Lhs {
+ id, _ := lhs.(*ast.Ident)
+ if id != nil && id.Name == "_" {
+ continue // blank assign has no effect
+ }
+ if n.Tok == token.DEFINE && id != nil && info.Defs[id] != nil {
+ continue // new var declared by := has no effect
+ }
+ unknown() // assignment to existing var
+ break
+ }
+
+ case *ast.GoStmt:
+ visitExpr(n.Call.Fun)
+ for _, arg := range n.Call.Args {
+ visitExpr(arg)
+ }
+ unknown() // effect: create goroutine
+
+ case *ast.DeferStmt:
+ visitExpr(n.Call.Fun)
+ for _, arg := range n.Call.Args {
+ visitExpr(arg)
+ }
+ unknown() // effect: push defer
+
+ case *ast.ReturnStmt:
+ for _, res := range n.Results {
+ visitExpr(res)
+ }
+ return false
+
+ case *ast.BlockStmt:
+ for _, stmt := range n.List {
+ if !visitStmt(stmt) {
+ return false
+ }
+ }
+
+ case *ast.BranchStmt:
+ unknown() // control flow
+
+ case *ast.IfStmt:
+ visitStmt(n.Init)
+ visitExpr(n.Cond)
+ unknown() // control flow
+
+ case *ast.SwitchStmt:
+ visitStmt(n.Init)
+ visitExpr(n.Tag)
+ unknown() // control flow
+
+ case *ast.TypeSwitchStmt:
+ visitStmt(n.Init)
+ visitStmt(n.Assign)
+ unknown() // control flow
+
+ case *ast.SelectStmt:
+ unknown() // control flow
+
+ case *ast.ForStmt:
+ visitStmt(n.Init)
+ visitExpr(n.Cond)
+ unknown() // control flow
+
+ case *ast.RangeStmt:
+ visitExpr(n.X)
+ unknown() // control flow
+
+ case *ast.EmptyStmt, *ast.BadStmt:
+ // no effect
+
+ case nil:
+ // optional subtree
+
+ default:
+ panic(n)
+ }
+ return true
+ }
+ visitStmt(body)
+
+ return effects
+}
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/doc.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/doc.go
new file mode 100644
index 00000000000..6bb4cef055d
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/doc.go
@@ -0,0 +1,288 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package inline implements inlining of Go function calls.
+
+The client provides information about the caller and callee,
+including the source text, syntax tree, and type information, and
+the inliner returns the modified source file for the caller, or an
+error if the inlining operation is invalid (for example because the
+function body refers to names that are inaccessible to the caller).
+
+Although this interface demands more information from the client
+than might seem necessary, it enables smoother integration with
+existing batch and interactive tools that have their own ways of
+managing the processes of reading, parsing, and type-checking
+packages. In particular, this package does not assume that the
+caller and callee belong to the same token.FileSet or
+types.Importer realms.
+
+There are many aspects to a function call. It is the only construct
+that can simultaneously bind multiple variables of different
+explicit types, with implicit assignment conversions. (Neither var
+nor := declarations can do that.) It defines the scope of control
+labels, of return statements, and of defer statements. Arguments
+and results of function calls may be tuples even though tuples are
+not first-class values in Go, and a tuple-valued call expression
+may be "spread" across the argument list of a call or the operands
+of a return statement. All these unique features mean that in the
+general case, not everything that can be expressed by a function
+call can be expressed without one.
+
+So, in general, inlining consists of modifying a function or method
+call expression f(a1, ..., an) so that the name of the function f
+is replaced ("literalized") by a literal copy of the function
+declaration, with free identifiers suitably modified to use the
+locally appropriate identifiers or perhaps constant argument
+values.
+
+Inlining must not change the semantics of the call. Semantics
+preservation is crucial for clients such as codebase maintenance
+tools that automatically inline all calls to designated functions
+on a large scale. Such tools must not introduce subtle behavior
+changes. (Fully inlining a call is dynamically observable using
+reflection over the call stack, but this exception to the rule is
+explicitly allowed.)
+
+In many cases it is possible to entirely replace ("reduce") the
+call by a copy of the function's body in which parameters have been
+replaced by arguments. The inliner supports a number of reduction
+strategies, and we expect this set to grow. Nonetheless, sound
+reduction is surprisingly tricky.
+
+The inliner is in some ways like an optimizing compiler. A compiler
+is considered correct if it doesn't change the meaning of the
+program in translation from source language to target language. An
+optimizing compiler exploits the particulars of the input to
+generate better code, where "better" usually means more efficient.
+When a case is found in which it emits suboptimal code, the
+compiler is improved to recognize more cases, or more rules, and
+more exceptions to rules; this process has no end. Inlining is
+similar except that "better" code means tidier code. The baseline
+translation (literalization) is correct, but there are endless
+rules--and exceptions to rules--by which the output can be
+improved.
+
+The following section lists some of the challenges, and ways in
+which they can be addressed.
+
+ - All effects of the call argument expressions must be preserved,
+ both in their number (they must not be eliminated or repeated),
+ and in their order (both with respect to other arguments, and any
+ effects in the callee function).
+
+ This must be the case even if the corresponding parameters are
+ never referenced, are referenced multiple times, referenced in
+ a different order from the arguments, or referenced within a
+ nested function that may be executed an arbitrary number of
+ times.
+
+ Currently, parameter replacement is not applied to arguments
+ with effects, but with further analysis of the sequence of
+ strict effects within the callee we could relax this constraint.
+
+ - When not all parameters can be substituted by their arguments
+ (e.g. due to possible effects), if the call appears in a
+ statement context, the inliner may introduce a var declaration
+ that declares the parameter variables (with the correct types)
+ and assigns them to their corresponding argument values.
+ The rest of the function body may then follow.
+ For example, the call
+
+ f(1, 2)
+
+ to the function
+
+ func f(x, y int32) { stmts }
+
+ may be reduced to
+
+ { var x, y int32 = 1, 2; stmts }.
+
+ There are many reasons why this is not always possible. For
+ example, true parameters are statically resolved in the same
+ scope, and are dynamically assigned their arguments in
+ parallel; but each spec in a var declaration is statically
+ resolved in sequence and dynamically executed in sequence, so
+ earlier parameters may shadow references in later ones.
+
+ - Even an argument expression as simple as ptr.x may not be
+ referentially transparent, because another argument may have the
+ effect of changing the value of ptr.
+
+ This constraint could be relaxed by some kind of alias or
+ escape analysis that proves that ptr cannot be mutated during
+ the call.
+
+ - Although constants are referentially transparent, as a matter of
+ style we do not wish to duplicate literals that are referenced
+ multiple times in the body because this undoes proper factoring.
+ Also, string literals may be arbitrarily large.
+
+ - If the function body consists of statements other than just
+ "return expr", in some contexts it may be syntactically
+ impossible to reduce the call. Consider:
+
+ if x := f(); cond { ... }
+
+ Go has no equivalent to Lisp's progn or Rust's blocks,
+ nor ML's let expressions (let param = arg in body);
+ its closest equivalent is func(param){body}(arg).
+ Reduction strategies must therefore consider the syntactic
+ context of the call.
+
+ In such situations we could work harder to extract a statement
+ context for the call, by transforming it to:
+
+ { x := f(); if cond { ... } }
+
+ - Similarly, without the equivalent of Rust-style blocks and
+ first-class tuples, there is no general way to reduce a call
+ to a function such as
+
+ func(params)(args)(results) { stmts; return expr }
+
+ to an expression such as
+
+ { var params = args; stmts; expr }
+
+ or even a statement such as
+
+ results = { var params = args; stmts; expr }
+
+ Consequently the declaration and scope of the result variables,
+ and the assignment and control-flow implications of the return
+ statement, must be dealt with by cases.
+
+ - A standalone call statement that calls a function whose body is
+ "return expr" cannot be simply replaced by the body expression
+ if it is not itself a call or channel receive expression; it is
+ necessary to explicitly discard the result using "_ = expr".
+
+ Similarly, if the body is a call expression, only calls to some
+ built-in functions with no result (such as copy or panic) are
+ permitted as statements, whereas others (such as append) return
+ a result that must be used, even if just by discarding.
+
+ - If a parameter or result variable is updated by an assignment
+ within the function body, it cannot always be safely replaced
+ by a variable in the caller. For example, given
+
+ func f(a int) int { a++; return a }
+
+ The call y = f(x) cannot be replaced by { x++; y = x } because
+ this would change the value of the caller's variable x.
+ Only if the caller is finished with x is this safe.
+
+ A similar argument applies to parameter or result variables
+ that escape: by eliminating a variable, inlining would change
+ the identity of the variable that escapes.
+
+ - If the function body uses 'defer' and the inlined call is not a
+ tail-call, inlining may delay the deferred effects.
+
+ - Because the scope of a control label is the entire function, a
+ call cannot be reduced if the caller and callee have intersecting
+ sets of control labels. (It is possible to α-rename any
+ conflicting ones, but our colleagues building C++ refactoring
+ tools report that, when tools must choose new identifiers, they
+ generally do a poor job.)
+
+ - Given
+
+ func f() uint8 { return 0 }
+
+ var x any = f()
+
+ reducing the call to var x any = 0 is unsound because it
+ discards the implicit conversion to uint8. We may need to make
+ each argument-to-parameter conversion explicit if the types
+ differ. Assignments to variadic parameters may need to
+ explicitly construct a slice.
+
+ An analogous problem applies to the implicit assignments in
+ return statements:
+
+ func g() any { return f() }
+
+ Replacing the call f() with 0 would silently lose a
+ conversion to uint8 and change the behavior of the program.
+
+ - When inlining a call f(1, x, g()) where those parameters are
+ unreferenced, we should be able to avoid evaluating 1 and x
+ since they are pure and thus have no effect. But x may be the
+ last reference to a local variable in the caller, so removing
+ it would cause a compilation error. Parameter substitution must
+ avoid making the caller's local variables unreferenced (or must
+ be prepared to eliminate the declaration too---this is where an
+ iterative framework for simplification would really help).
+
+ - An expression such as s[i] may be valid if s and i are
+ variables but invalid if either or both of them are constants.
+ For example, a negative constant index s[-1] is always out of
+ bounds, and even a non-negative constant index may be out of
+ bounds depending on the particular string constant (e.g.
+ "abc"[4]).
+
+ So, if a parameter participates in any expression that is
+ subject to additional compile-time checks when its operands are
+ constant, it may be unsafe to substitute that parameter by a
+ constant argument value (#62664).
+
+More complex callee functions are inlinable with more elaborate and
+invasive changes to the statements surrounding the call expression.
+
+TODO(adonovan): future work:
+
+ - Handle more of the above special cases by careful analysis,
+ thoughtful factoring of the large design space, and thorough
+ test coverage.
+
+ - Compute precisely (not conservatively) when parameter
+ substitution would remove the last reference to a caller local
+ variable, and blank out the local instead of retreating from
+ the substitution.
+
+ - Afford the client more control such as a limit on the total
+ increase in line count, or a refusal to inline using the
+ general approach (replacing name by function literal). This
+ could be achieved by returning metadata alongside the result
+ and having the client conditionally discard the change.
+
+ - Support inlining of generic functions, replacing type parameters
+ by their instantiations.
+
+ - Support inlining of calls to function literals ("closures").
+ But note that the existing algorithm makes widespread assumptions
+ that the callee is a package-level function or method.
+
+ - Eliminate explicit conversions of "untyped" literals inserted
+ conservatively when they are redundant. For example, the
+ conversion int32(1) is redundant when this value is used only as a
+ slice index; but it may be crucial if it is used in x := int32(1)
+ as it changes the type of x, which may have further implications.
+ The conversions may also be important to the falcon analysis.
+
+ - Allow non-'go' build systems such as Bazel/Blaze a chance to
+ decide whether an import is accessible using logic other than
+ "/internal/" path segments. This could be achieved by returning
+ the list of added import paths instead of a text diff.
+
+ - Inlining a function from another module may change the
+ effective version of the Go language spec that governs it. We
+ should probably make the client responsible for rejecting
+ attempts to inline from newer callees to older callers, since
+ there's no way for this package to access module versions.
+
+ - Use an alternative implementation of the import-organizing
+ operation that doesn't require operating on a complete file
+ (and reformatting). Then return the results in a higher-level
+ form as a set of import additions and deletions plus a single
+ diff that encloses the call expression. This interface could
+ perhaps be implemented atop imports.Process by post-processing
+ its result to obtain the abstract import changes and discarding
+ its formatted output.
+*/
+package inline
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/escape.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/escape.go
new file mode 100644
index 00000000000..45cce11a9e2
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/escape.go
@@ -0,0 +1,102 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+)
+
+// escape implements a simple "address-taken" escape analysis. It
+// calls f for each local variable that appears on the left side of an
+// assignment (escapes=false) or has its address taken (escapes=true).
+// The initialization of a variable by its declaration does not count
+// as an assignment.
+func escape(info *types.Info, root ast.Node, f func(v *types.Var, escapes bool)) {
+
+ // lvalue is called for each address-taken expression or LHS of assignment.
+ // Supported forms are: x, (x), x[i], x.f, *x, T{}.
+ var lvalue func(e ast.Expr, escapes bool)
+ lvalue = func(e ast.Expr, escapes bool) {
+ switch e := e.(type) {
+ case *ast.Ident:
+ if v, ok := info.Uses[e].(*types.Var); ok {
+ if !isPkgLevel(v) {
+ f(v, escapes)
+ }
+ }
+ case *ast.ParenExpr:
+ lvalue(e.X, escapes)
+ case *ast.IndexExpr:
+ // TODO(adonovan): support generics without assuming e.X has a core type.
+ // Consider:
+ //
+ // func Index[T interface{ [3]int | []int }](t T, i int) *int {
+ // return &t[i]
+ // }
+ //
+ // We must traverse the normal terms and check
+ // whether any of them is an array.
+ //
+ // We assume TypeOf returns non-nil.
+ if _, ok := info.TypeOf(e.X).Underlying().(*types.Array); ok {
+ lvalue(e.X, escapes) // &a[i] on array
+ }
+ case *ast.SelectorExpr:
+ // We assume TypeOf returns non-nil.
+ if _, ok := info.TypeOf(e.X).Underlying().(*types.Struct); ok {
+ lvalue(e.X, escapes) // &s.f on struct
+ }
+ case *ast.StarExpr:
+ // *ptr indirects an existing pointer
+ case *ast.CompositeLit:
+ // &T{...} creates a new variable
+ default:
+ panic(fmt.Sprintf("&x on %T", e)) // unreachable in well-typed code
+ }
+ }
+
+ // Search function body for operations &x, x.f(), x++, and x = y
+ // where x is a parameter. Each of these treats x as an address.
+ ast.Inspect(root, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.UnaryExpr:
+ if n.Op == token.AND {
+ lvalue(n.X, true) // &x
+ }
+
+ case *ast.CallExpr:
+ // implicit &x in method call x.f(),
+ // where x has type T and method is (*T).f
+ if sel, ok := n.Fun.(*ast.SelectorExpr); ok {
+ if seln, ok := info.Selections[sel]; ok &&
+ seln.Kind() == types.MethodVal &&
+ isPointer(seln.Obj().Type().Underlying().(*types.Signature).Recv().Type()) {
+ tArg, indirect := effectiveReceiver(seln)
+ if !indirect && !isPointer(tArg) {
+ lvalue(sel.X, true) // &x.f
+ }
+ }
+ }
+
+ case *ast.AssignStmt:
+ for _, lhs := range n.Lhs {
+ if id, ok := lhs.(*ast.Ident); ok &&
+ info.Defs[id] != nil &&
+ n.Tok == token.DEFINE {
+ // declaration: doesn't count
+ } else {
+ lvalue(lhs, false)
+ }
+ }
+
+ case *ast.IncDecStmt:
+ lvalue(n.X, false)
+ }
+ return true
+ })
+}
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/falcon.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/falcon.go
new file mode 100644
index 00000000000..037d33bd5a2
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/falcon.go
@@ -0,0 +1,879 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+// This file defines the callee side of the "fallible constant" analysis.
+
+import (
+ "fmt"
+ "go/ast"
+ "go/constant"
+ "go/format"
+ "go/token"
+ "go/types"
+ "strconv"
+ "strings"
+
+ "golang.org/x/tools/go/types/typeutil"
+ "golang.org/x/tools/internal/typeparams"
+)
+
+// falconResult is the result of the analysis of the callee.
+type falconResult struct {
+ Types []falconType // types for falcon constraint environment
+ Constraints []string // constraints (Go expressions) on values of fallible constants
+}
+
+// A falconType specifies the name and underlying type of a synthetic
+// defined type for use in falcon constraints.
+//
+// Unique types from callee code are bijectively mapped onto falcon
+// types so that constraints are independent of callee type
+// information but preserve type equivalence classes.
+//
+// Fresh names are deliberately obscure to avoid shadowing even if a
+// callee parameter has a name like "int" or "any".
+type falconType struct {
+ Name string
+ Kind types.BasicKind // string/number/bool
+}
+
+// falcon identifies "fallible constant" expressions, which are
+// expressions that may fail to compile if one or more of their
+// operands is changed from non-constant to constant.
+//
+// Consider:
+//
+// func sub(s string, i, j int) string { return s[i:j] }
+//
+// If parameters are replaced by constants, the compiler is
+// required to perform these additional checks:
+//
+// - if i is constant, 0 <= i.
+// - if s and i are constant, i <= len(s).
+// - ditto for j.
+// - if i and j are constant, i <= j.
+//
+// s[i:j] is thus a "fallible constant" expression dependent on {s, i,
+// j}. Each falcon creates a set of conditional constraints across one
+// or more parameter variables.
+//
+// - When inlining a call such as sub("abc", -1, 2), the parameter i
+// cannot be eliminated by substitution as its argument value is
+// negative.
+//
+// - When inlining sub("", 2, 1), all three parameters cannot be
+// simultaneously eliminated by substitution without violating i
+// <= len(s) and j <= len(s), but the parameters i and j could be
+// safely eliminated without s.
+//
+// Parameters that cannot be eliminated must remain non-constant,
+// either in the form of a binding declaration:
+//
+// { var i int = -1; return "abc"[i:2] }
+//
+// or a parameter of a literalization:
+//
+// func (i int) string { return "abc"[i:2] }(-1)
+//
+// These example expressions are obviously doomed to fail at run
+// time, but in realistic cases such expressions are dominated by
+// appropriate conditions that make them reachable only when safe:
+//
+// if 0 <= i && i <= j && j <= len(s) { _ = s[i:j] }
+//
+// (In principle a more sophisticated inliner could entirely eliminate
+// such unreachable blocks based on the condition being always-false
+// for the given parameter substitution, but this is tricky to do safely
+// because the type-checker considers only a single configuration.
+// Consider: if runtime.GOOS == "linux" { ... }.)
+//
+// We believe this is an exhaustive list of "fallible constant" operations:
+//
+// - switch z { case x: case y } // duplicate case values
+// - s[i], s[i:j], s[i:j:k] // index out of bounds (0 <= i <= j <= k <= len(s))
+// - T{x: 0} // index out of bounds, duplicate index
+// - x/y, x%y, x/=y, x%=y // integer division by zero; minint/-1 overflow
+// - x+y, x-y, x*y // arithmetic overflow
+// - x< 1 {
+ var elts []ast.Expr
+ for _, elem := range elems {
+ elts = append(elts, &ast.KeyValueExpr{
+ Key: elem,
+ Value: makeIntLit(0),
+ })
+ }
+ st.emit(&ast.CompositeLit{
+ Type: typ,
+ Elts: elts,
+ })
+ }
+}
+
+// -- traversal --
+
+// The traversal functions scan the callee body for expressions that
+// are not constant but would become constant if the parameter vars
+// were redeclared as constants, and emits for each one a constraint
+// (a Go expression) with the property that it will not type-check
+// (using types.CheckExpr) if the particular argument values are
+// unsuitable.
+//
+// These constraints are checked by Inline with the actual
+// constant argument values. Violations cause it to reject
+// parameters as candidates for substitution.
+
+func (st *falconState) stmt(s ast.Stmt) {
+ ast.Inspect(s, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case ast.Expr:
+ _ = st.expr(n)
+ return false // skip usual traversal
+
+ case *ast.AssignStmt:
+ switch n.Tok {
+ case token.QUO_ASSIGN, token.REM_ASSIGN:
+ // x /= y
+ // Possible "integer division by zero"
+ // Emit constraint: 1/y.
+ _ = st.expr(n.Lhs[0])
+ kY := st.expr(n.Rhs[0])
+ if kY, ok := kY.(ast.Expr); ok {
+ op := token.QUO
+ if n.Tok == token.REM_ASSIGN {
+ op = token.REM
+ }
+ st.emit(&ast.BinaryExpr{
+ Op: op,
+ X: makeIntLit(1),
+ Y: kY,
+ })
+ }
+ return false // skip usual traversal
+ }
+
+ case *ast.SwitchStmt:
+ if n.Init != nil {
+ st.stmt(n.Init)
+ }
+ tBool := types.Type(types.Typ[types.Bool])
+ tagType := tBool // default: true
+ if n.Tag != nil {
+ st.expr(n.Tag)
+ tagType = st.info.TypeOf(n.Tag)
+ }
+
+ // Possible "duplicate case value".
+ // Emit constraint map[T]int{v1: 0, ..., vN:0}
+ // to ensure all maybe-constant case values are unique
+ // (unless switch tag is boolean, which is relaxed).
+ var unique []ast.Expr
+ for _, clause := range n.Body.List {
+ clause := clause.(*ast.CaseClause)
+ for _, caseval := range clause.List {
+ if k := st.expr(caseval); k != nil {
+ unique = append(unique, st.toExpr(k))
+ }
+ }
+ for _, stmt := range clause.Body {
+ st.stmt(stmt)
+ }
+ }
+ if unique != nil && !types.Identical(tagType.Underlying(), tBool) {
+ tname := st.any
+ if !types.IsInterface(tagType) {
+ tname = st.typename(tagType)
+ }
+ t := &ast.MapType{
+ Key: makeIdent(tname),
+ Value: makeIdent(st.int),
+ }
+ st.emitUnique(t, unique)
+ }
+ }
+ return true
+ })
+}
+
+// fieldTypes visits the .Type of each field in the list.
+func (st *falconState) fieldTypes(fields *ast.FieldList) {
+ if fields != nil {
+ for _, field := range fields.List {
+ _ = st.expr(field.Type)
+ }
+ }
+}
+
+// expr visits the expression (or type) and returns a
+// non-nil result if the expression is constant or would
+// become constant if all suitable function parameters were
+// redeclared as constants.
+//
+// If the expression is constant, st.expr returns its type
+// and value (types.TypeAndValue). If the expression would
+// become constant, st.expr returns an ast.Expr tree whose
+// leaves are literals and parameter references, and whose
+// interior nodes are operations that may become constant,
+// such as -x, x+y, f(x), and T(x). We call these would-be
+// constant expressions "fallible constants", since they may
+// fail to type-check for some values of x, i, and j. (We
+// refer to the non-nil cases collectively as "maybe
+// constant", and the nil case as "definitely non-constant".)
+//
+// As a side effect, st.expr emits constraints for each
+// fallible constant expression; this is its main purpose.
+//
+// Consequently, st.expr must visit the entire subtree so
+// that all necessary constraints are emitted. It may not
+// short-circuit the traversal when it encounters a constant
+// subexpression as constants may contain arbitrary other
+// syntax that may impose constraints. Consider (as always)
+// this contrived but legal example of a type parameter (!)
+// that contains statement syntax:
+//
+// func f[T [unsafe.Sizeof(func() { stmts })]int]()
+//
+// There is no need to emit constraints for (e.g.) s[i] when s
+// and i are already constants, because we know the expression
+// is sound, but it is sometimes easier to emit these
+// redundant constraints than to avoid them.
+func (st *falconState) expr(e ast.Expr) (res any) { // = types.TypeAndValue | ast.Expr
+ tv := st.info.Types[e]
+ if tv.Value != nil {
+ // A constant value overrides any other result.
+ defer func() { res = tv }()
+ }
+
+ switch e := e.(type) {
+ case *ast.Ident:
+ if v, ok := st.info.Uses[e].(*types.Var); ok {
+ if _, ok := st.params[v]; ok && isBasic(v.Type(), types.IsConstType) {
+ return e // reference to constable parameter
+ }
+ }
+ // (References to *types.Const are handled by the defer.)
+
+ case *ast.BasicLit:
+ // constant
+
+ case *ast.ParenExpr:
+ return st.expr(e.X)
+
+ case *ast.FuncLit:
+ _ = st.expr(e.Type)
+ st.stmt(e.Body)
+ // definitely non-constant
+
+ case *ast.CompositeLit:
+ // T{k: v, ...}, where T ∈ {array,*array,slice,map},
+ // imposes a constraint that all constant k are
+ // distinct and, for arrays [n]T, within range 0-n.
+ //
+ // Types matter, not just values. For example,
+ // an interface-keyed map may contain keys
+ // that are numerically equal so long as they
+ // are of distinct types. For example:
+ //
+ // type myint int
+ // map[any]bool{1: true, 1: true} // error: duplicate key
+ // map[any]bool{1: true, int16(1): true} // ok
+ // map[any]bool{1: true, myint(1): true} // ok
+ //
+ // This can be asserted by emitting a
+ // constraint of the form T{k1: 0, ..., kN: 0}.
+ if e.Type != nil {
+ _ = st.expr(e.Type)
+ }
+ t := types.Unalias(typeparams.Deref(tv.Type))
+ ct := typeparams.CoreType(t)
+ var mapKeys []ast.Expr // map key expressions; must be distinct if constant
+ for _, elt := range e.Elts {
+ if kv, ok := elt.(*ast.KeyValueExpr); ok {
+ if is[*types.Map](ct) {
+ if k := st.expr(kv.Key); k != nil {
+ mapKeys = append(mapKeys, st.toExpr(k))
+ }
+ }
+ _ = st.expr(kv.Value)
+ } else {
+ _ = st.expr(elt)
+ }
+ }
+ if len(mapKeys) > 0 {
+ // Inlining a map literal may replace variable key expressions by constants.
+ // All such constants must have distinct values.
+ // (Array and slice literals do not permit non-constant keys.)
+ t := ct.(*types.Map)
+ var typ ast.Expr
+ if types.IsInterface(t.Key()) {
+ typ = &ast.MapType{
+ Key: makeIdent(st.any),
+ Value: makeIdent(st.int),
+ }
+ } else {
+ typ = &ast.MapType{
+ Key: makeIdent(st.typename(t.Key())),
+ Value: makeIdent(st.int),
+ }
+ }
+ st.emitUnique(typ, mapKeys)
+ }
+ // definitely non-constant
+
+ case *ast.SelectorExpr:
+ _ = st.expr(e.X)
+ _ = st.expr(e.Sel)
+ // The defer is sufficient to handle
+ // qualified identifiers (pkg.Const).
+ // All other cases are definitely non-constant.
+
+ case *ast.IndexExpr:
+ if tv.IsType() {
+ // type C[T]
+ _ = st.expr(e.X)
+ _ = st.expr(e.Index)
+ } else {
+ // term x[i]
+ //
+ // Constraints (if x is slice/string/array/*array, not map):
+ // - i >= 0
+ // if i is a fallible constant
+ // - i < len(x)
+ // if x is array/*array and
+ // i is a fallible constant;
+ // or if s is a string and both i,
+ // s are maybe-constants,
+ // but not both are constants.
+ kX := st.expr(e.X)
+ kI := st.expr(e.Index)
+ if kI != nil && !is[*types.Map](st.info.TypeOf(e.X).Underlying()) {
+ if kI, ok := kI.(ast.Expr); ok {
+ st.emitNonNegative(kI)
+ }
+ // Emit constraint to check indices against known length.
+ // TODO(adonovan): factor with SliceExpr logic.
+ var x ast.Expr
+ if kX != nil {
+ // string
+ x = st.toExpr(kX)
+ } else if arr, ok := typeparams.CoreType(typeparams.Deref(st.info.TypeOf(e.X))).(*types.Array); ok {
+ // array, *array
+ x = &ast.CompositeLit{
+ Type: &ast.ArrayType{
+ Len: makeIntLit(arr.Len()),
+ Elt: makeIdent(st.int),
+ },
+ }
+ }
+ if x != nil {
+ st.emit(&ast.IndexExpr{
+ X: x,
+ Index: st.toExpr(kI),
+ })
+ }
+ }
+ }
+ // definitely non-constant
+
+ case *ast.SliceExpr:
+ // x[low:high:max]
+ //
+ // Emit non-negative constraints for each index,
+ // plus low <= high <= max <= len(x)
+ // for each pair that are maybe-constant
+ // but not definitely constant.
+
+ kX := st.expr(e.X)
+ var kLow, kHigh, kMax any
+ if e.Low != nil {
+ kLow = st.expr(e.Low)
+ if kLow != nil {
+ if kLow, ok := kLow.(ast.Expr); ok {
+ st.emitNonNegative(kLow)
+ }
+ }
+ }
+ if e.High != nil {
+ kHigh = st.expr(e.High)
+ if kHigh != nil {
+ if kHigh, ok := kHigh.(ast.Expr); ok {
+ st.emitNonNegative(kHigh)
+ }
+ if kLow != nil {
+ st.emitMonotonic(st.toExpr(kLow), st.toExpr(kHigh))
+ }
+ }
+ }
+ if e.Max != nil {
+ kMax = st.expr(e.Max)
+ if kMax != nil {
+ if kMax, ok := kMax.(ast.Expr); ok {
+ st.emitNonNegative(kMax)
+ }
+ if kHigh != nil {
+ st.emitMonotonic(st.toExpr(kHigh), st.toExpr(kMax))
+ }
+ }
+ }
+
+ // Emit constraint to check indices against known length.
+ var x ast.Expr
+ if kX != nil {
+ // string
+ x = st.toExpr(kX)
+ } else if arr, ok := typeparams.CoreType(typeparams.Deref(st.info.TypeOf(e.X))).(*types.Array); ok {
+ // array, *array
+ x = &ast.CompositeLit{
+ Type: &ast.ArrayType{
+ Len: makeIntLit(arr.Len()),
+ Elt: makeIdent(st.int),
+ },
+ }
+ }
+ if x != nil {
+ // Avoid slice[::max] if kHigh is nonconstant (nil).
+ high, max := st.toExpr(kHigh), st.toExpr(kMax)
+ if high == nil {
+ high = max // => slice[:max:max]
+ }
+ st.emit(&ast.SliceExpr{
+ X: x,
+ Low: st.toExpr(kLow),
+ High: high,
+ Max: max,
+ })
+ }
+ // definitely non-constant
+
+ case *ast.TypeAssertExpr:
+ _ = st.expr(e.X)
+ if e.Type != nil {
+ _ = st.expr(e.Type)
+ }
+
+ case *ast.CallExpr:
+ _ = st.expr(e.Fun)
+ if tv, ok := st.info.Types[e.Fun]; ok && tv.IsType() {
+ // conversion T(x)
+ //
+ // Possible "value out of range".
+ kX := st.expr(e.Args[0])
+ if kX != nil && isBasic(tv.Type, types.IsConstType) {
+ conv := convert(makeIdent(st.typename(tv.Type)), st.toExpr(kX))
+ if is[ast.Expr](kX) {
+ st.emit(conv)
+ }
+ return conv
+ }
+ return nil // definitely non-constant
+ }
+
+ // call f(x)
+
+ all := true // all args are possibly-constant
+ kArgs := make([]ast.Expr, len(e.Args))
+ for i, arg := range e.Args {
+ if kArg := st.expr(arg); kArg != nil {
+ kArgs[i] = st.toExpr(kArg)
+ } else {
+ all = false
+ }
+ }
+
+ // Calls to built-ins with fallibly constant arguments
+ // may become constant. All other calls are either
+ // constant or non-constant
+ if id, ok := e.Fun.(*ast.Ident); ok && all && tv.Value == nil {
+ if builtin, ok := st.info.Uses[id].(*types.Builtin); ok {
+ switch builtin.Name() {
+ case "len", "imag", "real", "complex", "min", "max":
+ return &ast.CallExpr{
+ Fun: id,
+ Args: kArgs,
+ Ellipsis: e.Ellipsis,
+ }
+ }
+ }
+ }
+
+ case *ast.StarExpr: // *T, *ptr
+ _ = st.expr(e.X)
+
+ case *ast.UnaryExpr:
+ // + - ! ^ & <- ~
+ //
+ // Possible "negation of minint".
+ // Emit constraint: -x
+ kX := st.expr(e.X)
+ if kX != nil && !is[types.TypeAndValue](kX) {
+ if e.Op == token.SUB {
+ st.emit(&ast.UnaryExpr{
+ Op: e.Op,
+ X: st.toExpr(kX),
+ })
+ }
+
+ return &ast.UnaryExpr{
+ Op: e.Op,
+ X: st.toExpr(kX),
+ }
+ }
+
+ case *ast.BinaryExpr:
+ kX := st.expr(e.X)
+ kY := st.expr(e.Y)
+ switch e.Op {
+ case token.QUO, token.REM:
+ // x/y, x%y
+ //
+ // Possible "integer division by zero" or
+ // "minint / -1" overflow.
+ // Emit constraint: x/y or 1/y
+ if kY != nil {
+ if kX == nil {
+ kX = makeIntLit(1)
+ }
+ st.emit(&ast.BinaryExpr{
+ Op: e.Op,
+ X: st.toExpr(kX),
+ Y: st.toExpr(kY),
+ })
+ }
+
+ case token.ADD, token.SUB, token.MUL:
+ // x+y, x-y, x*y
+ //
+ // Possible "arithmetic overflow".
+ // Emit constraint: x+y
+ if kX != nil && kY != nil {
+ st.emit(&ast.BinaryExpr{
+ Op: e.Op,
+ X: st.toExpr(kX),
+ Y: st.toExpr(kY),
+ })
+ }
+
+ case token.SHL, token.SHR:
+ // x << y, x >> y
+ //
+ // Possible "constant shift too large".
+ // Either operand may be too large individually,
+ // and they may be too large together.
+ // Emit constraint:
+ // x << y (if both maybe-constant)
+ // x << 0 (if y is non-constant)
+ // 1 << y (if x is non-constant)
+ if kX != nil || kY != nil {
+ x := st.toExpr(kX)
+ if x == nil {
+ x = makeIntLit(1)
+ }
+ y := st.toExpr(kY)
+ if y == nil {
+ y = makeIntLit(0)
+ }
+ st.emit(&ast.BinaryExpr{
+ Op: e.Op,
+ X: x,
+ Y: y,
+ })
+ }
+
+ case token.LSS, token.GTR, token.EQL, token.NEQ, token.LEQ, token.GEQ:
+ // < > == != <= <=
+ //
+ // A "x cmp y" expression with constant operands x, y is
+ // itself constant, but I can't see how a constant bool
+ // could be fallible: the compiler doesn't reject duplicate
+ // boolean cases in a switch, presumably because boolean
+ // switches are less like n-way branches and more like
+ // sequential if-else chains with possibly overlapping
+ // conditions; and there is (sadly) no way to convert a
+ // boolean constant to an int constant.
+ }
+ if kX != nil && kY != nil {
+ return &ast.BinaryExpr{
+ Op: e.Op,
+ X: st.toExpr(kX),
+ Y: st.toExpr(kY),
+ }
+ }
+
+ // types
+ //
+ // We need to visit types (and even type parameters)
+ // in order to reach all the places where things could go wrong:
+ //
+ // const (
+ // s = ""
+ // i = 0
+ // )
+ // type C[T [unsafe.Sizeof(func() { _ = s[i] })]int] bool
+
+ case *ast.IndexListExpr:
+ _ = st.expr(e.X)
+ for _, expr := range e.Indices {
+ _ = st.expr(expr)
+ }
+
+ case *ast.Ellipsis:
+ if e.Elt != nil {
+ _ = st.expr(e.Elt)
+ }
+
+ case *ast.ArrayType:
+ if e.Len != nil {
+ _ = st.expr(e.Len)
+ }
+ _ = st.expr(e.Elt)
+
+ case *ast.StructType:
+ st.fieldTypes(e.Fields)
+
+ case *ast.FuncType:
+ st.fieldTypes(e.TypeParams)
+ st.fieldTypes(e.Params)
+ st.fieldTypes(e.Results)
+
+ case *ast.InterfaceType:
+ st.fieldTypes(e.Methods)
+
+ case *ast.MapType:
+ _ = st.expr(e.Key)
+ _ = st.expr(e.Value)
+
+ case *ast.ChanType:
+ _ = st.expr(e.Value)
+ }
+ return
+}
+
+// toExpr converts the result of visitExpr to a falcon expression.
+// (We don't do this in visitExpr as we first need to discriminate
+// constants from maybe-constants.)
+func (st *falconState) toExpr(x any) ast.Expr {
+ switch x := x.(type) {
+ case nil:
+ return nil
+
+ case types.TypeAndValue:
+ lit := makeLiteral(x.Value)
+ if !isBasic(x.Type, types.IsUntyped) {
+ // convert to "typed" type
+ lit = &ast.CallExpr{
+ Fun: makeIdent(st.typename(x.Type)),
+ Args: []ast.Expr{lit},
+ }
+ }
+ return lit
+
+ case ast.Expr:
+ return x
+
+ default:
+ panic(x)
+ }
+}
+
+func makeLiteral(v constant.Value) ast.Expr {
+ switch v.Kind() {
+ case constant.Bool:
+ // Rather than refer to the true or false built-ins,
+ // which could be shadowed by poorly chosen parameter
+ // names, we use 0 == 0 for true and 0 != 0 for false.
+ op := token.EQL
+ if !constant.BoolVal(v) {
+ op = token.NEQ
+ }
+ return &ast.BinaryExpr{
+ Op: op,
+ X: makeIntLit(0),
+ Y: makeIntLit(0),
+ }
+
+ case constant.String:
+ return &ast.BasicLit{
+ Kind: token.STRING,
+ Value: v.ExactString(),
+ }
+
+ case constant.Int:
+ return &ast.BasicLit{
+ Kind: token.INT,
+ Value: v.ExactString(),
+ }
+
+ case constant.Float:
+ return &ast.BasicLit{
+ Kind: token.FLOAT,
+ Value: v.ExactString(),
+ }
+
+ case constant.Complex:
+ // The components could be float or int.
+ y := makeLiteral(constant.Imag(v))
+ y.(*ast.BasicLit).Value += "i" // ugh
+ if re := constant.Real(v); !consteq(re, kZeroInt) {
+ // complex: x + yi
+ y = &ast.BinaryExpr{
+ Op: token.ADD,
+ X: makeLiteral(re),
+ Y: y,
+ }
+ }
+ return y
+
+ default:
+ panic(v.Kind())
+ }
+}
+
+func makeIntLit(x int64) *ast.BasicLit {
+ return &ast.BasicLit{
+ Kind: token.INT,
+ Value: strconv.FormatInt(x, 10),
+ }
+}
+
+func isBasic(t types.Type, info types.BasicInfo) bool {
+ basic, ok := t.Underlying().(*types.Basic)
+ return ok && basic.Info()&info != 0
+}
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/inline.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/inline.go
new file mode 100644
index 00000000000..6a31d3bdd71
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/inline.go
@@ -0,0 +1,3546 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/constant"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "go/types"
+ "maps"
+ pathpkg "path"
+ "reflect"
+ "slices"
+ "strings"
+
+ "golang.org/x/tools/go/ast/astutil"
+ "golang.org/x/tools/go/types/typeutil"
+ internalastutil "golang.org/x/tools/internal/astutil"
+ "golang.org/x/tools/internal/astutil/free"
+ "golang.org/x/tools/internal/packagepath"
+ "golang.org/x/tools/internal/refactor"
+ "golang.org/x/tools/internal/typeparams"
+ "golang.org/x/tools/internal/typesinternal"
+ "golang.org/x/tools/internal/versions"
+)
+
+// A Caller describes the function call and its enclosing context.
+//
+// The client is responsible for populating this struct and passing it to Inline.
+type Caller struct {
+ Fset *token.FileSet
+ Types *types.Package
+ Info *types.Info
+ File *ast.File
+ Call *ast.CallExpr
+
+ // CountUses is an optional optimized computation of
+ // the number of times pkgname appears in Info.Uses.
+ CountUses func(pkgname *types.PkgName) int
+
+ path []ast.Node // path from call to root of file syntax tree
+ enclosingFunc *ast.FuncDecl // top-level function/method enclosing the call, if any
+}
+
+type logger = func(string, ...any)
+
+// Options specifies parameters affecting the inliner algorithm.
+// All fields are optional.
+type Options struct {
+ Logf logger // log output function, records decision-making process
+ IgnoreEffects bool // ignore potential side effects of arguments (unsound)
+}
+
+// Result holds the result of code transformation.
+type Result struct {
+ Edits []refactor.Edit // edits around CallExpr and imports
+ Literalized bool // chosen strategy replaced callee() with func(){...}()
+ BindingDecl bool // transformation added "var params = args" declaration
+}
+
+// Inline inlines the called function (callee) into the function call (caller)
+// and returns the updated, formatted content of the caller source file.
+//
+// Inline does not mutate any public fields of Caller or Callee.
+func Inline(caller *Caller, callee *Callee, opts *Options) (*Result, error) {
+ copy := *opts // shallow copy
+ opts = ©
+ // Set default options.
+ if opts.Logf == nil {
+ opts.Logf = func(string, ...any) {}
+ }
+
+ st := &state{
+ caller: caller,
+ callee: callee,
+ opts: opts,
+ }
+ return st.inline()
+}
+
+// state holds the working state of the inliner.
+type state struct {
+ caller *Caller
+ callee *Callee
+ opts *Options
+}
+
+func (st *state) inline() (*Result, error) {
+ logf, caller, callee := st.opts.Logf, st.caller, st.callee
+
+ logf("inline %s @ %v",
+ debugFormatNode(caller.Fset, caller.Call),
+ caller.Fset.PositionFor(caller.Call.Lparen, false))
+
+ if ast.IsGenerated(caller.File) {
+ return nil, fmt.Errorf("cannot inline calls from generated files")
+ }
+
+ res, err := st.inlineCall()
+ if err != nil {
+ return nil, err
+ }
+
+ // Replace the call (or some node that encloses it) by new syntax.
+ assert(res.old != nil, "old is nil")
+ assert(res.new != nil, "new is nil")
+
+ // A single return operand inlined to a unary
+ // expression context may need parens. Otherwise:
+ // func two() int { return 1+1 }
+ // print(-two()) => print(-1+1) // oops!
+ //
+ // Usually it is not necessary to insert ParenExprs
+ // as the formatter is smart enough to insert them as
+ // needed by the context. But the res.{old,new}
+ // substitution is done by formatting res.new in isolation
+ // and then splicing its text over res.old, so the
+ // formatter doesn't see the parent node and cannot do
+ // the right thing. (One solution would be to always
+ // format the enclosing node of old, but that requires
+ // non-lossy comment handling, #20744.)
+ //
+ // So, we must analyze the call's context
+ // to see whether ambiguity is possible.
+ // For example, if the context is x[y:z], then
+ // the x subtree is subject to precedence ambiguity
+ // (replacing x by p+q would give p+q[y:z] which is wrong)
+ // but the y and z subtrees are safe.
+ if new, ok := res.new.(ast.Expr); ok {
+ parent := caller.path[slices.Index(caller.path, res.old)+1]
+ res.new = internalastutil.MaybeParenthesize(parent, res.old.(ast.Expr), new)
+ }
+
+ // Some reduction strategies return a new block holding the
+ // callee's statements. The block's braces may be elided when
+ // there is no conflict between names declared in the block
+ // with those declared by the parent block, and no risk of
+ // a caller's goto jumping forward across a declaration.
+ //
+ // This elision is only safe when the ExprStmt is beneath a
+ // BlockStmt, CaseClause.Body, or CommClause.Body;
+ // (see "statement theory").
+ //
+ // The inlining analysis may have already determined that eliding braces is
+ // safe. Otherwise, we analyze its safety here.
+ elideBraces := res.elideBraces
+ if !elideBraces {
+ if newBlock, ok := res.new.(*ast.BlockStmt); ok {
+ i := slices.Index(caller.path, res.old)
+ parent := caller.path[i+1]
+ var body []ast.Stmt
+ switch parent := parent.(type) {
+ case *ast.BlockStmt:
+ body = parent.List
+ case *ast.CommClause:
+ body = parent.Body
+ case *ast.CaseClause:
+ body = parent.Body
+ }
+ if body != nil {
+ callerNames := declares(body)
+
+ // If BlockStmt is a function body,
+ // include its receiver, params, and results.
+ addFieldNames := func(fields *ast.FieldList) {
+ if fields != nil {
+ for _, field := range fields.List {
+ for _, id := range field.Names {
+ callerNames[id.Name] = true
+ }
+ }
+ }
+ }
+ switch f := caller.path[i+2].(type) {
+ case *ast.FuncDecl:
+ addFieldNames(f.Recv)
+ addFieldNames(f.Type.Params)
+ addFieldNames(f.Type.Results)
+ case *ast.FuncLit:
+ addFieldNames(f.Type.Params)
+ addFieldNames(f.Type.Results)
+ }
+
+ if len(callerLabels(caller.path)) > 0 {
+ // TODO(adonovan): be more precise and reject
+ // only forward gotos across the inlined block.
+ logf("keeping block braces: caller uses control labels")
+ } else if intersects(declares(newBlock.List), callerNames) {
+ logf("keeping block braces: avoids name conflict")
+ } else {
+ elideBraces = true
+ }
+ }
+ }
+ }
+
+ var edits []refactor.Edit
+
+ // Format the cloned callee.
+ {
+ // TODO(adonovan): might it make more sense to use
+ // callee.Fset when formatting res.new?
+ // The new tree is a mix of (cloned) caller nodes for
+ // the argument expressions and callee nodes for the
+ // function body. In essence the question is: which
+ // is more likely to have comments?
+ // Usually the callee body will be larger and more
+ // statement-heavy than the arguments, but a
+ // strategy may widen the scope of the replacement
+ // (res.old) from CallExpr to, say, its enclosing
+ // block, so the caller nodes dominate.
+ // Precise comment handling would make this a
+ // non-issue. Formatting wouldn't really need a
+ // FileSet at all.
+
+ var out bytes.Buffer
+ if elideBraces {
+ for i, stmt := range res.new.(*ast.BlockStmt).List {
+ if i > 0 {
+ out.WriteByte('\n')
+ }
+ if err := format.Node(&out, caller.Fset, stmt); err != nil {
+ return nil, err
+ }
+ }
+ } else {
+ if err := format.Node(&out, caller.Fset, res.new); err != nil {
+ return nil, err
+ }
+ }
+
+ edits = append(edits, refactor.Edit{
+ Pos: res.old.Pos(),
+ End: res.old.End(),
+ NewText: out.Bytes(),
+ })
+ }
+
+ // Add new imports.
+ //
+ // It's possible that not all are needed (e.g. for type names
+ // that melted away), but we'll let the client (such as an
+ // analysis driver) clean it up since it must remove unused
+ // imports anyway.
+ for _, imp := range res.newImports {
+ // Check that the new imports are accessible.
+ if !packagepath.CanImport(caller.Types.Path(), imp.path) {
+ return nil, fmt.Errorf("can't inline function %v as its body refers to inaccessible package %q", callee, imp.path)
+ }
+
+ // We've already validated the import, so we call
+ // AddImportEdits directly to compute the edit.
+ name := ""
+ if imp.explicit {
+ name = imp.name
+ }
+ edits = append(edits, refactor.AddImportEdits(caller.File, name, imp.path)...)
+ }
+
+ literalized := false
+ if call, ok := res.new.(*ast.CallExpr); ok && is[*ast.FuncLit](call.Fun) {
+ literalized = true
+ }
+
+ // Delete imports referenced only by caller.Call.Fun.
+ //
+ // It's ambiguous to let the client (e.g. analysis driver)
+ // remove unneeded imports in this case because it is common
+ // to inlining a call from "dir1/a".F to "dir2/a".F, which
+ // leaves two imports of packages named 'a', both providing a.F.
+ //
+ // However, the only two import deletion tools at our disposal
+ // are astutil.DeleteNamedImport, which mutates the AST, and
+ // refactor.Delete{Spec,Decl}, which need a Cursor. So we need
+ // to reinvent the wheel here.
+ for _, oldImport := range res.oldImports {
+ spec := oldImport.spec
+
+ // Include adjacent comments.
+ pos := spec.Pos()
+ if doc := spec.Doc; doc != nil {
+ pos = doc.Pos()
+ }
+ end := spec.End()
+ if doc := spec.Comment; doc != nil {
+ end = doc.End()
+ }
+
+ // Find the enclosing import decl.
+ // If it's paren-less, we must delete it too.
+ for _, decl := range caller.File.Decls {
+ decl, ok := decl.(*ast.GenDecl)
+ if !(ok && decl.Tok == token.IMPORT) {
+ break // stop at first non-import decl
+ }
+ if internalastutil.NodeContainsPos(decl, spec.Pos()) && !decl.Rparen.IsValid() {
+ // Include adjacent comments.
+ pos = decl.Pos()
+ if doc := decl.Doc; doc != nil {
+ pos = doc.Pos()
+ }
+ end = decl.End()
+ break
+ }
+ }
+
+ edits = append(edits, refactor.Edit{
+ Pos: pos,
+ End: end,
+ })
+ }
+
+ return &Result{
+ Edits: edits,
+ Literalized: literalized,
+ BindingDecl: res.bindingDecl,
+ }, nil
+}
+
+// An oldImport is an import that will be deleted from the caller file.
+type oldImport struct {
+ pkgName *types.PkgName
+ spec *ast.ImportSpec
+}
+
+// A newImport is an import that will be added to the caller file.
+type newImport struct {
+ name string
+ path string
+ explicit bool // use name as ImportSpec.Name
+}
+
+// importState tracks information about imports.
+type importState struct {
+ logf func(string, ...any)
+ caller *Caller
+ importMap map[string][]string // from package paths in the caller's file to local names
+ newImports []newImport // for references to free names in callee; to be added to the file
+ oldImports []oldImport // referenced only by caller.Call.Fun; to be removed from the file
+}
+
+// newImportState returns an importState with initial information about the caller's imports.
+func newImportState(logf func(string, ...any), caller *Caller, callee *gobCallee) *importState {
+ // For simplicity we ignore existing dot imports, so that a qualified
+ // identifier (QI) in the callee is always represented by a QI in the caller,
+ // allowing us to treat a QI like a selection on a package name.
+ ist := &importState{
+ logf: logf,
+ caller: caller,
+ importMap: make(map[string][]string),
+ }
+
+ // Provide an inefficient default implementation of CountUses.
+ // (Ideally clients amortize this for the entire package.)
+ countUses := caller.CountUses
+ if countUses == nil {
+ uses := make(map[*types.PkgName]int)
+ for _, obj := range caller.Info.Uses {
+ if pkgname, ok := obj.(*types.PkgName); ok {
+ uses[pkgname]++
+ }
+ }
+ countUses = func(pkgname *types.PkgName) int {
+ return uses[pkgname]
+ }
+ }
+
+ for _, imp := range caller.File.Imports {
+ if pkgName, ok := importedPkgName(caller.Info, imp); ok &&
+ pkgName.Name() != "." &&
+ pkgName.Name() != "_" {
+
+ // If the import's sole use is in caller.Call.Fun of the form p.F(...),
+ // where p.F is a qualified identifier, the p import may not be
+ // necessary.
+ //
+ // Only the qualified identifier case matters, as other references to
+ // imported package names in the Call.Fun expression (e.g.
+ // x.after(3*time.Second).f() or time.Second.String()) will remain after
+ // inlining, as arguments.
+ //
+ // If that is the case, proactively check if any of the callee FreeObjs
+ // need this import. Doing so eagerly simplifies the resulting logic.
+ needed := true
+ if sel, ok := ast.Unparen(caller.Call.Fun).(*ast.SelectorExpr); ok &&
+ is[*ast.Ident](sel.X) &&
+ caller.Info.Uses[sel.X.(*ast.Ident)] == pkgName &&
+ countUses(pkgName) == 1 {
+ needed = false // no longer needed by caller
+ // Check to see if any of the inlined free objects need this package.
+ for _, obj := range callee.FreeObjs {
+ if obj.PkgPath == pkgName.Imported().Path() && obj.Shadow[pkgName.Name()] == 0 {
+ needed = true // needed by callee
+ break
+ }
+ }
+ }
+
+ // Exclude imports not needed by the caller or callee after inlining; the second
+ // return value holds these.
+ if needed {
+ path := pkgName.Imported().Path()
+ ist.importMap[path] = append(ist.importMap[path], pkgName.Name())
+ } else {
+ ist.oldImports = append(ist.oldImports, oldImport{pkgName: pkgName, spec: imp})
+ }
+ }
+ }
+ return ist
+}
+
+// importName finds an existing import name to use in a particular shadowing
+// context. It is used to determine the set of new imports in
+// localName, and is also used for writing out names in inlining
+// strategies below.
+func (i *importState) importName(pkgPath string, shadow shadowMap) string {
+ for _, name := range i.importMap[pkgPath] {
+ // Check that either the import preexisted, or that it was newly added
+ // (no PkgName) but is not shadowed, either in the callee (shadows) or
+ // caller (caller.lookup).
+ if shadow[name] == 0 {
+ found := i.caller.lookup(name)
+ if is[*types.PkgName](found) || found == nil {
+ return name
+ }
+ }
+ }
+ return ""
+}
+
+// findNewLocalName returns a new local package name to use in a particular shadowing context.
+// It considers the existing local name used by the callee, or construct a new local name
+// based on the package name.
+func (i *importState) findNewLocalName(pkgName, calleePkgName string, shadow shadowMap) string {
+ newlyAdded := func(name string) bool {
+ return slices.ContainsFunc(i.newImports, func(n newImport) bool { return n.name == name })
+ }
+
+ // shadowedInCaller reports whether a candidate package name
+ // already refers to a declaration in the caller.
+ shadowedInCaller := func(name string) bool {
+ obj := i.caller.lookup(name)
+ if obj == nil {
+ return false
+ }
+ // If obj will be removed, the name is available.
+ return !slices.ContainsFunc(i.oldImports, func(o oldImport) bool { return o.pkgName == obj })
+ }
+
+ // import added by callee
+ //
+ // Try to preserve the local package name used by the callee first.
+ //
+ // If that is shadowed, choose a local package name based on last segment of
+ // package path plus, if needed, a numeric suffix to ensure uniqueness.
+ //
+ // "init" is not a legal PkgName.
+ if shadow[calleePkgName] == 0 && !shadowedInCaller(calleePkgName) && !newlyAdded(calleePkgName) && calleePkgName != "init" {
+ return calleePkgName
+ }
+
+ base := pkgName
+ name := base
+ for n := 0; shadow[name] != 0 || shadowedInCaller(name) || newlyAdded(name) || name == "init"; n++ {
+ name = fmt.Sprintf("%s%d", base, n)
+ }
+
+ return name
+}
+
+// localName returns the local name for a given imported package path,
+// adding one if it doesn't exists.
+func (i *importState) localName(pkgPath, pkgName, calleePkgName string, shadow shadowMap) string {
+ // Does an import already exist that works in this shadowing context?
+ if name := i.importName(pkgPath, shadow); name != "" {
+ return name
+ }
+
+ name := i.findNewLocalName(pkgName, calleePkgName, shadow)
+ i.logf("adding import %s %q", name, pkgPath)
+ // Use explicit pkgname (out of necessity) when it differs from the declared name,
+ // or (for good style) when it differs from base(pkgpath).
+ i.newImports = append(i.newImports, newImport{
+ name: name,
+ path: pkgPath,
+ explicit: name != pkgName || name != pathpkg.Base(pkgPath),
+ })
+ i.importMap[pkgPath] = append(i.importMap[pkgPath], name)
+ return name
+}
+
+type inlineCallResult struct {
+ newImports []newImport // to add
+ oldImports []oldImport // to remove
+
+ // If elideBraces is set, old is an ast.Stmt and new is an ast.BlockStmt to
+ // be spliced in. This allows the inlining analysis to assert that inlining
+ // the block is OK; if elideBraces is unset and old is an ast.Stmt and new is
+ // an ast.BlockStmt, braces may still be elided if the post-processing
+ // analysis determines that it is safe to do so.
+ //
+ // Ideally, it would not be necessary for the inlining analysis to "reach
+ // through" to the post-processing pass in this way. Instead, inlining could
+ // just set old to be an ast.BlockStmt and rewrite the entire BlockStmt, but
+ // unfortunately in order to preserve comments, it is important that inlining
+ // replace as little syntax as possible.
+ elideBraces bool
+ bindingDecl bool // transformation inserted "var params = args" declaration
+ old, new ast.Node // e.g. replace call expr by callee function body expression
+}
+
+// inlineCall returns a pair of an old node (the call, or something
+// enclosing it) and a new node (its replacement, which may be a
+// combination of caller, callee, and new nodes), along with the set
+// of new imports needed.
+//
+// TODO(adonovan): rethink the 'result' interface. The assumption of a
+// one-to-one replacement seems fragile. One can easily imagine the
+// transformation replacing the call and adding new variable
+// declarations, for example, or replacing a call statement by zero or
+// many statements.)
+// NOTE(rfindley): we've sort-of done this, with the 'elideBraces' flag that
+// allows inlining a statement list. However, due to loss of comments, more
+// sophisticated rewrites are challenging.
+//
+// TODO(rfindley): see if we can reduce the amount of comment lossiness by
+// using printer.CommentedNode, which has been useful elsewhere.
+//
+// TODO(rfindley): inlineCall is getting very long, and very stateful, making
+// it very hard to read. The following refactoring may improve readability and
+// maintainability:
+// - Rename 'state' to 'callsite', since that is what it encapsulates.
+// - Add results of pre-processing analysis into the callsite struct, such as
+// the effective importMap, new/old imports, arguments, etc. Essentially
+// anything that resulted from initial analysis of the call site, and which
+// may be useful to inlining strategies.
+// - Delegate this call site analysis to a constructor or initializer, such
+// as 'analyzeCallsite', so that it does not consume bandwidth in the
+// 'inlineCall' logical flow.
+// - Once analyzeCallsite returns, the callsite is immutable, much in the
+// same way as the Callee and Caller are immutable.
+// - Decide on a standard interface for strategies (and substrategies), such
+// that they may be delegated to a separate method on callsite.
+//
+// In this way, the logical flow of inline call will clearly follow the
+// following structure:
+// 1. Analyze the call site.
+// 2. Try strategies, in order, until one succeeds.
+// 3. Process the results.
+//
+// If any expensive analysis may be avoided by earlier strategies, it can be
+// encapsulated in its own type and passed to subsequent strategies.
+func (st *state) inlineCall() (*inlineCallResult, error) {
+ logf, caller, callee := st.opts.Logf, st.caller, &st.callee.impl
+
+ checkInfoFields(caller.Info)
+
+ // Inlining of dynamic calls is not currently supported,
+ // even for local closure calls. (This would be a lot of work.)
+ calleeSymbol := typeutil.StaticCallee(caller.Info, caller.Call)
+ if calleeSymbol == nil {
+ // e.g. interface method
+ return nil, fmt.Errorf("cannot inline: not a static function call")
+ }
+
+ // Reject cross-package inlining if callee has
+ // free references to unexported symbols.
+ samePkg := caller.Types.Path() == callee.PkgPath
+ if !samePkg && len(callee.Unexported) > 0 {
+ return nil, fmt.Errorf("cannot inline call to %s because body refers to non-exported %s",
+ callee.Name, callee.Unexported[0])
+ }
+
+ // Reject cross-file inlining if callee requires a newer dialect of Go (#75726).
+ // (Versions default to types.Config.GoVersion, which is unset in many tests,
+ // though should be populated by an analysis driver.)
+ callerGoVersion := caller.Info.FileVersions[caller.File]
+ if callerGoVersion != "" && callee.GoVersion != "" && versions.Before(callerGoVersion, callee.GoVersion) {
+ return nil, fmt.Errorf("cannot inline call to %s (declared using %s) into a file using %s",
+ callee.Name, callee.GoVersion, callerGoVersion)
+ }
+
+ // -- analyze callee's free references in caller context --
+
+ // Compute syntax path enclosing Call, innermost first (Path[0]=Call),
+ // and outermost enclosing function, if any.
+ caller.path, _ = astutil.PathEnclosingInterval(caller.File, caller.Call.Pos(), caller.Call.End())
+ for _, n := range caller.path {
+ if decl, ok := n.(*ast.FuncDecl); ok {
+ caller.enclosingFunc = decl
+ break
+ }
+ }
+
+ // If call is within a function, analyze all its
+ // local vars for the "single assignment" property.
+ // (Taking the address &v counts as a potential assignment.)
+ var assign1 func(v *types.Var) bool // reports whether v a single-assignment local var
+ {
+ updatedLocals := make(map[*types.Var]bool)
+ if caller.enclosingFunc != nil {
+ escape(caller.Info, caller.enclosingFunc, func(v *types.Var, _ bool) {
+ updatedLocals[v] = true
+ })
+ logf("multiple-assignment vars: %v", updatedLocals)
+ }
+ assign1 = func(v *types.Var) bool { return !updatedLocals[v] }
+ }
+
+ // Extract information about the caller's imports.
+ istate := newImportState(logf, caller, callee)
+
+ // Compute the renaming of the callee's free identifiers.
+ objRenames, err := st.renameFreeObjs(istate)
+ if err != nil {
+ return nil, err
+ }
+
+ res := &inlineCallResult{
+ newImports: istate.newImports,
+ oldImports: istate.oldImports,
+ }
+
+ // Parse callee function declaration.
+ calleeFset, calleeDecl, err := parseCompact(callee.Content)
+ if err != nil {
+ return nil, err // "can't happen"
+ }
+
+ // replaceCalleeID replaces an identifier in the callee. See [replacer] for
+ // more detailed semantics.
+ replaceCalleeID := func(offset int, repl ast.Expr, unpackVariadic bool) {
+ path, id := findIdent(calleeDecl, calleeDecl.Pos()+token.Pos(offset))
+ logf("- replace id %q @ #%d to %q", id.Name, offset, debugFormatNode(calleeFset, repl))
+ // Replace f([]T{a, b, c}...) with f(a, b, c).
+ if lit, ok := repl.(*ast.CompositeLit); ok && unpackVariadic && len(path) > 0 {
+ if call, ok := last(path).(*ast.CallExpr); ok &&
+ call.Ellipsis.IsValid() &&
+ id == last(call.Args) {
+
+ call.Args = append(call.Args[:len(call.Args)-1], lit.Elts...)
+ call.Ellipsis = token.NoPos
+ return
+ }
+ }
+ if len(path) > 0 {
+ repl = internalastutil.MaybeParenthesize(last(path), id, repl)
+ }
+ replaceNode(calleeDecl, id, repl)
+ }
+
+ // Generate replacements for each free identifier.
+ // (The same tree may be spliced in multiple times, resulting in a DAG.)
+ for _, ref := range callee.FreeRefs {
+ if repl := objRenames[ref.Object]; repl != nil {
+ replaceCalleeID(ref.Offset, repl, false)
+ }
+ }
+
+ // Gather the effective call arguments, including the receiver.
+ // Later, elements will be eliminated (=> nil) by parameter substitution.
+ args, err := st.arguments(caller, calleeDecl, assign1)
+ if err != nil {
+ return nil, err // e.g. implicit field selection cannot be made explicit
+ }
+
+ // Gather effective parameter tuple, including the receiver if any.
+ // Simplify variadic parameters to slices (in all cases but one).
+ var params []*parameter // including receiver; nil => parameter substituted
+ {
+ sig := calleeSymbol.Type().(*types.Signature)
+ if sig.Recv() != nil {
+ params = append(params, ¶meter{
+ obj: sig.Recv(),
+ fieldType: calleeDecl.Recv.List[0].Type,
+ info: callee.Params[0],
+ })
+ }
+
+ // Flatten the list of syntactic types.
+ var types []ast.Expr
+ for _, field := range calleeDecl.Type.Params.List {
+ if field.Names == nil {
+ types = append(types, field.Type)
+ } else {
+ for range field.Names {
+ types = append(types, field.Type)
+ }
+ }
+ }
+
+ for i := 0; i < sig.Params().Len(); i++ {
+ params = append(params, ¶meter{
+ obj: sig.Params().At(i),
+ fieldType: types[i],
+ info: callee.Params[len(params)],
+ })
+ }
+
+ // Variadic function?
+ //
+ // There are three possible types of call:
+ // - ordinary f(a1, ..., aN)
+ // - ellipsis f(a1, ..., slice...)
+ // - spread f(recv?, g()) where g() is a tuple.
+ // The first two are desugared to non-variadic calls
+ // with an ordinary slice parameter;
+ // the third is tricky and cannot be reduced, and (if
+ // a receiver is present) cannot even be literalized.
+ // Fortunately it is vanishingly rare.
+ //
+ // TODO(adonovan): extract this to a function.
+ if sig.Variadic() {
+ lastParam := last(params)
+ if len(args) > 0 && last(args).spread {
+ // spread call to variadic: tricky
+ lastParam.variadic = true
+ } else {
+ // ordinary/ellipsis call to variadic
+
+ // simplify decl: func(T...) -> func([]T)
+ lastParamField := last(calleeDecl.Type.Params.List)
+ lastParamField.Type = &ast.ArrayType{
+ Elt: lastParamField.Type.(*ast.Ellipsis).Elt,
+ }
+
+ if caller.Call.Ellipsis.IsValid() {
+ // ellipsis call: f(slice...) -> f(slice)
+ // nop
+ } else {
+ // ordinary call: f(a1, ... aN) -> f([]T{a1, ..., aN})
+ //
+ // Substitution of []T{...} in the callee body may lead to
+ // g([]T{a1, ..., aN}...), which we simplify to g(a1, ..., an)
+ // later; see replaceCalleeID.
+ n := len(params) - 1
+ ordinary, extra := args[:n], args[n:]
+ var elts []ast.Expr
+ freevars := make(map[string]bool)
+ pure, effects := true, false
+ for _, arg := range extra {
+ elts = append(elts, arg.expr)
+ pure = pure && arg.pure
+ effects = effects || arg.effects
+ maps.Copy(freevars, arg.freevars)
+ }
+ args = append(ordinary, &argument{
+ expr: &ast.CompositeLit{
+ Type: lastParamField.Type,
+ Elts: elts,
+ },
+ typ: lastParam.obj.Type(),
+ constant: nil,
+ pure: pure,
+ effects: effects,
+ duplicable: false,
+ freevars: freevars,
+ variadic: true,
+ })
+ }
+ }
+ }
+ }
+
+ typeArgs := st.typeArguments(caller.Call)
+ if len(typeArgs) != len(callee.TypeParams) {
+ return nil, fmt.Errorf("cannot inline: type parameter inference is not yet supported")
+ }
+ if err := substituteTypeParams(logf, callee.TypeParams, typeArgs, params, replaceCalleeID); err != nil {
+ return nil, err
+ }
+
+ // Log effective arguments.
+ for i, arg := range args {
+ logf("arg #%d: %s pure=%t effects=%t duplicable=%t free=%v type=%v",
+ i, debugFormatNode(caller.Fset, arg.expr),
+ arg.pure, arg.effects, arg.duplicable, arg.freevars, arg.typ)
+ }
+
+ // Note: computation below should be expressed in terms of
+ // the args and params slices, not the raw material.
+
+ // Perform parameter substitution.
+ // May eliminate some elements of params/args.
+ substitute(logf, caller, params, args, callee.Effects, callee.Falcon, replaceCalleeID)
+
+ // Update the callee's signature syntax.
+ updateCalleeParams(calleeDecl, params)
+
+ // Create a var (param = arg; ...) decl for use by some strategies.
+ bindingDecl := createBindingDecl(logf, caller, args, calleeDecl, callee.Results)
+
+ var remainingArgs []ast.Expr
+ for _, arg := range args {
+ if arg != nil {
+ remainingArgs = append(remainingArgs, arg.expr)
+ }
+ }
+
+ // -- let the inlining strategies begin --
+ //
+ // When we commit to a strategy, we log a message of the form:
+ //
+ // "strategy: reduce expr-context call to { return expr }"
+ //
+ // This is a terse way of saying:
+ //
+ // we plan to reduce a call
+ // that appears in expression context
+ // to a function whose body is of the form { return expr }
+
+ // TODO(adonovan): split this huge function into a sequence of
+ // function calls with an error sentinel that means "try the
+ // next strategy", and make sure each strategy writes to the
+ // log the reason it didn't match.
+
+ // Special case: eliminate a call to a function whose body is empty.
+ // (=> callee has no results and caller is a statement.)
+ //
+ // func f(params) {}
+ // f(args)
+ // => _, _ = args
+ //
+ if len(calleeDecl.Body.List) == 0 {
+ logf("strategy: reduce call to empty body")
+
+ // Evaluate the arguments for effects and delete the call entirely.
+ // Note(golang/go#71486): stmt can be nil if the call is in a go or defer
+ // statement.
+ // TODO: discard go or defer statements as well.
+ if stmt := callStmt(caller.path, false); stmt != nil {
+ res.old = stmt
+ if nargs := len(remainingArgs); nargs > 0 {
+ // Emit "_, _ = args" to discard results.
+
+ // TODO(adonovan): if args is the []T{a1, ..., an}
+ // literal synthesized during variadic simplification,
+ // consider unwrapping it to its (pure) elements.
+ // Perhaps there's no harm doing this for any slice literal.
+
+ // Make correction for spread calls
+ // f(g()) or recv.f(g()) where g() is a tuple.
+ if last := last(args); last != nil && last.spread {
+ nspread := last.typ.(*types.Tuple).Len()
+ if len(args) > 1 { // [recv, g()]
+ // A single AssignStmt cannot discard both, so use a 2-spec var decl.
+ res.new = &ast.GenDecl{
+ Tok: token.VAR,
+ Specs: []ast.Spec{
+ &ast.ValueSpec{
+ Names: []*ast.Ident{makeIdent("_")},
+ Values: []ast.Expr{args[0].expr},
+ },
+ &ast.ValueSpec{
+ Names: blanks[*ast.Ident](nspread),
+ Values: []ast.Expr{args[1].expr},
+ },
+ },
+ }
+ return res, nil
+ }
+
+ // Sole argument is spread call.
+ nargs = nspread
+ }
+
+ res.new = &ast.AssignStmt{
+ Lhs: blanks[ast.Expr](nargs),
+ Tok: token.ASSIGN,
+ Rhs: remainingArgs,
+ }
+
+ } else {
+ // No remaining arguments: delete call statement entirely
+ res.new = &ast.EmptyStmt{}
+ }
+ return res, nil
+ }
+ }
+
+ // If all parameters have been substituted and no result
+ // variable is referenced, we don't need a binding decl.
+ // This may enable better reduction strategies.
+ allResultsUnreferenced := forall(callee.Results, func(i int, r *paramInfo) bool { return len(r.Refs) == 0 })
+ needBindingDecl := !allResultsUnreferenced ||
+ exists(params, func(i int, p *parameter) bool { return p != nil })
+
+ // The two strategies below overlap for a tail call of {return exprs}:
+ // The expr-context reduction is nice because it keeps the
+ // caller's return stmt and merely switches its operand,
+ // without introducing a new block, but it doesn't work with
+ // implicit return conversions.
+ //
+ // TODO(adonovan): unify these cases more cleanly, allowing return-
+ // operand replacement and implicit conversions, by adding
+ // conversions around each return operand (if not a spread return).
+
+ // Special case: call to { return exprs }.
+ //
+ // Reduces to:
+ // { var (bindings); _, _ = exprs }
+ // or _, _ = exprs
+ // or expr
+ //
+ // If:
+ // - the body is just "return expr" with trivial implicit conversions,
+ // or the caller's return type matches the callee's,
+ // - all parameters and result vars can be eliminated
+ // or replaced by a binding decl,
+ // then the call expression can be replaced by the
+ // callee's body expression, suitably substituted.
+ if len(calleeDecl.Body.List) == 1 &&
+ is[*ast.ReturnStmt](calleeDecl.Body.List[0]) &&
+ len(calleeDecl.Body.List[0].(*ast.ReturnStmt).Results) > 0 { // not a bare return
+ results := calleeDecl.Body.List[0].(*ast.ReturnStmt).Results
+
+ parent, grandparent := callContext(caller.path)
+
+ // statement context
+ if stmt, ok := parent.(*ast.ExprStmt); ok &&
+ (!needBindingDecl || bindingDecl != nil) {
+ logf("strategy: reduce stmt-context call to { return exprs }")
+ clearPositions(calleeDecl.Body)
+
+ if callee.ValidForCallStmt {
+ logf("callee body is valid as statement")
+ // Inv: len(results) == 1
+ if !needBindingDecl {
+ // Reduces to: expr
+ res.old = caller.Call
+ res.new = results[0]
+ } else {
+ // Reduces to: { var (bindings); expr }
+ res.bindingDecl = true
+ res.old = stmt
+ res.new = &ast.BlockStmt{
+ List: []ast.Stmt{
+ bindingDecl.stmt,
+ &ast.ExprStmt{X: results[0]},
+ },
+ }
+ }
+ } else {
+ logf("callee body is not valid as statement")
+ // The call is a standalone statement, but the
+ // callee body is not suitable as a standalone statement
+ // (f() or <-ch), explicitly discard the results:
+ // Reduces to: _, _ = exprs
+ discard := &ast.AssignStmt{
+ Lhs: blanks[ast.Expr](callee.NumResults),
+ Tok: token.ASSIGN,
+ Rhs: results,
+ }
+ res.old = stmt
+ if !needBindingDecl {
+ // Reduces to: _, _ = exprs
+ res.new = discard
+ } else {
+ // Reduces to: { var (bindings); _, _ = exprs }
+ res.bindingDecl = true
+ res.new = &ast.BlockStmt{
+ List: []ast.Stmt{
+ bindingDecl.stmt,
+ discard,
+ },
+ }
+ }
+ }
+ return res, nil
+ }
+
+ // Assignment context.
+ //
+ // If there is no binding decl, or if the binding decl declares no names,
+ // an assignment a, b := f() can be reduced to a, b := x, y.
+ if stmt, ok := parent.(*ast.AssignStmt); ok &&
+ is[*ast.BlockStmt](grandparent) &&
+ (!needBindingDecl || (bindingDecl != nil && len(bindingDecl.names) == 0)) {
+
+ // Reduces to: { var (bindings); lhs... := rhs... }
+ if newStmts, ok := st.assignStmts(stmt, results, istate.importName); ok {
+ logf("strategy: reduce assign-context call to { return exprs }")
+
+ clearPositions(calleeDecl.Body)
+
+ block := &ast.BlockStmt{
+ List: newStmts,
+ }
+ if needBindingDecl {
+ res.bindingDecl = true
+ block.List = prepend(bindingDecl.stmt, block.List...)
+ }
+
+ // assignStmts does not introduce new bindings, and replacing an
+ // assignment only works if the replacement occurs in the same scope.
+ // Therefore, we must ensure that braces are elided.
+ res.elideBraces = true
+ res.old = stmt
+ res.new = block
+ return res, nil
+ }
+ }
+
+ // expression context
+ if !needBindingDecl {
+ clearPositions(calleeDecl.Body)
+
+ anyNonTrivialReturns := hasNonTrivialReturn(callee.Returns)
+
+ if callee.NumResults == 1 {
+ logf("strategy: reduce expr-context call to { return expr }")
+ // (includes some simple tail-calls)
+
+ // Make implicit return conversion explicit.
+ if anyNonTrivialReturns {
+ results[0] = convert(calleeDecl.Type.Results.List[0].Type, results[0])
+ }
+
+ res.old = caller.Call
+ res.new = results[0]
+ return res, nil
+
+ } else if !anyNonTrivialReturns {
+ logf("strategy: reduce spread-context call to { return expr }")
+ // There is no general way to reify conversions in a spread
+ // return, hence the requirement above.
+ //
+ // TODO(adonovan): allow this reduction when no
+ // conversion is required by the context.
+
+ // The call returns multiple results but is
+ // not a standalone call statement. It must
+ // be the RHS of a spread assignment:
+ // var x, y = f()
+ // x, y := f()
+ // x, y = f()
+ // or the sole argument to a spread call:
+ // printf(f())
+ // or spread return statement:
+ // return f()
+ res.old = parent
+ switch context := parent.(type) {
+ case *ast.AssignStmt:
+ // Inv: the call must be in Rhs[0], not Lhs.
+ assign := shallowCopy(context)
+ assign.Rhs = results
+ res.new = assign
+ case *ast.ValueSpec:
+ // Inv: the call must be in Values[0], not Names.
+ spec := shallowCopy(context)
+ spec.Values = results
+ res.new = spec
+ case *ast.CallExpr:
+ // Inv: the call must be in Args[0], not Fun.
+ call := shallowCopy(context)
+ call.Args = results
+ res.new = call
+ case *ast.ReturnStmt:
+ // Inv: the call must be Results[0].
+ ret := shallowCopy(context)
+ ret.Results = results
+ res.new = ret
+ default:
+ return nil, fmt.Errorf("internal error: unexpected context %T for spread call", context)
+ }
+ return res, nil
+ }
+ }
+ }
+
+ // Special case: tail-call.
+ //
+ // Inlining:
+ // return f(args)
+ // where:
+ // func f(params) (results) { body }
+ // reduces to:
+ // { var (bindings); body }
+ // { body }
+ // so long as:
+ // - all parameters can be eliminated or replaced by a binding decl,
+ // - call is a tail-call;
+ // - all returns in body have trivial result conversions,
+ // or the caller's return type matches the callee's,
+ // - there is no label conflict;
+ // - no result variable is referenced by name,
+ // or implicitly by a bare return.
+ //
+ // The body may use defer, arbitrary control flow, and
+ // multiple returns.
+ //
+ // TODO(adonovan): add a strategy for a 'void tail
+ // call', i.e. a call statement prior to an (explicit
+ // or implicit) return.
+ parent, _ := callContext(caller.path)
+ if ret, ok := parent.(*ast.ReturnStmt); ok &&
+ len(ret.Results) == 1 &&
+ tailCallSafeReturn(caller, calleeSymbol, callee) &&
+ !callee.HasBareReturn &&
+ (!needBindingDecl || bindingDecl != nil) &&
+ !hasLabelConflict(caller.path, callee.Labels) &&
+ allResultsUnreferenced {
+ logf("strategy: reduce tail-call")
+ body := calleeDecl.Body
+ clearPositions(body)
+ if needBindingDecl {
+ res.bindingDecl = true
+ body.List = prepend(bindingDecl.stmt, body.List...)
+ }
+ res.old = ret
+ res.new = body
+ return res, nil
+ }
+
+ // Special case: call to void function
+ //
+ // Inlining:
+ // f(args)
+ // where:
+ // func f(params) { stmts }
+ // reduces to:
+ // { var (bindings); stmts }
+ // { stmts }
+ // so long as:
+ // - callee is a void function (no returns)
+ // - callee does not use defer
+ // - there is no label conflict between caller and callee
+ // - all parameters and result vars can be eliminated
+ // or replaced by a binding decl,
+ // - caller ExprStmt is in unrestricted statement context.
+ if stmt := callStmt(caller.path, true); stmt != nil &&
+ (!needBindingDecl || bindingDecl != nil) &&
+ !callee.HasDefer &&
+ !hasLabelConflict(caller.path, callee.Labels) &&
+ len(callee.Returns) == 0 {
+ logf("strategy: reduce stmt-context call to { stmts }")
+ body := calleeDecl.Body
+ var repl ast.Stmt = body
+ clearPositions(repl)
+ if needBindingDecl {
+ body.List = prepend(bindingDecl.stmt, body.List...)
+ }
+ res.old = stmt
+ res.new = repl
+ return res, nil
+ }
+
+ // TODO(adonovan): parameterless call to { stmts; return expr }
+ // from one of these contexts:
+ // x, y = f()
+ // x, y := f()
+ // var x, y = f()
+ // =>
+ // var (x T1, y T2); { stmts; x, y = expr }
+ //
+ // Because the params are no longer declared simultaneously
+ // we need to check that (for example) x ∉ freevars(T2),
+ // in addition to the usual checks for arg/result conversions,
+ // complex control, etc.
+ // Also test cases where expr is an n-ary call (spread returns).
+
+ // Literalization isn't quite infallible.
+ // Consider a spread call to a method in which
+ // no parameters are eliminated, e.g.
+ // new(T).f(g())
+ // where
+ // func (recv *T) f(x, y int) { body }
+ // func g() (int, int)
+ // This would be literalized to:
+ // func (recv *T, x, y int) { body }(new(T), g()),
+ // which is not a valid argument list because g() must appear alone.
+ // Reject this case for now.
+ if len(args) == 2 && args[0] != nil && args[1] != nil && is[*types.Tuple](args[1].typ) {
+ return nil, fmt.Errorf("can't yet inline spread call to method")
+ }
+
+ // Infallible general case: literalization.
+ //
+ // func(params) { body }(args)
+ //
+ logf("strategy: literalization")
+ funcLit := &ast.FuncLit{
+ Type: calleeDecl.Type,
+ Body: calleeDecl.Body,
+ }
+ // clear positions before prepending the binding decl below, since the
+ // binding decl contains syntax from the caller and we must not mutate the
+ // caller. (This was a prior bug.)
+ clearPositions(funcLit)
+
+ // Literalization can still make use of a binding
+ // decl as it gives a more natural reading order:
+ //
+ // func() { var params = args; body }()
+ //
+ // TODO(adonovan): relax the allResultsUnreferenced requirement
+ // by adding a parameter-only (no named results) binding decl.
+ if bindingDecl != nil && allResultsUnreferenced {
+ funcLit.Type.Params.List = nil
+ remainingArgs = nil
+ res.bindingDecl = true
+ funcLit.Body.List = prepend(bindingDecl.stmt, funcLit.Body.List...)
+ }
+
+ // Emit a new call to a function literal in place of
+ // the callee name, with appropriate replacements.
+ newCall := &ast.CallExpr{
+ Fun: funcLit,
+ Ellipsis: token.NoPos, // f(slice...) is always simplified
+ Args: remainingArgs,
+ }
+ res.old = caller.Call
+ res.new = newCall
+ return res, nil
+}
+
+// renameFreeObjs computes the renaming of the callee's free identifiers.
+// It returns a slice of names (identifiers or selector expressions) corresponding
+// to the callee's free objects (gobCallee.FreeObjs).
+func (st *state) renameFreeObjs(istate *importState) ([]ast.Expr, error) {
+ caller, callee := st.caller, &st.callee.impl
+ objRenames := make([]ast.Expr, len(callee.FreeObjs)) // nil => no change
+ for i, obj := range callee.FreeObjs {
+ // obj is a free object of the callee.
+ //
+ // Possible cases are:
+ // - builtin function, type, or value (e.g. nil, zero)
+ // => check not shadowed in caller.
+ // - package-level var/func/const/types
+ // => same package: check not shadowed in caller.
+ // => otherwise: import other package, form a qualified identifier.
+ // (Unexported cross-package references were rejected already.)
+ // - type parameter
+ // => not yet supported
+ // - pkgname
+ // => import other package and use its local name.
+ //
+ // There can be no free references to labels, fields, or methods.
+
+ // Note that we must consider potential shadowing both
+ // at the caller side (caller.lookup) and, when
+ // choosing new PkgNames, within the callee (obj.shadow).
+
+ var newName ast.Expr
+ if obj.Kind == "pkgname" {
+ // Use locally appropriate import, creating as needed.
+ n := istate.localName(obj.PkgPath, obj.PkgName, obj.Name, obj.Shadow)
+ newName = makeIdent(n) // imported package
+ } else if !obj.ValidPos {
+ // Built-in function, type, or value (e.g. nil, zero):
+ // check not shadowed at caller.
+ found := caller.lookup(obj.Name) // always finds something
+ if found.Pos().IsValid() {
+ return nil, fmt.Errorf("cannot inline, because the callee refers to built-in %q, which in the caller is shadowed by a %s (declared at line %d)",
+ obj.Name, objectKind(found),
+ caller.Fset.PositionFor(found.Pos(), false).Line)
+ }
+
+ } else {
+ // Must be reference to package-level var/func/const/type,
+ // since type parameters are not yet supported.
+ qualify := false
+ if obj.PkgPath == callee.PkgPath {
+ // reference within callee package
+ if caller.Types.Path() == callee.PkgPath {
+ // Caller and callee are in same package.
+ // Check caller has not shadowed the decl.
+ //
+ // This may fail if the callee is "fake", such as for signature
+ // refactoring where the callee is modified to be a trivial wrapper
+ // around the refactored signature.
+ found := caller.lookup(obj.Name)
+ if found != nil && !isPkgLevel(found) {
+ return nil, fmt.Errorf("cannot inline, because the callee refers to %s %q, which in the caller is shadowed by a %s (declared at line %d)",
+ obj.Kind, obj.Name,
+ objectKind(found),
+ caller.Fset.PositionFor(found.Pos(), false).Line)
+ }
+ } else {
+ // Cross-package reference.
+ qualify = true
+ }
+ } else {
+ // Reference to a package-level declaration
+ // in another package, without a qualified identifier:
+ // it must be a dot import.
+ qualify = true
+ }
+
+ // Form a qualified identifier, pkg.Name.
+ if qualify {
+ pkgName := istate.localName(obj.PkgPath, obj.PkgName, obj.PkgName, obj.Shadow)
+ newName = &ast.SelectorExpr{
+ X: makeIdent(pkgName),
+ Sel: makeIdent(obj.Name),
+ }
+ }
+ }
+ objRenames[i] = newName
+ }
+ return objRenames, nil
+}
+
+type argument struct {
+ expr ast.Expr
+ typ types.Type // may be tuple for sole non-receiver arg in spread call
+ constant constant.Value // value of argument if constant
+ spread bool // final arg is call() assigned to multiple params
+ pure bool // expr is pure (doesn't read variables)
+ effects bool // expr has effects (updates variables)
+ duplicable bool // expr may be duplicated
+ freevars map[string]bool // free names of expr
+ variadic bool // is explicit []T{...} for eliminated variadic
+ desugaredRecv bool // is *recv or &recv, where operator was elided
+}
+
+// typeArguments returns the type arguments of the call.
+// It only collects the arguments that are explicitly provided; it does
+// not attempt type inference.
+func (st *state) typeArguments(call *ast.CallExpr) []*argument {
+ var exprs []ast.Expr
+ switch d := ast.Unparen(call.Fun).(type) {
+ case *ast.IndexExpr:
+ exprs = []ast.Expr{d.Index}
+ case *ast.IndexListExpr:
+ exprs = d.Indices
+ default:
+ // No type arguments
+ return nil
+ }
+ var args []*argument
+ for _, e := range exprs {
+ arg := &argument{expr: e, freevars: freeVars(st.caller.Info, e)}
+ args = append(args, arg)
+ }
+ return args
+}
+
+// arguments returns the effective arguments of the call.
+//
+// If the receiver argument and parameter have
+// different pointerness, make the "&" or "*" explicit.
+//
+// Also, if x.f() is shorthand for promoted method x.y.f(),
+// make the .y explicit in T.f(x.y, ...).
+//
+// Beware that:
+//
+// - a method can only be called through a selection, but only
+// the first of these two forms needs special treatment:
+//
+// expr.f(args) -> ([&*]expr, args) MethodVal
+// T.f(recv, args) -> ( expr, args) MethodExpr
+//
+// - the presence of a value in receiver-position in the call
+// is a property of the caller, not the callee. A method
+// (calleeDecl.Recv != nil) may be called like an ordinary
+// function.
+//
+// - the types.Signatures seen by the caller (from
+// StaticCallee) and by the callee (from decl type)
+// differ in this case.
+//
+// In a spread call f(g()), the sole ordinary argument g(),
+// always last in args, has a tuple type.
+//
+// We compute type-based predicates like pure, duplicable,
+// freevars, etc, now, before we start modifying syntax.
+func (st *state) arguments(caller *Caller, calleeDecl *ast.FuncDecl, assign1 func(*types.Var) bool) ([]*argument, error) {
+ var args []*argument
+
+ callArgs := caller.Call.Args
+ if calleeDecl.Recv != nil {
+ if len(st.callee.impl.TypeParams) > 0 {
+ return nil, fmt.Errorf("cannot inline: generic methods not yet supported")
+ }
+ sel := ast.Unparen(caller.Call.Fun).(*ast.SelectorExpr)
+ seln := caller.Info.Selections[sel]
+ var recvArg ast.Expr
+ switch seln.Kind() {
+ case types.MethodVal: // recv.f(callArgs)
+ recvArg = sel.X
+ case types.MethodExpr: // T.f(recv, callArgs)
+ recvArg = callArgs[0]
+ callArgs = callArgs[1:]
+ }
+ if recvArg != nil {
+ // Compute all the type-based predicates now,
+ // before we start meddling with the syntax;
+ // the meddling will update them.
+ arg := &argument{
+ expr: recvArg,
+ typ: caller.Info.TypeOf(recvArg),
+ constant: caller.Info.Types[recvArg].Value,
+ pure: pure(caller.Info, assign1, recvArg),
+ effects: st.effects(caller.Info, recvArg),
+ duplicable: duplicable(caller.Info, recvArg),
+ freevars: freeVars(caller.Info, recvArg),
+ }
+ recvArg = nil // prevent accidental use
+
+ // Move receiver argument recv.f(args) to argument list f(&recv, args).
+ args = append(args, arg)
+
+ // Make field selections explicit (recv.f -> recv.y.f),
+ // updating arg.{expr,typ}.
+ indices := seln.Index()
+ for _, index := range indices[:len(indices)-1] {
+ fld := typeparams.CoreType(typeparams.Deref(arg.typ)).(*types.Struct).Field(index)
+ if fld.Pkg() != caller.Types && !fld.Exported() {
+ return nil, fmt.Errorf("in %s, implicit reference to unexported field .%s cannot be made explicit",
+ debugFormatNode(caller.Fset, caller.Call.Fun),
+ fld.Name())
+ }
+ if isPointer(arg.typ) {
+ arg.pure = false // implicit *ptr operation => impure
+ }
+ arg.expr = &ast.SelectorExpr{
+ X: arg.expr,
+ Sel: makeIdent(fld.Name()),
+ }
+ arg.typ = fld.Type()
+ arg.duplicable = false
+ }
+
+ // Make * or & explicit.
+ argIsPtr := isPointer(arg.typ)
+ paramIsPtr := isPointer(seln.Obj().Type().Underlying().(*types.Signature).Recv().Type())
+ if !argIsPtr && paramIsPtr {
+ // &recv
+ arg.expr = &ast.UnaryExpr{Op: token.AND, X: arg.expr}
+ arg.typ = types.NewPointer(arg.typ)
+ arg.desugaredRecv = true
+ } else if argIsPtr && !paramIsPtr {
+ // *recv
+ arg.expr = &ast.StarExpr{X: arg.expr}
+ arg.typ = typeparams.Deref(arg.typ)
+ arg.duplicable = false
+ arg.pure = false
+ arg.desugaredRecv = true
+ }
+ }
+ }
+ for _, expr := range callArgs {
+ tv := caller.Info.Types[expr]
+ args = append(args, &argument{
+ expr: expr,
+ typ: tv.Type,
+ constant: tv.Value,
+ spread: is[*types.Tuple](tv.Type), // => last
+ pure: pure(caller.Info, assign1, expr),
+ effects: st.effects(caller.Info, expr),
+ duplicable: duplicable(caller.Info, expr),
+ freevars: freeVars(caller.Info, expr),
+ })
+ }
+
+ // Re-typecheck each constant argument expression in a neutral context.
+ //
+ // In a call such as func(int16){}(1), the type checker infers
+ // the type "int16", not "untyped int", for the argument 1,
+ // because it has incorporated information from the left-hand
+ // side of the assignment implicit in parameter passing, but
+ // of course in a different context, the expression 1 may have
+ // a different type.
+ //
+ // So, we must use CheckExpr to recompute the type of the
+ // argument in a neutral context to find its inherent type.
+ // (This is arguably a bug in go/types, but I'm pretty certain
+ // I requested it be this way long ago... -adonovan)
+ //
+ // This is only needed for constants. Other implicit
+ // assignment conversions, such as unnamed-to-named struct or
+ // chan to <-chan, do not result in the type-checker imposing
+ // the LHS type on the RHS value.
+ for _, arg := range args {
+ if arg.constant == nil {
+ continue
+ }
+ info := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
+ if err := types.CheckExpr(caller.Fset, caller.Types, caller.Call.Pos(), arg.expr, info); err != nil {
+ return nil, err
+ }
+ arg.typ = info.TypeOf(arg.expr)
+ }
+
+ return args, nil
+}
+
+type parameter struct {
+ obj *types.Var // parameter var from caller's signature
+ fieldType ast.Expr // syntax of type, from calleeDecl.Type.{Recv,Params}
+ info *paramInfo // information from AnalyzeCallee
+ variadic bool // (final) parameter is unsimplified ...T
+}
+
+// A replacer replaces an identifier at the given offset in the callee.
+// The replacement tree must not belong to the caller; use cloneNode as needed.
+// If unpackVariadic is set, the replacement is a composite resulting from
+// variadic elimination, and may be unpacked into variadic calls.
+type replacer = func(offset int, repl ast.Expr, unpackVariadic bool)
+
+// substituteTypeParams replaces type parameters in the callee with the corresponding type arguments
+// from the call.
+func substituteTypeParams(logf logger, typeParams []*paramInfo, typeArgs []*argument, params []*parameter, replace replacer) error {
+ assert(len(typeParams) == len(typeArgs), "mismatched number of type params/args")
+ for i, paramInfo := range typeParams {
+ arg := typeArgs[i]
+ // Perform a simplified, conservative shadow analysis: fail if there is any shadowing.
+ for free := range arg.freevars {
+ if paramInfo.Shadow[free] != 0 {
+ return fmt.Errorf("cannot inline: type argument #%d (type parameter %s) is shadowed", i, paramInfo.Name)
+ }
+ }
+ logf("replacing type param %s with %s", paramInfo.Name, debugFormatNode(token.NewFileSet(), arg.expr))
+ for _, ref := range paramInfo.Refs {
+ replace(ref.Offset, internalastutil.CloneNode(arg.expr), false)
+ }
+ // Also replace parameter field types.
+ // TODO(jba): find a way to do this that is not so slow and clumsy.
+ // Ideally, we'd walk each p.fieldType once, replacing all type params together.
+ for _, p := range params {
+ if id, ok := p.fieldType.(*ast.Ident); ok && id.Name == paramInfo.Name {
+ p.fieldType = arg.expr
+ } else {
+ for _, id := range identsNamed(p.fieldType, paramInfo.Name) {
+ replaceNode(p.fieldType, id, arg.expr)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func identsNamed(n ast.Node, name string) []*ast.Ident {
+ var ids []*ast.Ident
+ ast.Inspect(n, func(n ast.Node) bool {
+ if id, ok := n.(*ast.Ident); ok && id.Name == name {
+ ids = append(ids, id)
+ }
+ return true
+ })
+ return ids
+}
+
+// substitute implements parameter elimination by substitution.
+//
+// It considers each parameter and its corresponding argument in turn
+// and evaluate these conditions:
+//
+// - the parameter is neither address-taken nor assigned;
+// - the argument is pure;
+// - if the parameter refcount is zero, the argument must
+// not contain the last use of a local var;
+// - if the parameter refcount is > 1, the argument must be duplicable;
+// - the argument (or types.Default(argument) if it's untyped) has
+// the same type as the parameter.
+//
+// If all conditions are met then the parameter can be substituted and
+// each reference to it replaced by the argument. In that case, the
+// replaceCalleeID function is called for each reference to the
+// parameter, and is provided with its relative offset and replacement
+// expression (argument), and the corresponding elements of params and
+// args are replaced by nil.
+func substitute(logf logger, caller *Caller, params []*parameter, args []*argument, effects []int, falcon falconResult, replace replacer) {
+ // Inv:
+ // in calls to variadic, len(args) >= len(params)-1
+ // in spread calls to non-variadic, len(args) < len(params)
+ // in spread calls to variadic, len(args) <= len(params)
+ // (In spread calls len(args) = 1, or 2 if call has receiver.)
+ // Non-spread variadics have been simplified away already,
+ // so the args[i] lookup is safe if we stop after the spread arg.
+ assert(len(args) <= len(params), "too many arguments")
+
+ // Collect candidates for substitution.
+ //
+ // An argument is a candidate if it is not otherwise rejected, and any free
+ // variables that are shadowed only by other parameters.
+ //
+ // Therefore, substitution candidates are represented by a graph, where edges
+ // lead from each argument to the other arguments that, if substituted, would
+ // allow the argument to be substituted. We collect these edges in the
+ // [substGraph]. Any node that is known not to be elided from the graph.
+ // Arguments in this graph with no edges are substitutable independent of
+ // other nodes, though they may be removed due to falcon or effects analysis.
+ sg := make(substGraph)
+next:
+ for i, param := range params {
+ arg := args[i]
+
+ // Check argument against parameter.
+ //
+ // Beware: don't use types.Info on arg since
+ // the syntax may be synthetic (not created by parser)
+ // and thus lacking positions and types;
+ // do it earlier (see pure/duplicable/freevars).
+
+ if arg.spread {
+ // spread => last argument, but not always last parameter
+ logf("keeping param %q and following ones: argument %s is spread",
+ param.info.Name, debugFormatNode(caller.Fset, arg.expr))
+ return // give up
+ }
+ assert(!param.variadic, "unsimplified variadic parameter")
+ if param.info.Escapes {
+ logf("keeping param %q: escapes from callee", param.info.Name)
+ continue
+ }
+ if param.info.Assigned {
+ logf("keeping param %q: assigned by callee", param.info.Name)
+ continue // callee needs the parameter variable
+ }
+ if len(param.info.Refs) > 1 && !arg.duplicable {
+ logf("keeping param %q: argument is not duplicable", param.info.Name)
+ continue // incorrect or poor style to duplicate an expression
+ }
+ if len(param.info.Refs) == 0 {
+ if arg.effects {
+ logf("keeping param %q: though unreferenced, it has effects", param.info.Name)
+ continue
+ }
+
+ // If the caller is within a function body,
+ // eliminating an unreferenced parameter might
+ // remove the last reference to a caller local var.
+ if caller.enclosingFunc != nil {
+ for free := range arg.freevars {
+ // TODO(rfindley): we can get this 100% right by looking for
+ // references among other arguments which have non-zero references
+ // within the callee.
+ if v, ok := caller.lookup(free).(*types.Var); ok && within(v.Pos(), caller.enclosingFunc.Body) && !isUsedOutsideCall(caller, v) {
+
+ // Check to see if the substituted var is used within other args
+ // whose corresponding params ARE used in the callee
+ usedElsewhere := func() bool {
+ for i, param := range params {
+ if i < len(args) && len(param.info.Refs) > 0 { // excludes original param
+ for name := range args[i].freevars {
+ if caller.lookup(name) == v {
+ return true
+ }
+ }
+ }
+ }
+ return false
+ }
+ if !usedElsewhere() {
+ logf("keeping param %q: arg contains perhaps the last reference to caller local %v @ %v",
+ param.info.Name, v, caller.Fset.PositionFor(v.Pos(), false))
+ continue next
+ }
+ }
+ }
+ }
+ }
+
+ // Arg is a potential substitution candidate: analyze its shadowing.
+ //
+ // Consider inlining a call f(z, 1) to
+ //
+ // func f(x, y int) int { z := y; return x + y + z }
+ //
+ // we can't replace x in the body by z (or any
+ // expression that has z as a free identifier) because there's an
+ // intervening declaration of z that would shadow the caller's one.
+ //
+ // However, we *could* replace x in the body by y, as long as the y
+ // parameter is also removed by substitution.
+
+ sg[arg] = nil // Absent shadowing, the arg is substitutable.
+ for free := range arg.freevars {
+ switch s := param.info.Shadow[free]; {
+ case s < 0:
+ // Shadowed by a non-parameter symbol, so arg is not substitutable.
+ delete(sg, arg)
+ case s > 0:
+ // Shadowed by a parameter; arg may be substitutable, if only shadowed
+ // by other substitutable parameters.
+ if s > len(args) {
+ // Defensive: this should not happen in the current factoring, since
+ // spread arguments are already handled.
+ delete(sg, arg)
+ }
+ if edges, ok := sg[arg]; ok {
+ sg[arg] = append(edges, args[s-1])
+ }
+ }
+ }
+ }
+
+ // Process the initial state of the substitution graph.
+ sg.prune()
+
+ // Now we check various conditions on the substituted argument set as a
+ // whole. These conditions reject substitution candidates, but since their
+ // analysis depends on the full set of candidates, we do not process side
+ // effects of their candidate rejection until after the analysis completes,
+ // in a call to prune. After pruning, we must re-run the analysis to check
+ // for additional rejections.
+ //
+ // Here's an example of that in practice:
+ //
+ // var a [3]int
+ //
+ // func falcon(x, y, z int) {
+ // _ = x + a[y+z]
+ // }
+ //
+ // func _() {
+ // var y int
+ // const x, z = 1, 2
+ // falcon(y, x, z)
+ // }
+ //
+ // In this example, arguments 0 and 1 are shadowed by each other's
+ // corresponding parameter, and so each can be substituted only if they are
+ // both substituted. But the fallible constant analysis finds a violated
+ // constraint: x + z = 3, and so the constant array index would cause a
+ // compile-time error if argument 1 (x) were substituted. Therefore,
+ // following the falcon analysis, we must also prune argument 0.
+ //
+ // As far as I (rfindley) can tell, the falcon analysis should always succeed
+ // after the first pass, as it's not possible for additional bindings to
+ // cause new constraint failures. Nevertheless, we re-run it to be sure.
+ //
+ // However, the same cannot be said of the effects analysis, as demonstrated
+ // by this example:
+ //
+ // func effects(w, x, y, z int) {
+ // _ = x + w + y + z
+ // }
+
+ // func _() {
+ // v := 0
+ // w := func() int { v++; return 0 }
+ // x := func() int { v++; return 0 }
+ // y := func() int { v++; return 0 }
+ // effects(x(), w(), y(), x()) //@ inline(re"effects", effects)
+ // }
+ //
+ // In this example, arguments 0, 1, and 3 are related by the substitution
+ // graph. The first effects analysis implies that arguments 0 and 1 must be
+ // bound, and therefore argument 3 must be bound. But then a subsequent
+ // effects analysis forces argument 2 to also be bound.
+
+ // Reject constant arguments as substitution candidates if they cause
+ // violation of falcon constraints.
+ //
+ // Keep redoing the analysis until we no longer reject additional arguments,
+ // as the set of substituted parameters affects the falcon package.
+ for checkFalconConstraints(logf, params, args, falcon, sg) {
+ sg.prune()
+ }
+
+ // As a final step, introduce bindings to resolve any
+ // evaluation order hazards. This must be done last, as
+ // additional subsequent bindings could introduce new hazards.
+ //
+ // As with the falcon analysis, keep redoing the analysis until the no more
+ // arguments are rejected.
+ for resolveEffects(logf, args, effects, sg) {
+ sg.prune()
+ }
+
+ // The remaining candidates are safe to substitute.
+ for i, param := range params {
+ if arg := args[i]; sg.has(arg) {
+
+ // It is safe to substitute param and replace it with arg.
+ // The formatter introduces parens as needed for precedence.
+ //
+ // Because arg.expr belongs to the caller,
+ // we clone it before splicing it into the callee tree.
+ logf("replacing parameter %q by argument %q",
+ param.info.Name, debugFormatNode(caller.Fset, arg.expr))
+ for _, ref := range param.info.Refs {
+ // Apply any transformations necessary for this reference.
+ argExpr := arg.expr
+
+ // If the reference itself is being selected, and we applied desugaring
+ // (an explicit &x or *x), we can undo that desugaring here as it is
+ // not necessary for a selector. We don't need to check addressability
+ // here because if we desugared, the receiver must have been
+ // addressable.
+ if ref.IsSelectionOperand && arg.desugaredRecv {
+ switch e := argExpr.(type) {
+ case *ast.UnaryExpr:
+ argExpr = e.X
+ case *ast.StarExpr:
+ argExpr = e.X
+ }
+ }
+
+ // If the reference requires exact type agreement between parameter and
+ // argument, wrap the argument in an explicit conversion if
+ // substitution might materially change its type. (We already did the
+ // necessary shadowing check on the parameter type syntax.)
+ //
+ // The types must agree in any of these cases:
+ // - the argument affects type inference;
+ // - the reference's concrete type is assigned to an interface type;
+ // - the reference is not an assignment, nor a trivial conversion of an untyped constant.
+ //
+ // In all other cases, no explicit conversion is necessary as either
+ // the type does not matter, or must have already agreed for well-typed
+ // code.
+ //
+ // This is only needed for substituted arguments. All other arguments
+ // are given explicit types in either a binding decl or when using the
+ // literalization strategy.
+ //
+ // If the types are identical, we can eliminate
+ // redundant type conversions such as this:
+ //
+ // Callee:
+ // func f(i int32) { fmt.Println(i) }
+ // Caller:
+ // func g() { f(int32(1)) }
+ // Inlined as:
+ // func g() { fmt.Println(int32(int32(1)))
+ //
+ // Recall that non-trivial does not imply non-identical for constant
+ // conversions; however, at this point state.arguments has already
+ // re-typechecked the constant and set arg.type to its (possibly
+ // "untyped") inherent type, so the conversion from untyped 1 to int32
+ // is non-trivial even though both arg and param have identical types
+ // (int32).
+ needType := ref.AffectsInference ||
+ (ref.Assignable && ref.IfaceAssignment && !param.info.IsInterface) ||
+ (!ref.Assignable && !trivialConversion(arg.constant, arg.typ, param.obj.Type()))
+
+ if needType &&
+ !types.Identical(types.Default(arg.typ), param.obj.Type()) {
+
+ // If arg.expr is already an interface call, strip it.
+ if call, ok := argExpr.(*ast.CallExpr); ok && len(call.Args) == 1 {
+ if typ, ok := isConversion(caller.Info, call); ok && isNonTypeParamInterface(typ) {
+ argExpr = call.Args[0]
+ }
+ }
+
+ argExpr = convert(param.fieldType, argExpr)
+ logf("param %q (offset %d): adding explicit %s -> %s conversion around argument",
+ param.info.Name, ref.Offset, arg.typ, param.obj.Type())
+ }
+ replace(ref.Offset, internalastutil.CloneNode(argExpr).(ast.Expr), arg.variadic)
+ }
+ params[i] = nil // substituted
+ args[i] = nil // substituted
+ }
+ }
+}
+
+// isConversion reports whether the given call is a type conversion, returning
+// (operand, true) if so.
+//
+// If the call is not a conversion, it returns (nil, false).
+func isConversion(info *types.Info, call *ast.CallExpr) (types.Type, bool) {
+ if tv, ok := info.Types[call.Fun]; ok && tv.IsType() {
+ return tv.Type, true
+ }
+ return nil, false
+}
+
+// isNonTypeParamInterface reports whether t is a non-type parameter interface
+// type.
+func isNonTypeParamInterface(t types.Type) bool {
+ return !typeparams.IsTypeParam(t) && types.IsInterface(t)
+}
+
+// isUsedOutsideCall reports whether v is used outside of caller.Call, within
+// the body of caller.enclosingFunc.
+func isUsedOutsideCall(caller *Caller, v *types.Var) bool {
+ used := false
+ ast.Inspect(caller.enclosingFunc.Body, func(n ast.Node) bool {
+ if n == caller.Call {
+ return false
+ }
+ switch n := n.(type) {
+ case *ast.Ident:
+ if use := caller.Info.Uses[n]; use == v {
+ used = true
+ }
+ case *ast.FuncType:
+ // All params are used.
+ for _, fld := range n.Params.List {
+ for _, n := range fld.Names {
+ if def := caller.Info.Defs[n]; def == v {
+ used = true
+ }
+ }
+ }
+ }
+ return !used // keep going until we find a use
+ })
+ return used
+}
+
+// checkFalconConstraints checks whether constant arguments
+// are safe to substitute (e.g. s[i] -> ""[0] is not safe.)
+//
+// Any failed constraint causes us to reject all constant arguments as
+// substitution candidates (by clearing args[i].substitution=false).
+//
+// TODO(adonovan): we could obtain a finer result rejecting only the
+// freevars of each failed constraint, and processing constraints in
+// order of increasing arity, but failures are quite rare.
+func checkFalconConstraints(logf logger, params []*parameter, args []*argument, falcon falconResult, sg substGraph) bool {
+ // Create a dummy package, as this is the only
+ // way to create an environment for CheckExpr.
+ pkg := types.NewPackage("falcon", "falcon")
+
+ // Declare types used by constraints.
+ for _, typ := range falcon.Types {
+ logf("falcon env: type %s %s", typ.Name, types.Typ[typ.Kind])
+ pkg.Scope().Insert(types.NewTypeName(token.NoPos, pkg, typ.Name, types.Typ[typ.Kind]))
+ }
+
+ // Declared constants and variables for parameters.
+ nconst := 0
+ for i, param := range params {
+ name := param.info.Name
+ if name == "" {
+ continue // unreferenced
+ }
+ arg := args[i]
+ if arg.constant != nil && sg.has(arg) && param.info.FalconType != "" {
+ t := pkg.Scope().Lookup(param.info.FalconType).Type()
+ pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, t, arg.constant))
+ logf("falcon env: const %s %s = %v", name, param.info.FalconType, arg.constant)
+ nconst++
+ } else {
+ v := types.NewVar(token.NoPos, pkg, name, arg.typ)
+ typesinternal.SetVarKind(v, typesinternal.PackageVar)
+ pkg.Scope().Insert(v)
+ logf("falcon env: var %s %s", name, arg.typ)
+ }
+ }
+ if nconst == 0 {
+ return false // nothing to do
+ }
+
+ // Parse and evaluate the constraints in the environment.
+ fset := token.NewFileSet()
+ removed := false
+ for _, falcon := range falcon.Constraints {
+ expr, err := parser.ParseExprFrom(fset, "falcon", falcon, 0)
+ if err != nil {
+ panic(fmt.Sprintf("failed to parse falcon constraint %s: %v", falcon, err))
+ }
+ if err := types.CheckExpr(fset, pkg, token.NoPos, expr, nil); err != nil {
+ logf("falcon: constraint %s violated: %v", falcon, err)
+ for j, arg := range args {
+ if arg.constant != nil && sg.has(arg) {
+ logf("keeping param %q due falcon violation", params[j].info.Name)
+ removed = sg.remove(arg) || removed
+ }
+ }
+ break
+ }
+ logf("falcon: constraint %s satisfied", falcon)
+ }
+ return removed
+}
+
+// resolveEffects marks arguments as non-substitutable to resolve
+// hazards resulting from the callee evaluation order described by the
+// effects list.
+//
+// To do this, each argument is categorized as a read (R), write (W),
+// or pure. A hazard occurs when the order of evaluation of a W
+// changes with respect to any R or W. Pure arguments can be
+// effectively ignored, as they can be safely evaluated in any order.
+//
+// The callee effects list contains the index of each parameter in the
+// order it is first evaluated during execution of the callee. In
+// addition, the two special values R∞ and W∞ indicate the relative
+// position of the callee's first non-parameter read and its first
+// effects (or other unknown behavior).
+// For example, the list [0 2 1 R∞ 3 W∞] for func(a, b, c, d)
+// indicates that the callee referenced parameters a, c, and b,
+// followed by an arbitrary read, then parameter d, and finally
+// unknown behavior.
+//
+// When an argument is marked as not substitutable, we say that it is
+// 'bound', in the sense that its evaluation occurs in a binding decl
+// or literalized call. Such bindings always occur in the original
+// callee parameter order.
+//
+// In this context, "resolving hazards" means binding arguments so
+// that they are evaluated in a valid, hazard-free order. A trivial
+// solution to this problem would be to bind all arguments, but of
+// course that's not useful. The goal is to bind as few arguments as
+// possible.
+//
+// The algorithm proceeds by inspecting arguments in reverse parameter
+// order (right to left), preserving the invariant that every
+// higher-ordered argument is either already substituted or does not
+// need to be substituted. At each iteration, if there is an
+// evaluation hazard in the callee effects relative to the current
+// argument, the argument must be bound. Subsequently, if the argument
+// is bound for any reason, each lower-ordered argument must also be
+// bound if either the argument or lower-order argument is a
+// W---otherwise the binding itself would introduce a hazard.
+//
+// Thus, after each iteration, there are no hazards relative to the
+// current argument. Subsequent iterations cannot introduce hazards
+// with that argument because they can result only in additional
+// binding of lower-ordered arguments.
+func resolveEffects(logf logger, args []*argument, effects []int, sg substGraph) bool {
+ effectStr := func(effects bool, idx int) string {
+ i := fmt.Sprint(idx)
+ if idx == len(args) {
+ i = "∞"
+ }
+ return string("RW"[btoi(effects)]) + i
+ }
+ removed := false
+ for i := len(args) - 1; i >= 0; i-- {
+ argi := args[i]
+ if sg.has(argi) && !argi.pure {
+ // i is not bound: check whether it must be bound due to hazards.
+ idx := slices.Index(effects, i)
+ if idx >= 0 {
+ for _, j := range effects[:idx] {
+ var (
+ ji int // effective param index
+ jw bool // j is a write
+ )
+ if j == winf || j == rinf {
+ jw = j == winf
+ ji = len(args)
+ } else {
+ jw = args[j].effects
+ ji = j
+ }
+ if ji > i && (jw || argi.effects) { // out of order evaluation
+ logf("binding argument %s: preceded by %s",
+ effectStr(argi.effects, i), effectStr(jw, ji))
+
+ removed = sg.remove(argi) || removed
+ break
+ }
+ }
+ }
+ }
+ if !sg.has(argi) {
+ for j := 0; j < i; j++ {
+ argj := args[j]
+ if argj.pure {
+ continue
+ }
+ if (argi.effects || argj.effects) && sg.has(argj) {
+ logf("binding argument %s: %s is bound",
+ effectStr(argj.effects, j), effectStr(argi.effects, i))
+
+ removed = sg.remove(argj) || removed
+ }
+ }
+ }
+ }
+ return removed
+}
+
+// A substGraph is a directed graph representing arguments that may be
+// substituted, provided all of their related arguments (or "dependencies") are
+// also substituted. The candidates arguments for substitution are the keys in
+// this graph, and the edges represent shadowing of free variables of the key
+// by parameters corresponding to the dependency arguments.
+//
+// Any argument not present as a map key is known not to be substitutable. Some
+// arguments may have edges leading to other arguments that are not present in
+// the graph. In this case, those arguments also cannot be substituted, because
+// they have free variables that are shadowed by parameters that cannot be
+// substituted. Calling [substGraph.prune] removes these arguments from the
+// graph.
+//
+// The 'prune' operation is not built into the 'remove' step both because
+// analyses (falcon, effects) need local information about each argument
+// independent of dependencies, and for the efficiency of pruning once en masse
+// after each analysis.
+type substGraph map[*argument][]*argument
+
+// has reports whether arg is a candidate for substitution.
+func (g substGraph) has(arg *argument) bool {
+ _, ok := g[arg]
+ return ok
+}
+
+// remove marks arg as not substitutable, reporting whether the arg was
+// previously substitutable.
+//
+// remove does not have side effects on other arguments that may be
+// unsubstitutable as a result of their dependency being removed.
+// Call [substGraph.prune] to propagate these side effects, removing dependent
+// arguments.
+func (g substGraph) remove(arg *argument) bool {
+ pre := len(g)
+ delete(g, arg)
+ return len(g) < pre
+}
+
+// prune updates the graph to remove any keys that reach other arguments not
+// present in the graph.
+func (g substGraph) prune() {
+ // visit visits the forward transitive closure of arg and reports whether any
+ // missing argument was encountered, removing all nodes on the path to it
+ // from arg.
+ //
+ // The seen map is used for cycle breaking. In the presence of cycles, visit
+ // may report a false positive for an intermediate argument. For example,
+ // consider the following graph, where only a and b are candidates for
+ // substitution (meaning, only a and b are present in the graph).
+ //
+ // a ↔ b
+ // ↓
+ // [c]
+ //
+ // In this case, starting a visit from a, visit(b, seen) may report 'true',
+ // because c has not yet been considered. For this reason, we must guarantee
+ // that visit is called with an empty seen map at least once for each node.
+ var visit func(*argument, map[*argument]unit) bool
+ visit = func(arg *argument, seen map[*argument]unit) bool {
+ deps, ok := g[arg]
+ if !ok {
+ return false
+ }
+ if _, ok := seen[arg]; !ok {
+ seen[arg] = unit{}
+ for _, dep := range deps {
+ if !visit(dep, seen) {
+ delete(g, arg)
+ return false
+ }
+ }
+ }
+ return true
+ }
+ for arg := range g {
+ // Remove any argument that is, or transitively depends upon,
+ // an unsubstitutable argument.
+ //
+ // Each visitation gets a fresh cycle-breaking set.
+ visit(arg, make(map[*argument]unit))
+ }
+}
+
+// updateCalleeParams updates the calleeDecl syntax to remove
+// substituted parameters and move the receiver (if any) to the head
+// of the ordinary parameters.
+func updateCalleeParams(calleeDecl *ast.FuncDecl, params []*parameter) {
+ // The logic is fiddly because of the three forms of ast.Field:
+ //
+ // func(int), func(x int), func(x, y int)
+ //
+ // Also, ensure that all remaining parameters are named
+ // to avoid a mix of named/unnamed when joining (recv, params...).
+ // func (T) f(int, bool) -> (_ T, _ int, _ bool)
+ // (Strictly, we need do this only for methods and only when
+ // the namednesses of Recv and Params differ; that might be tidier.)
+
+ paramIdx := 0 // index in original parameter list (incl. receiver)
+ var newParams []*ast.Field
+ filterParams := func(field *ast.Field) {
+ var names []*ast.Ident
+ if field.Names == nil {
+ // Unnamed parameter field (e.g. func f(int)
+ if params[paramIdx] != nil {
+ // Give it an explicit name "_" since we will
+ // make the receiver (if any) a regular parameter
+ // and one cannot mix named and unnamed parameters.
+ names = append(names, makeIdent("_"))
+ }
+ paramIdx++
+ } else {
+ // Named parameter field e.g. func f(x, y int)
+ // Remove substituted parameters in place.
+ // If all were substituted, delete field.
+ for _, id := range field.Names {
+ if pinfo := params[paramIdx]; pinfo != nil {
+ // Rename unreferenced parameters with "_".
+ // This is crucial for binding decls, since
+ // unlike parameters, they are subject to
+ // "unreferenced var" checks.
+ if len(pinfo.info.Refs) == 0 {
+ id = makeIdent("_")
+ }
+ names = append(names, id)
+ }
+ paramIdx++
+ }
+ }
+ if names != nil {
+ newParams = append(newParams, &ast.Field{
+ Names: names,
+ Type: field.Type,
+ })
+ }
+ }
+ if calleeDecl.Recv != nil {
+ filterParams(calleeDecl.Recv.List[0])
+ calleeDecl.Recv = nil
+ }
+ for _, field := range calleeDecl.Type.Params.List {
+ filterParams(field)
+ }
+ calleeDecl.Type.Params.List = newParams
+}
+
+// bindingDeclInfo records information about the binding decl produced by
+// createBindingDecl.
+type bindingDeclInfo struct {
+ names map[string]bool // names bound by the binding decl; possibly empty
+ stmt ast.Stmt // the binding decl itself
+}
+
+// createBindingDecl constructs a "binding decl" that implements
+// parameter assignment and declares any named result variables
+// referenced by the callee. It returns nil if there were no
+// unsubstituted parameters.
+//
+// It may not always be possible to create the decl (e.g. due to
+// shadowing), in which case it also returns nil; but if it succeeds,
+// the declaration may be used by reduction strategies to relax the
+// requirement that all parameters have been substituted.
+//
+// For example, a call:
+//
+// f(a0, a1, a2)
+//
+// where:
+//
+// func f(p0, p1 T0, p2 T1) { body }
+//
+// reduces to:
+//
+// {
+// var (
+// p0, p1 T0 = a0, a1
+// p2 T1 = a2
+// )
+// body
+// }
+//
+// so long as p0, p1 ∉ freevars(T1) or freevars(a2), and so on,
+// because each spec is statically resolved in sequence and
+// dynamically assigned in sequence. By contrast, all
+// parameters are resolved simultaneously and assigned
+// simultaneously.
+//
+// The pX names should already be blank ("_") if the parameter
+// is unreferenced; this avoids "unreferenced local var" checks.
+//
+// Strategies may impose additional checks on return
+// conversions, labels, defer, etc.
+func createBindingDecl(logf logger, caller *Caller, args []*argument, calleeDecl *ast.FuncDecl, results []*paramInfo) *bindingDeclInfo {
+ // Spread calls are tricky as they may not align with the
+ // parameters' field groupings nor types.
+ // For example, given
+ // func g() (int, string)
+ // the call
+ // f(g())
+ // is legal with these decls of f:
+ // func f(int, string)
+ // func f(x, y any)
+ // func f(x, y ...any)
+ // TODO(adonovan): support binding decls for spread calls by
+ // splitting parameter groupings as needed.
+ if lastArg := last(args); lastArg != nil && lastArg.spread {
+ logf("binding decls not yet supported for spread calls")
+ return nil
+ }
+
+ var (
+ specs []ast.Spec
+ names = make(map[string]bool) // names defined by previous specs
+ )
+ // shadow reports whether any name referenced by spec is
+ // shadowed by a name declared by a previous spec (since,
+ // unlike parameters, each spec of a var decl is within the
+ // scope of the previous specs).
+ shadow := func(spec *ast.ValueSpec) bool {
+ // Compute union of free names of type and values
+ // and detect shadowing. Values is the arguments
+ // (caller syntax), so we can use type info.
+ // But Type is the untyped callee syntax,
+ // so we have to use a syntax-only algorithm.
+ const includeComplitIdents = true
+ free := free.Names(spec.Type, includeComplitIdents)
+ for _, value := range spec.Values {
+ for name := range freeVars(caller.Info, value) {
+ free[name] = true
+ }
+ }
+ for name := range free {
+ if names[name] {
+ logf("binding decl would shadow free name %q", name)
+ return true
+ }
+ }
+ for _, id := range spec.Names {
+ if id.Name != "_" {
+ names[id.Name] = true
+ }
+ }
+ return false
+ }
+
+ // parameters
+ //
+ // Bind parameters that were not eliminated through
+ // substitution. (Non-nil arguments correspond to the
+ // remaining parameters in calleeDecl.)
+ var values []ast.Expr
+ for _, arg := range args {
+ if arg != nil {
+ values = append(values, arg.expr)
+ }
+ }
+ for _, field := range calleeDecl.Type.Params.List {
+ // Each field (param group) becomes a ValueSpec.
+ spec := &ast.ValueSpec{
+ Names: cleanNodes(field.Names),
+ Type: cleanNode(field.Type),
+ Values: values[:len(field.Names)],
+ }
+ values = values[len(field.Names):]
+ if shadow(spec) {
+ return nil
+ }
+ specs = append(specs, spec)
+ }
+ assert(len(values) == 0, "args/params mismatch")
+
+ // results
+ //
+ // Add specs to declare any named result
+ // variables that are referenced by the body.
+ if calleeDecl.Type.Results != nil {
+ resultIdx := 0
+ for _, field := range calleeDecl.Type.Results.List {
+ if field.Names == nil {
+ resultIdx++
+ continue // unnamed field
+ }
+ var names []*ast.Ident
+ for _, id := range field.Names {
+ if len(results[resultIdx].Refs) > 0 {
+ names = append(names, id)
+ }
+ resultIdx++
+ }
+ if len(names) > 0 {
+ spec := &ast.ValueSpec{
+ Names: cleanNodes(names),
+ Type: cleanNode(field.Type),
+ }
+ if shadow(spec) {
+ return nil
+ }
+ specs = append(specs, spec)
+ }
+ }
+ }
+
+ if len(specs) == 0 {
+ logf("binding decl not needed: all parameters substituted")
+ return nil
+ }
+
+ stmt := &ast.DeclStmt{
+ Decl: &ast.GenDecl{
+ Tok: token.VAR,
+ Specs: specs,
+ },
+ }
+ logf("binding decl: %s", debugFormatNode(caller.Fset, stmt))
+ return &bindingDeclInfo{names: names, stmt: stmt}
+}
+
+// lookup does a symbol lookup in the lexical environment of the caller.
+func (caller *Caller) lookup(name string) types.Object {
+ pos := caller.Call.Pos()
+ for _, n := range caller.path {
+ if scope := scopeFor(caller.Info, n); scope != nil {
+ if _, obj := scope.LookupParent(name, pos); obj != nil {
+ return obj
+ }
+ }
+ }
+ return nil
+}
+
+func scopeFor(info *types.Info, n ast.Node) *types.Scope {
+ // The function body scope (containing not just params)
+ // is associated with the function's type, not body.
+ switch fn := n.(type) {
+ case *ast.FuncDecl:
+ n = fn.Type
+ case *ast.FuncLit:
+ n = fn.Type
+ }
+ return info.Scopes[n]
+}
+
+// -- predicates over expressions --
+
+// freeVars returns the names of all free identifiers of e:
+// those lexically referenced by it but not defined within it.
+// (Fields and methods are not included.)
+func freeVars(info *types.Info, e ast.Expr) map[string]bool {
+ free := make(map[string]bool)
+ ast.Inspect(e, func(n ast.Node) bool {
+ if id, ok := n.(*ast.Ident); ok {
+ // The isField check is so that we don't treat T{f: 0} as a ref to f.
+ if obj, ok := info.Uses[id]; ok && !within(obj.Pos(), e) && !isField(obj) {
+ free[obj.Name()] = true
+ }
+ }
+ return true
+ })
+ return free
+}
+
+// effects reports whether an expression might change the state of the
+// program (through function calls and channel receives) and affect
+// the evaluation of subsequent expressions.
+func (st *state) effects(info *types.Info, expr ast.Expr) bool {
+ effects := false
+ ast.Inspect(expr, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.FuncLit:
+ return false // prune descent
+
+ case *ast.CallExpr:
+ if info.Types[n.Fun].IsType() {
+ // A conversion T(x) has only the effect of its operand.
+ } else if !typesinternal.CallsPureBuiltin(info, n) {
+ // A handful of built-ins have no effect
+ // beyond those of their arguments.
+ // All other calls (including append, copy, recover)
+ // have unknown effects.
+ //
+ // As with 'pure', there is room for
+ // improvement by inspecting the callee.
+ effects = true
+ }
+
+ case *ast.UnaryExpr:
+ if n.Op == token.ARROW { // <-ch
+ effects = true
+ }
+ }
+ return true
+ })
+
+ // Even if consideration of effects is not desired,
+ // we continue to compute, log, and discard them.
+ if st.opts.IgnoreEffects && effects {
+ effects = false
+ st.opts.Logf("ignoring potential effects of argument %s",
+ debugFormatNode(st.caller.Fset, expr))
+ }
+
+ return effects
+}
+
+// pure reports whether an expression has the same result no matter
+// when it is executed relative to other expressions, so it can be
+// commuted with any other expression or statement without changing
+// its meaning.
+//
+// An expression is considered impure if it reads the contents of any
+// variable, with the exception of "single assignment" local variables
+// (as classified by the provided callback), which are never updated
+// after their initialization.
+//
+// Pure does not imply duplicable: for example, new(T) and T{} are
+// pure expressions but both return a different value each time they
+// are evaluated, so they are not safe to duplicate.
+//
+// Purity does not imply freedom from run-time panics. We assume that
+// target programs do not encounter run-time panics nor depend on them
+// for correct operation.
+//
+// TODO(adonovan): add unit tests of this function.
+func pure(info *types.Info, assign1 func(*types.Var) bool, e ast.Expr) bool {
+ var pure func(e ast.Expr) bool
+ pure = func(e ast.Expr) bool {
+ switch e := e.(type) {
+ case *ast.ParenExpr:
+ return pure(e.X)
+
+ case *ast.Ident:
+ if v, ok := info.Uses[e].(*types.Var); ok {
+ // In general variables are impure
+ // as they may be updated, but
+ // single-assignment local variables
+ // never change value.
+ //
+ // We assume all package-level variables
+ // may be updated, but for non-exported
+ // ones we could do better by analyzing
+ // the complete package.
+ return !isPkgLevel(v) && assign1(v)
+ }
+
+ // All other kinds of reference are pure.
+ return true
+
+ case *ast.FuncLit:
+ // A function literal may allocate a closure that
+ // references mutable variables, but mutation
+ // cannot be observed without calling the function,
+ // and calls are considered impure.
+ return true
+
+ case *ast.BasicLit:
+ return true
+
+ case *ast.UnaryExpr: // + - ! ^ & but not <-
+ return e.Op != token.ARROW && pure(e.X)
+
+ case *ast.BinaryExpr: // arithmetic, shifts, comparisons, &&/||
+ return pure(e.X) && pure(e.Y)
+
+ case *ast.CallExpr:
+ // A conversion is as pure as its operand.
+ if info.Types[e.Fun].IsType() {
+ return pure(e.Args[0])
+ }
+
+ // Calls to some built-ins are as pure as their arguments.
+ if typesinternal.CallsPureBuiltin(info, e) {
+ for _, arg := range e.Args {
+ if !pure(arg) {
+ return false
+ }
+ }
+ return true
+ }
+
+ // All other calls are impure, so we can
+ // reject them without even looking at e.Fun.
+ //
+ // More sophisticated analysis could infer purity in
+ // commonly used functions such as strings.Contains;
+ // perhaps we could offer the client a hook so that
+ // go/analysis-based implementation could exploit the
+ // results of a purity analysis. But that would make
+ // the inliner's choices harder to explain.
+ return false
+
+ case *ast.CompositeLit:
+ // T{...} is as pure as its elements.
+ for _, elt := range e.Elts {
+ if kv, ok := elt.(*ast.KeyValueExpr); ok {
+ if !pure(kv.Value) {
+ return false
+ }
+ if id, ok := kv.Key.(*ast.Ident); ok {
+ if v, ok := info.Uses[id].(*types.Var); ok && v.IsField() {
+ continue // struct {field: value}
+ }
+ }
+ // map/slice/array {key: value}
+ if !pure(kv.Key) {
+ return false
+ }
+
+ } else if !pure(elt) {
+ return false
+ }
+ }
+ return true
+
+ case *ast.SelectorExpr:
+ if seln, ok := info.Selections[e]; ok {
+ // See types.SelectionKind for background.
+ switch seln.Kind() {
+ case types.MethodExpr:
+ // A method expression T.f acts like a
+ // reference to a func decl, so it is pure.
+ return true
+
+ case types.MethodVal, types.FieldVal:
+ // A field or method selection x.f is pure
+ // if x is pure and the selection does
+ // not indirect a pointer.
+ return !indirectSelection(seln) && pure(e.X)
+
+ default:
+ panic(seln)
+ }
+ } else {
+ // A qualified identifier is
+ // treated like an unqualified one.
+ return pure(e.Sel)
+ }
+
+ case *ast.StarExpr:
+ return false // *ptr depends on the state of the heap
+
+ default:
+ return false
+ }
+ }
+ return pure(e)
+}
+
+// duplicable reports whether it is appropriate for the expression to
+// be freely duplicated.
+//
+// Given the declaration
+//
+// func f(x T) T { return x + g() + x }
+//
+// an argument y is considered duplicable if we would wish to see a
+// call f(y) simplified to y+g()+y. This is true for identifiers,
+// integer literals, unary negation, and selectors x.f where x is not
+// a pointer. But we would not wish to duplicate expressions that:
+// - have side effects (e.g. nearly all calls),
+// - are not referentially transparent (e.g. &T{}, ptr.field, *ptr), or
+// - are long (e.g. "huge string literal").
+func duplicable(info *types.Info, e ast.Expr) bool {
+ switch e := e.(type) {
+ case *ast.ParenExpr:
+ return duplicable(info, e.X)
+
+ case *ast.Ident:
+ return true
+
+ case *ast.BasicLit:
+ v := info.Types[e].Value
+ switch e.Kind {
+ case token.INT:
+ return true // any int
+ case token.STRING:
+ return consteq(v, kZeroString) // only ""
+ case token.FLOAT:
+ return consteq(v, kZeroFloat) || consteq(v, kOneFloat) // only 0.0 or 1.0
+ }
+
+ case *ast.UnaryExpr: // e.g. +1, -1
+ return (e.Op == token.ADD || e.Op == token.SUB) && duplicable(info, e.X)
+
+ case *ast.CompositeLit:
+ // Empty struct or array literals T{} are duplicable.
+ // (Non-empty literals are too verbose, and slice/map
+ // literals allocate indirect variables.)
+ if len(e.Elts) == 0 {
+ switch info.TypeOf(e).Underlying().(type) {
+ case *types.Struct, *types.Array:
+ return true
+ }
+ }
+ return false
+
+ case *ast.CallExpr:
+ // Treat type conversions as duplicable if they do not observably allocate.
+ // The only cases of observable allocations are
+ // the `[]byte(string)` and `[]rune(string)` conversions.
+ //
+ // Duplicating string([]byte) conversions increases
+ // allocation but doesn't change behavior, but the
+ // reverse, []byte(string), allocates a distinct array,
+ // which is observable.
+
+ if !info.Types[e.Fun].IsType() { // check whether e.Fun is a type conversion
+ return false
+ }
+
+ fun := info.TypeOf(e.Fun)
+ arg := info.TypeOf(e.Args[0])
+
+ switch fun := fun.Underlying().(type) {
+ case *types.Slice:
+ // Do not mark []byte(string) and []rune(string) as duplicable.
+ elem, ok := fun.Elem().Underlying().(*types.Basic)
+ if ok && (elem.Kind() == types.Rune || elem.Kind() == types.Byte) {
+ from, ok := arg.Underlying().(*types.Basic)
+ isString := ok && from.Info()&types.IsString != 0
+ return !isString
+ }
+ case *types.TypeParam:
+ return false // be conservative
+ }
+ return true
+
+ case *ast.SelectorExpr:
+ if seln, ok := info.Selections[e]; ok {
+ // A field or method selection x.f is referentially
+ // transparent if it does not indirect a pointer.
+ return !indirectSelection(seln)
+ }
+ // A qualified identifier pkg.Name is referentially transparent.
+ return true
+ }
+ return false
+}
+
+func consteq(x, y constant.Value) bool {
+ return constant.Compare(x, token.EQL, y)
+}
+
+var (
+ kZeroInt = constant.MakeInt64(0)
+ kZeroString = constant.MakeString("")
+ kZeroFloat = constant.MakeFloat64(0.0)
+ kOneFloat = constant.MakeFloat64(1.0)
+)
+
+// -- inline helpers --
+
+func assert(cond bool, msg string) {
+ if !cond {
+ panic(msg)
+ }
+}
+
+// blanks returns a slice of n > 0 blank identifiers.
+func blanks[E ast.Expr](n int) []E {
+ if n == 0 {
+ panic("blanks(0)")
+ }
+ res := make([]E, n)
+ for i := range res {
+ res[i] = ast.Expr(makeIdent("_")).(E) // ugh
+ }
+ return res
+}
+
+func makeIdent(name string) *ast.Ident {
+ return &ast.Ident{Name: name}
+}
+
+// importedPkgName returns the PkgName object declared by an ImportSpec.
+// TODO(adonovan): make this a method of types.Info (#62037).
+func importedPkgName(info *types.Info, imp *ast.ImportSpec) (*types.PkgName, bool) {
+ var obj types.Object
+ if imp.Name != nil {
+ obj = info.Defs[imp.Name]
+ } else {
+ obj = info.Implicits[imp]
+ }
+ pkgname, ok := obj.(*types.PkgName)
+ return pkgname, ok
+}
+
+func isPkgLevel(obj types.Object) bool {
+ // TODO(adonovan): consider using the simpler obj.Parent() ==
+ // obj.Pkg().Scope() instead. But be sure to test carefully
+ // with instantiations of generics.
+ return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
+
+// callContext returns the two nodes immediately enclosing the call
+// (specified as a PathEnclosingInterval), ignoring parens.
+func callContext(callPath []ast.Node) (parent, grandparent ast.Node) {
+ _ = callPath[0].(*ast.CallExpr) // sanity check
+ for _, n := range callPath[1:] {
+ if !is[*ast.ParenExpr](n) {
+ if parent == nil {
+ parent = n
+ } else {
+ return parent, n
+ }
+ }
+ }
+ return parent, nil
+}
+
+// hasLabelConflict reports whether the set of labels of the function
+// enclosing the call (specified as a PathEnclosingInterval)
+// intersects with the set of callee labels.
+func hasLabelConflict(callPath []ast.Node, calleeLabels []string) bool {
+ labels := callerLabels(callPath)
+ for _, label := range calleeLabels {
+ if labels[label] {
+ return true // conflict
+ }
+ }
+ return false
+}
+
+// callerLabels returns the set of control labels in the function (if
+// any) enclosing the call (specified as a PathEnclosingInterval).
+func callerLabels(callPath []ast.Node) map[string]bool {
+ var callerBody *ast.BlockStmt
+ switch f := callerFunc(callPath).(type) {
+ case *ast.FuncDecl:
+ callerBody = f.Body
+ case *ast.FuncLit:
+ callerBody = f.Body
+ }
+ var labels map[string]bool
+ if callerBody != nil {
+ ast.Inspect(callerBody, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.FuncLit:
+ return false // prune traversal
+ case *ast.LabeledStmt:
+ if labels == nil {
+ labels = make(map[string]bool)
+ }
+ labels[n.Label.Name] = true
+ }
+ return true
+ })
+ }
+ return labels
+}
+
+// callerFunc returns the innermost Func{Decl,Lit} node enclosing the
+// call (specified as a PathEnclosingInterval).
+func callerFunc(callPath []ast.Node) ast.Node {
+ _ = callPath[0].(*ast.CallExpr) // sanity check
+ for _, n := range callPath[1:] {
+ if is[*ast.FuncDecl](n) || is[*ast.FuncLit](n) {
+ return n
+ }
+ }
+ return nil
+}
+
+// callStmt reports whether the function call (specified
+// as a PathEnclosingInterval) appears within an ExprStmt,
+// and returns it if so.
+//
+// If unrestricted, callStmt returns nil if the ExprStmt f() appears
+// in a restricted context (such as "if f(); cond {") where it cannot
+// be replaced by an arbitrary statement. (See "statement theory".)
+func callStmt(callPath []ast.Node, unrestricted bool) *ast.ExprStmt {
+ parent, _ := callContext(callPath)
+ stmt, ok := parent.(*ast.ExprStmt)
+ if ok && unrestricted {
+ switch callPath[slices.Index(callPath, ast.Node(stmt))+1].(type) {
+ case *ast.LabeledStmt,
+ *ast.BlockStmt,
+ *ast.CaseClause,
+ *ast.CommClause:
+ // unrestricted
+ default:
+ // TODO(adonovan): handle restricted
+ // XYZStmt.Init contexts (but not ForStmt.Post)
+ // by creating a block around the if/for/switch:
+ // "if f(); cond {" -> "{ stmts; if cond {"
+
+ return nil // restricted
+ }
+ }
+ return stmt
+}
+
+// Statement theory
+//
+// These are all the places a statement may appear in the AST:
+//
+// LabeledStmt.Stmt Stmt -- any
+// BlockStmt.List []Stmt -- any (but see switch/select)
+// IfStmt.Init Stmt? -- simple
+// IfStmt.Body BlockStmt
+// IfStmt.Else Stmt? -- IfStmt or BlockStmt
+// CaseClause.Body []Stmt -- any
+// SwitchStmt.Init Stmt? -- simple
+// SwitchStmt.Body BlockStmt -- CaseClauses only
+// TypeSwitchStmt.Init Stmt? -- simple
+// TypeSwitchStmt.Assign Stmt -- AssignStmt(TypeAssertExpr) or ExprStmt(TypeAssertExpr)
+// TypeSwitchStmt.Body BlockStmt -- CaseClauses only
+// CommClause.Comm Stmt? -- SendStmt or ExprStmt(UnaryExpr) or AssignStmt(UnaryExpr)
+// CommClause.Body []Stmt -- any
+// SelectStmt.Body BlockStmt -- CommClauses only
+// ForStmt.Init Stmt? -- simple
+// ForStmt.Post Stmt? -- simple
+// ForStmt.Body BlockStmt
+// RangeStmt.Body BlockStmt
+//
+// simple = AssignStmt | SendStmt | IncDecStmt | ExprStmt.
+//
+// A BlockStmt cannot replace an ExprStmt in
+// {If,Switch,TypeSwitch}Stmt.Init or ForStmt.Post.
+// That is allowed only within:
+// LabeledStmt.Stmt Stmt
+// BlockStmt.List []Stmt
+// CaseClause.Body []Stmt
+// CommClause.Body []Stmt
+
+// replaceNode performs a destructive update of the tree rooted at
+// root, replacing each occurrence of "from" with "to". If to is nil and
+// the element is within a slice, the slice element is removed.
+//
+// The root itself cannot be replaced; an attempt will panic.
+//
+// This function must not be called on the caller's syntax tree.
+//
+// TODO(adonovan): polish this up and move it to astutil package.
+// TODO(adonovan): needs a unit test.
+func replaceNode(root ast.Node, from, to ast.Node) {
+ if from == nil {
+ panic("from == nil")
+ }
+ if reflect.ValueOf(from).IsNil() {
+ panic(fmt.Sprintf("from == (%T)(nil)", from))
+ }
+ if from == root {
+ panic("from == root")
+ }
+ found := false
+ var parent reflect.Value // parent variable of interface type, containing a pointer
+ var visit func(reflect.Value)
+ visit = func(v reflect.Value) {
+ switch v.Kind() {
+ case reflect.Pointer:
+ if v.Interface() == from {
+ found = true
+
+ // If v is a struct field or array element
+ // (e.g. Field.Comment or Field.Names[i])
+ // then it is addressable (a pointer variable).
+ //
+ // But if it was the value an interface
+ // (e.g. *ast.Ident within ast.Node)
+ // then it is non-addressable, and we need
+ // to set the enclosing interface (parent).
+ if !v.CanAddr() {
+ v = parent
+ }
+
+ // to=nil => use zero value
+ var toV reflect.Value
+ if to != nil {
+ toV = reflect.ValueOf(to)
+ } else {
+ toV = reflect.Zero(v.Type()) // e.g. ast.Expr(nil)
+ }
+ v.Set(toV)
+
+ } else if !v.IsNil() {
+ switch v.Interface().(type) {
+ case *ast.Object, *ast.Scope:
+ // Skip fields of types potentially involved in cycles.
+ default:
+ visit(v.Elem())
+ }
+ }
+
+ case reflect.Struct:
+ for i := range v.Type().NumField() {
+ visit(v.Field(i))
+ }
+
+ case reflect.Slice:
+ compact := false
+ for i := range v.Len() {
+ visit(v.Index(i))
+ if v.Index(i).IsNil() {
+ compact = true
+ }
+ }
+ if compact {
+ // Elements were deleted. Eliminate nils.
+ // (Do this is a second pass to avoid
+ // unnecessary writes in the common case.)
+ j := 0
+ for i := range v.Len() {
+ if !v.Index(i).IsNil() {
+ v.Index(j).Set(v.Index(i))
+ j++
+ }
+ }
+ v.SetLen(j)
+ }
+ case reflect.Interface:
+ parent = v
+ visit(v.Elem())
+
+ case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer:
+ panic(v) // unreachable in AST
+ default:
+ // bool, string, number: nop
+ }
+ parent = reflect.Value{}
+ }
+ visit(reflect.ValueOf(root))
+ if !found {
+ panic(fmt.Sprintf("%T not found", from))
+ }
+}
+
+// cleanNode returns a clone of node with positions cleared.
+//
+// It should be used for any callee nodes that are formatted using the caller
+// file set.
+func cleanNode[T ast.Node](node T) T {
+ clone := internalastutil.CloneNode(node)
+ clearPositions(clone)
+ return clone
+}
+
+func cleanNodes[T ast.Node](nodes []T) []T {
+ var clean []T
+ for _, node := range nodes {
+ clean = append(clean, cleanNode(node))
+ }
+ return clean
+}
+
+// clearPositions destroys token.Pos information within the tree rooted at root,
+// as positions in callee trees may cause caller comments to be emitted prematurely.
+//
+// In general it isn't safe to clear a valid Pos because some of them
+// (e.g. CallExpr.Ellipsis, TypeSpec.Assign) are significant to
+// go/printer, so this function sets each non-zero Pos to 1, which
+// suffices to avoid advancing the printer's comment cursor.
+//
+// This function mutates its argument; do not invoke on caller syntax.
+//
+// TODO(adonovan): remove this horrendous workaround when #20744 is finally fixed.
+func clearPositions(root ast.Node) {
+ posType := reflect.TypeFor[token.Pos]()
+ ast.Inspect(root, func(n ast.Node) bool {
+ if n != nil {
+ v := reflect.ValueOf(n).Elem() // deref the pointer to struct
+ fields := v.Type().NumField()
+ for i := range fields {
+ f := v.Field(i)
+ // Clearing Pos arbitrarily is destructive,
+ // as its presence may be semantically significant
+ // (e.g. CallExpr.Ellipsis, TypeSpec.Assign)
+ // or affect formatting preferences (e.g. GenDecl.Lparen).
+ //
+ // Note: for proper formatting, it may be necessary to be selective
+ // about which positions we set to 1 vs which we set to token.NoPos.
+ // (e.g. we can set most to token.NoPos, save the few that are
+ // significant).
+ if f.Type() == posType {
+ if f.Interface() != token.NoPos {
+ f.Set(reflect.ValueOf(token.Pos(1)))
+ }
+ }
+ }
+ }
+ return true
+ })
+}
+
+// findIdent finds the Ident beneath root that has the given pos.
+// It returns the path to the ident (excluding the ident), and the ident
+// itself, where the path is the sequence of ast.Nodes encountered in a
+// depth-first search to find ident.
+func findIdent(root ast.Node, pos token.Pos) ([]ast.Node, *ast.Ident) {
+ // TODO(adonovan): opt: skip subtrees that don't contain pos.
+ var (
+ path []ast.Node
+ found *ast.Ident
+ )
+ ast.Inspect(root, func(n ast.Node) bool {
+ if found != nil {
+ return false
+ }
+ if n == nil {
+ path = path[:len(path)-1]
+ return false
+ }
+ if id, ok := n.(*ast.Ident); ok {
+ if id.Pos() == pos {
+ found = id
+ return true
+ }
+ }
+ path = append(path, n)
+ return true
+ })
+ if found == nil {
+ panic(fmt.Sprintf("findIdent %d not found in %s",
+ pos, debugFormatNode(token.NewFileSet(), root)))
+ }
+ return path, found
+}
+
+func prepend[T any](elem T, slice ...T) []T {
+ return append([]T{elem}, slice...)
+}
+
+// debugFormatNode formats a node or returns a formatting error.
+// Its sloppy treatment of errors is appropriate only for logging.
+func debugFormatNode(fset *token.FileSet, n ast.Node) string {
+ var out strings.Builder
+ if err := format.Node(&out, fset, n); err != nil {
+ out.WriteString(err.Error())
+ }
+ return out.String()
+}
+
+func shallowCopy[T any](ptr *T) *T {
+ copy := *ptr
+ return ©
+}
+
+// ∀
+func forall[T any](list []T, f func(i int, x T) bool) bool {
+ for i, x := range list {
+ if !f(i, x) {
+ return false
+ }
+ }
+ return true
+}
+
+// ∃
+func exists[T any](list []T, f func(i int, x T) bool) bool {
+ for i, x := range list {
+ if f(i, x) {
+ return true
+ }
+ }
+ return false
+}
+
+// last returns the last element of a slice, or zero if empty.
+func last[T any](slice []T) T {
+ n := len(slice)
+ if n > 0 {
+ return slice[n-1]
+ }
+ return *new(T)
+}
+
+// declares returns the set of lexical names declared by a
+// sequence of statements from the same block, excluding sub-blocks.
+// (Lexical names do not include control labels.)
+func declares(stmts []ast.Stmt) map[string]bool {
+ names := make(map[string]bool)
+ for _, stmt := range stmts {
+ switch stmt := stmt.(type) {
+ case *ast.DeclStmt:
+ for _, spec := range stmt.Decl.(*ast.GenDecl).Specs {
+ switch spec := spec.(type) {
+ case *ast.ValueSpec:
+ for _, id := range spec.Names {
+ names[id.Name] = true
+ }
+ case *ast.TypeSpec:
+ names[spec.Name.Name] = true
+ }
+ }
+
+ case *ast.AssignStmt:
+ if stmt.Tok == token.DEFINE {
+ for _, lhs := range stmt.Lhs {
+ names[lhs.(*ast.Ident).Name] = true
+ }
+ }
+ }
+ }
+ delete(names, "_")
+ return names
+}
+
+// A importNameFunc is used to query local import names in the caller, in a
+// particular shadowing context.
+//
+// The shadow map contains additional names shadowed in the inlined code, at
+// the position the local import name is to be used. The shadow map only needs
+// to contain newly introduced names in the inlined code; names shadowed at the
+// caller are handled automatically.
+type importNameFunc = func(pkgPath string, shadow shadowMap) string
+
+// assignStmts rewrites a statement assigning the results of a call into zero
+// or more statements that assign its return operands, or (nil, false) if no
+// such rewrite is possible. The set of bindings created by the result of
+// assignStmts is the same as the set of bindings created by the callerStmt.
+//
+// The callee must contain exactly one return statement.
+//
+// This is (once again) a surprisingly complex task. For example, depending on
+// types and existing bindings, the assignment
+//
+// a, b := f()
+//
+// could be rewritten as:
+//
+// a, b := 1, 2
+//
+// but may need to be written as:
+//
+// a, b := int8(1), int32(2)
+//
+// In the case where the return statement within f is a spread call to another
+// function g(), we cannot explicitly convert the return values inline, and so
+// it may be necessary to split the declaration and assignment of variables
+// into separate statements:
+//
+// a, b := g()
+//
+// or
+//
+// var a int32
+// a, b = g()
+//
+// or
+//
+// var (
+// a int8
+// b int32
+// )
+// a, b = g()
+//
+// Note: assignStmts may return (nil, true) if it determines that the rewritten
+// assignment consists only of _ = nil assignments.
+func (st *state) assignStmts(callerStmt *ast.AssignStmt, returnOperands []ast.Expr, importName importNameFunc) ([]ast.Stmt, bool) {
+ logf, caller, callee := st.opts.Logf, st.caller, &st.callee.impl
+
+ assert(len(callee.Returns) == 1, "unexpected multiple returns")
+ resultInfo := callee.Returns[0]
+
+ // When constructing assign statements, we need to make sure that we don't
+ // modify types on the left-hand side, such as would happen if the type of a
+ // RHS expression does not match the corresponding LHS type at the caller
+ // (due to untyped conversion or interface widening).
+ //
+ // This turns out to be remarkably tricky to handle correctly.
+ //
+ // Substrategies below are labeled as `Substrategy :`.
+
+ // Collect LHS information.
+ var (
+ lhs []ast.Expr // shallow copy of the LHS slice, for mutation
+ defs = make([]*ast.Ident, len(callerStmt.Lhs)) // indexes in lhs of defining identifiers
+ blanks = make([]bool, len(callerStmt.Lhs)) // indexes in lhs of blank identifiers
+ byType typeutil.Map // map of distinct types -> indexes, for writing specs later
+ )
+ for i, expr := range callerStmt.Lhs {
+ lhs = append(lhs, expr)
+ if name, ok := expr.(*ast.Ident); ok {
+ if name.Name == "_" {
+ blanks[i] = true
+ continue // no type
+ }
+
+ if obj, isDef := caller.Info.Defs[name]; isDef {
+ defs[i] = name
+ typ := obj.Type()
+ idxs, _ := byType.At(typ).([]int)
+ idxs = append(idxs, i)
+ byType.Set(typ, idxs)
+ }
+ }
+ }
+
+ // Collect RHS information
+ //
+ // The RHS is either a parallel assignment or spread assignment, but by
+ // looping over both callerStmt.Rhs and returnOperands we handle both.
+ var (
+ rhs []ast.Expr // new RHS of assignment, owned by the inliner
+ callIdx = -1 // index of the call among the original RHS
+ nilBlankAssigns = make(map[int]unit) // indexes in rhs of _ = nil assignments, which can be deleted
+ freeNames = make(map[string]bool) // free(ish) names among rhs expressions
+ nonTrivial = make(map[int]bool) // indexes in rhs of nontrivial result conversions
+ )
+ const includeComplitIdents = true
+
+ for i, expr := range callerStmt.Rhs {
+ if expr == caller.Call {
+ assert(callIdx == -1, "malformed (duplicative) AST")
+ callIdx = i
+ for j, returnOperand := range returnOperands {
+ maps.Copy(freeNames, free.Names(returnOperand, includeComplitIdents))
+ rhs = append(rhs, returnOperand)
+ if resultInfo[j]&nonTrivialResult != 0 {
+ nonTrivial[i+j] = true
+ }
+ if blanks[i+j] && resultInfo[j]&untypedNilResult != 0 {
+ nilBlankAssigns[i+j] = unit{}
+ }
+ }
+ } else {
+ // We must clone before clearing positions, since e came from the caller.
+ expr = internalastutil.CloneNode(expr)
+ clearPositions(expr)
+ maps.Copy(freeNames, free.Names(expr, includeComplitIdents))
+ rhs = append(rhs, expr)
+ }
+ }
+ assert(callIdx >= 0, "failed to find call in RHS")
+
+ // Substrategy "splice": Check to see if we can simply splice in the result
+ // expressions from the callee, such as simplifying
+ //
+ // x, y := f()
+ //
+ // to
+ //
+ // x, y := e1, e2
+ //
+ // where the types of x and y match the types of e1 and e2.
+ //
+ // This works as long as we don't need to write any additional type
+ // information.
+ if len(nonTrivial) == 0 { // no non-trivial conversions to worry about
+
+ logf("substrategy: splice assignment")
+ return []ast.Stmt{&ast.AssignStmt{
+ Lhs: lhs,
+ Tok: callerStmt.Tok,
+ TokPos: callerStmt.TokPos,
+ Rhs: rhs,
+ }}, true
+ }
+
+ // Inlining techniques below will need to write type information in order to
+ // preserve the correct types of LHS identifiers.
+ //
+ // typeExpr is a simple helper to write out type expressions. It currently
+ // handles (possibly qualified) type names.
+ //
+ // TODO(rfindley):
+ // 1. expand this to handle more type expressions.
+ // 2. refactor to share logic with callee rewriting.
+ universeAny := types.Universe.Lookup("any")
+ typeExpr := func(typ types.Type, shadow shadowMap) ast.Expr {
+ var (
+ typeName string
+ obj *types.TypeName // nil for basic types
+ )
+ if tname := typesinternal.TypeNameFor(typ); tname != nil {
+ obj = tname
+ typeName = tname.Name()
+ }
+
+ // Special case: check for universe "any".
+ // TODO(golang/go#66921): this may become unnecessary if any becomes a proper alias.
+ if typ == universeAny.Type() {
+ typeName = "any"
+ }
+
+ if typeName == "" {
+ return nil
+ }
+
+ if obj == nil || obj.Pkg() == nil || obj.Pkg() == caller.Types { // local type or builtin
+ if shadow[typeName] != 0 {
+ logf("cannot write shadowed type name %q", typeName)
+ return nil
+ }
+ obj, _ := caller.lookup(typeName).(*types.TypeName)
+ if obj != nil && types.Identical(obj.Type(), typ) {
+ return ast.NewIdent(typeName)
+ }
+ } else if pkgName := importName(obj.Pkg().Path(), shadow); pkgName != "" {
+ return &ast.SelectorExpr{
+ X: ast.NewIdent(pkgName),
+ Sel: ast.NewIdent(typeName),
+ }
+ }
+ return nil
+ }
+
+ // Substrategy "spread": in the case of a spread call (func f() (T1, T2) return
+ // g()), since we didn't hit the 'splice' substrategy, there must be some
+ // non-declaring expression on the LHS. Simplify this by pre-declaring
+ // variables, rewriting
+ //
+ // x, y := f()
+ //
+ // to
+ //
+ // var x int
+ // x, y = g()
+ //
+ // Which works as long as the predeclared variables do not overlap with free
+ // names on the RHS.
+ if len(rhs) != len(lhs) {
+ assert(len(rhs) == 1 && len(returnOperands) == 1, "expected spread call")
+
+ for _, id := range defs {
+ if id != nil && freeNames[id.Name] {
+ // By predeclaring variables, we're changing them to be in scope of the
+ // RHS. We can't do this if their names are free on the RHS.
+ return nil, false
+ }
+ }
+
+ // Write out the specs, being careful to avoid shadowing free names in
+ // their type expressions.
+ var (
+ specs []ast.Spec
+ specIdxs []int
+ shadow = make(shadowMap)
+ )
+ failed := false
+ byType.Iterate(func(typ types.Type, v any) {
+ if failed {
+ return
+ }
+ idxs := v.([]int)
+ specIdxs = append(specIdxs, idxs[0])
+ texpr := typeExpr(typ, shadow)
+ if texpr == nil {
+ failed = true
+ return
+ }
+ spec := &ast.ValueSpec{
+ Type: texpr,
+ }
+ for _, idx := range idxs {
+ spec.Names = append(spec.Names, ast.NewIdent(defs[idx].Name))
+ }
+ specs = append(specs, spec)
+ })
+ if failed {
+ return nil, false
+ }
+ logf("substrategy: spread assignment")
+ return []ast.Stmt{
+ &ast.DeclStmt{
+ Decl: &ast.GenDecl{
+ Tok: token.VAR,
+ Specs: specs,
+ },
+ },
+ &ast.AssignStmt{
+ Lhs: callerStmt.Lhs,
+ Tok: token.ASSIGN,
+ Rhs: returnOperands,
+ },
+ }, true
+ }
+
+ assert(len(lhs) == len(rhs), "mismatching LHS and RHS")
+
+ // Substrategy "convert": write out RHS expressions with explicit type conversions
+ // as necessary, rewriting
+ //
+ // x, y := f()
+ //
+ // to
+ //
+ // x, y := 1, int32(2)
+ //
+ // As required to preserve types.
+ //
+ // In the special case of _ = nil, which is disallowed by the type checker
+ // (since nil has no default type), we delete the assignment.
+ var origIdxs []int // maps back to original indexes after lhs and rhs are pruned
+ i := 0
+ for j := range lhs {
+ if _, ok := nilBlankAssigns[j]; !ok {
+ lhs[i] = lhs[j]
+ rhs[i] = rhs[j]
+ origIdxs = append(origIdxs, j)
+ i++
+ }
+ }
+ lhs = lhs[:i]
+ rhs = rhs[:i]
+
+ if len(lhs) == 0 {
+ logf("trivial assignment after pruning nil blanks assigns")
+ // After pruning, we have no remaining assignments.
+ // Signal this by returning a non-nil slice of statements.
+ return nil, true
+ }
+
+ // Write out explicit conversions as necessary.
+ //
+ // A conversion is necessary if the LHS is being defined, and the RHS return
+ // involved a nontrivial implicit conversion.
+ for i, expr := range rhs {
+ idx := origIdxs[i]
+ if nonTrivial[idx] && defs[idx] != nil {
+ typ := caller.Info.TypeOf(lhs[i])
+ texpr := typeExpr(typ, nil)
+ if texpr == nil {
+ return nil, false
+ }
+ if _, ok := texpr.(*ast.StarExpr); ok {
+ // TODO(rfindley): is this necessary? Doesn't the formatter add these parens?
+ texpr = &ast.ParenExpr{X: texpr} // *T -> (*T) so that (*T)(x) is valid
+ }
+ rhs[i] = &ast.CallExpr{
+ Fun: texpr,
+ Args: []ast.Expr{expr},
+ }
+ }
+ }
+ logf("substrategy: convert assignment")
+ return []ast.Stmt{&ast.AssignStmt{
+ Lhs: lhs,
+ Tok: callerStmt.Tok,
+ Rhs: rhs,
+ }}, true
+}
+
+// tailCallSafeReturn reports whether the callee's return statements may be safely
+// used to return from the function enclosing the caller (which must exist).
+func tailCallSafeReturn(caller *Caller, calleeSymbol *types.Func, callee *gobCallee) bool {
+ // It is safe if all callee returns involve only trivial conversions.
+ if !hasNonTrivialReturn(callee.Returns) {
+ return true
+ }
+
+ var callerType types.Type
+ // Find type of innermost function enclosing call.
+ // (Beware: Caller.enclosingFunc is the outermost.)
+loop:
+ for _, n := range caller.path {
+ switch f := n.(type) {
+ case *ast.FuncDecl:
+ callerType = caller.Info.ObjectOf(f.Name).Type()
+ break loop
+ case *ast.FuncLit:
+ callerType = caller.Info.TypeOf(f)
+ break loop
+ }
+ }
+
+ // Non-trivial return conversions in the callee are permitted
+ // if the same non-trivial conversion would occur after inlining,
+ // i.e. if the caller and callee results tuples are identical.
+ callerResults := callerType.(*types.Signature).Results()
+ calleeResults := calleeSymbol.Type().(*types.Signature).Results()
+ return types.Identical(callerResults, calleeResults)
+}
+
+// hasNonTrivialReturn reports whether any of the returns involve a nontrivial
+// implicit conversion of a result expression.
+func hasNonTrivialReturn(returnInfo [][]returnOperandFlags) bool {
+ for _, resultInfo := range returnInfo {
+ for _, r := range resultInfo {
+ if r&nonTrivialResult != 0 {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+type unit struct{} // for representing sets as maps
diff --git a/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/util.go b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/util.go
new file mode 100644
index 00000000000..5f895cce573
--- /dev/null
+++ b/hack/tools/vendor/golang.org/x/tools/internal/refactor/inline/util.go
@@ -0,0 +1,169 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+// This file defines various common helpers.
+
+import (
+ "go/ast"
+ "go/constant"
+ "go/token"
+ "go/types"
+ "reflect"
+ "strings"
+
+ "golang.org/x/tools/internal/typeparams"
+)
+
+func is[T any](x any) bool {
+ _, ok := x.(T)
+ return ok
+}
+
+func btoi(b bool) int {
+ if b {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+func offsetOf(fset *token.FileSet, pos token.Pos) int {
+ return fset.PositionFor(pos, false).Offset
+}
+
+// objectKind returns an object's kind (e.g. var, func, const, typename).
+func objectKind(obj types.Object) string {
+ return strings.TrimPrefix(strings.ToLower(reflect.TypeOf(obj).String()), "*types.")
+}
+
+// within reports whether pos is within the half-open interval [n.Pos, n.End).
+func within(pos token.Pos, n ast.Node) bool {
+ return n.Pos() <= pos && pos < n.End()
+}
+
+// trivialConversion reports whether it is safe to omit the implicit
+// value-to-variable conversion that occurs in argument passing or
+// result return. The only case currently allowed is converting from
+// untyped constant to its default type (e.g. 0 to int).
+//
+// The reason for this check is that converting from A to B to C may
+// yield a different result than converting A directly to C: consider
+// 0 to int32 to any.
+//
+// trivialConversion under-approximates trivial conversions, as unfortunately
+// go/types does not record the type of an expression *before* it is implicitly
+// converted, and therefore it cannot distinguish typed constant
+// expressions from untyped constant expressions. For example, in the
+// expression `c + 2`, where c is a uint32 constant, trivialConversion does not
+// detect that the default type of this expression is actually uint32, not untyped
+// int.
+//
+// We could, of course, do better here by reverse engineering some of go/types'
+// constant handling. That may or may not be worthwhile.
+//
+// Example: in func f() int32 { return 0 },
+// the type recorded for 0 is int32, not untyped int;
+// although it is Identical to the result var,
+// the conversion is non-trivial.
+func trivialConversion(fromValue constant.Value, from, to types.Type) bool {
+ if fromValue != nil {
+ var defaultType types.Type
+ switch fromValue.Kind() {
+ case constant.Bool:
+ defaultType = types.Typ[types.Bool]
+ case constant.String:
+ defaultType = types.Typ[types.String]
+ case constant.Int:
+ defaultType = types.Typ[types.Int]
+ case constant.Float:
+ defaultType = types.Typ[types.Float64]
+ case constant.Complex:
+ defaultType = types.Typ[types.Complex128]
+ default:
+ return false
+ }
+ return types.Identical(defaultType, to)
+ }
+ return types.Identical(from, to)
+}
+
+func checkInfoFields(info *types.Info) {
+ assert(info.Defs != nil, "types.Info.Defs is nil")
+ assert(info.Implicits != nil, "types.Info.Implicits is nil")
+ assert(info.Scopes != nil, "types.Info.Scopes is nil")
+ assert(info.Selections != nil, "types.Info.Selections is nil")
+ assert(info.Types != nil, "types.Info.Types is nil")
+ assert(info.Uses != nil, "types.Info.Uses is nil")
+ assert(info.FileVersions != nil, "types.Info.FileVersions is nil")
+}
+
+// intersects reports whether the maps' key sets intersect.
+func intersects[K comparable, T1, T2 any](x map[K]T1, y map[K]T2) bool {
+ if len(x) > len(y) {
+ return intersects(y, x)
+ }
+ for k := range x {
+ if _, ok := y[k]; ok {
+ return true
+ }
+ }
+ return false
+}
+
+// convert returns syntax for the conversion T(x).
+func convert(T, x ast.Expr) *ast.CallExpr {
+ // The formatter generally adds parens as needed,
+ // but before go1.22 it had a bug (#63362) for
+ // channel types that requires this workaround.
+ if ch, ok := T.(*ast.ChanType); ok && ch.Dir == ast.RECV {
+ T = &ast.ParenExpr{X: T}
+ }
+ return &ast.CallExpr{
+ Fun: T,
+ Args: []ast.Expr{x},
+ }
+}
+
+// isPointer reports whether t's core type is a pointer.
+func isPointer(t types.Type) bool {
+ return is[*types.Pointer](typeparams.CoreType(t))
+}
+
+// indirectSelection is like seln.Indirect() without bug #8353.
+func indirectSelection(seln *types.Selection) bool {
+ // Work around bug #8353 in Selection.Indirect when Kind=MethodVal.
+ if seln.Kind() == types.MethodVal {
+ tArg, indirect := effectiveReceiver(seln)
+ if indirect {
+ return true
+ }
+
+ tParam := seln.Obj().Type().Underlying().(*types.Signature).Recv().Type()
+ return isPointer(tArg) && !isPointer(tParam) // implicit *
+ }
+
+ return seln.Indirect()
+}
+
+// effectiveReceiver returns the effective type of the method
+// receiver after all implicit field selections (but not implicit * or
+// & operations) have been applied.
+//
+// The boolean indicates whether any implicit field selection was indirect.
+func effectiveReceiver(seln *types.Selection) (types.Type, bool) {
+ assert(seln.Kind() == types.MethodVal, "not MethodVal")
+ t := seln.Recv()
+ indices := seln.Index()
+ indirect := false
+ for _, index := range indices[:len(indices)-1] {
+ if isPointer(t) {
+ indirect = true
+ t = typeparams.MustDeref(t)
+ }
+ t = typeparams.CoreType(t).(*types.Struct).Field(index).Type()
+ }
+ return t, indirect
+}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/.travis.yml b/hack/tools/vendor/gopkg.in/op/go-logging.v1/.travis.yml
deleted file mode 100644
index 70e012b81e4..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/.travis.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-language: go
-
-go:
- - 1.0
- - 1.1
- - tip
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/CONTRIBUTORS b/hack/tools/vendor/gopkg.in/op/go-logging.v1/CONTRIBUTORS
deleted file mode 100644
index 958416ef1de..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/CONTRIBUTORS
+++ /dev/null
@@ -1,5 +0,0 @@
-Alec Thomas
-Guilhem Lettron
-Ivan Daniluk
-Nimi Wariboko Jr
-Róbert Selvek
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/LICENSE b/hack/tools/vendor/gopkg.in/op/go-logging.v1/LICENSE
deleted file mode 100644
index f1f6cfcef93..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2013 Örjan Persson. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/README.md b/hack/tools/vendor/gopkg.in/op/go-logging.v1/README.md
deleted file mode 100644
index 9999d90f5a7..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/README.md
+++ /dev/null
@@ -1,89 +0,0 @@
-## Golang logging library
-
-[](https://godoc.org/github.com/op/go-logging) [](https://travis-ci.org/op/go-logging)
-
-Package logging implements a logging infrastructure for Go. Its output format
-is customizable and supports different logging backends like syslog, file and
-memory. Multiple backends can be utilized with different log levels per backend
-and logger.
-
-## Example
-
-Let's have a look at an [example](examples/example.go) which demonstrates most
-of the features found in this library.
-
-[](examples/example.go)
-
-```go
-package main
-
-import (
- "os"
-
- "github.com/op/go-logging"
-)
-
-var log = logging.MustGetLogger("example")
-
-// Example format string. Everything except the message has a custom color
-// which is dependent on the log level. Many fields have a custom output
-// formatting too, eg. the time returns the hour down to the milli second.
-var format = logging.MustStringFormatter(
- `%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`,
-)
-
-// Password is just an example type implementing the Redactor interface. Any
-// time this is logged, the Redacted() function will be called.
-type Password string
-
-func (p Password) Redacted() interface{} {
- return logging.Redact(string(p))
-}
-
-func main() {
- // For demo purposes, create two backend for os.Stderr.
- backend1 := logging.NewLogBackend(os.Stderr, "", 0)
- backend2 := logging.NewLogBackend(os.Stderr, "", 0)
-
- // For messages written to backend2 we want to add some additional
- // information to the output, including the used log level and the name of
- // the function.
- backend2Formatter := logging.NewBackendFormatter(backend2, format)
-
- // Only errors and more severe messages should be sent to backend1
- backend1Leveled := logging.AddModuleLevel(backend1)
- backend1Leveled.SetLevel(logging.ERROR, "")
-
- // Set the backends to be used.
- logging.SetBackend(backend1Leveled, backend2Formatter)
-
- log.Debugf("debug %s", Password("secret"))
- log.Info("info")
- log.Notice("notice")
- log.Warning("warning")
- log.Error("err")
- log.Critical("crit")
-}
-```
-
-## Installing
-
-### Using *go get*
-
- $ go get github.com/op/go-logging
-
-After this command *go-logging* is ready to use. Its source will be in:
-
- $GOPATH/src/pkg/github.com/op/go-logging
-
-You can use `go get -u` to update the package.
-
-## Documentation
-
-For docs, see http://godoc.org/github.com/op/go-logging or run:
-
- $ godoc github.com/op/go-logging
-
-## Additional resources
-
-* [wslog](https://godoc.org/github.com/cryptix/go/logging/wslog) -- exposes log messages through a WebSocket.
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/backend.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/backend.go
deleted file mode 100644
index 74d9201083f..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/backend.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logging
-
-// defaultBackend is the backend used for all logging calls.
-var defaultBackend LeveledBackend
-
-// Backend is the interface which a log backend need to implement to be able to
-// be used as a logging backend.
-type Backend interface {
- Log(Level, int, *Record) error
-}
-
-// SetBackend replaces the backend currently set with the given new logging
-// backend.
-func SetBackend(backends ...Backend) LeveledBackend {
- var backend Backend
- if len(backends) == 1 {
- backend = backends[0]
- } else {
- backend = MultiLogger(backends...)
- }
-
- defaultBackend = AddModuleLevel(backend)
- return defaultBackend
-}
-
-// SetLevel sets the logging level for the specified module. The module
-// corresponds to the string specified in GetLogger.
-func SetLevel(level Level, module string) {
- defaultBackend.SetLevel(level, module)
-}
-
-// GetLevel returns the logging level for the specified module.
-func GetLevel(module string) Level {
- return defaultBackend.GetLevel(module)
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/format.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/format.go
deleted file mode 100644
index 2d6a4044f32..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/format.go
+++ /dev/null
@@ -1,400 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logging
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "os"
- "path"
- "path/filepath"
- "regexp"
- "runtime"
- "strings"
- "sync"
- "time"
-)
-
-// TODO see Formatter interface in fmt/print.go
-// TODO try text/template, maybe it have enough performance
-// TODO other template systems?
-// TODO make it possible to specify formats per backend?
-type fmtVerb int
-
-const (
- fmtVerbTime fmtVerb = iota
- fmtVerbLevel
- fmtVerbID
- fmtVerbPid
- fmtVerbProgram
- fmtVerbModule
- fmtVerbMessage
- fmtVerbLongfile
- fmtVerbShortfile
- fmtVerbLongpkg
- fmtVerbShortpkg
- fmtVerbLongfunc
- fmtVerbShortfunc
- fmtVerbCallpath
- fmtVerbLevelColor
-
- // Keep last, there are no match for these below.
- fmtVerbUnknown
- fmtVerbStatic
-)
-
-var fmtVerbs = []string{
- "time",
- "level",
- "id",
- "pid",
- "program",
- "module",
- "message",
- "longfile",
- "shortfile",
- "longpkg",
- "shortpkg",
- "longfunc",
- "shortfunc",
- "callpath",
- "color",
-}
-
-const rfc3339Milli = "2006-01-02T15:04:05.999Z07:00"
-
-var defaultVerbsLayout = []string{
- rfc3339Milli,
- "s",
- "d",
- "d",
- "s",
- "s",
- "s",
- "s",
- "s",
- "s",
- "s",
- "s",
- "s",
- "s",
- "",
-}
-
-var (
- pid = os.Getpid()
- program = filepath.Base(os.Args[0])
-)
-
-func getFmtVerbByName(name string) fmtVerb {
- for i, verb := range fmtVerbs {
- if name == verb {
- return fmtVerb(i)
- }
- }
- return fmtVerbUnknown
-}
-
-// Formatter is the required interface for a custom log record formatter.
-type Formatter interface {
- Format(calldepth int, r *Record, w io.Writer) error
-}
-
-// formatter is used by all backends unless otherwise overriden.
-var formatter struct {
- sync.RWMutex
- def Formatter
-}
-
-func getFormatter() Formatter {
- formatter.RLock()
- defer formatter.RUnlock()
- return formatter.def
-}
-
-var (
- // DefaultFormatter is the default formatter used and is only the message.
- DefaultFormatter = MustStringFormatter("%{message}")
-
- // GlogFormatter mimics the glog format
- GlogFormatter = MustStringFormatter("%{level:.1s}%{time:0102 15:04:05.999999} %{pid} %{shortfile}] %{message}")
-)
-
-// SetFormatter sets the default formatter for all new backends. A backend will
-// fetch this value once it is needed to format a record. Note that backends
-// will cache the formatter after the first point. For now, make sure to set
-// the formatter before logging.
-func SetFormatter(f Formatter) {
- formatter.Lock()
- defer formatter.Unlock()
- formatter.def = f
-}
-
-var formatRe = regexp.MustCompile(`%{([a-z]+)(?::(.*?[^\\]))?}`)
-
-type part struct {
- verb fmtVerb
- layout string
-}
-
-// stringFormatter contains a list of parts which explains how to build the
-// formatted string passed on to the logging backend.
-type stringFormatter struct {
- parts []part
-}
-
-// NewStringFormatter returns a new Formatter which outputs the log record as a
-// string based on the 'verbs' specified in the format string.
-//
-// The verbs:
-//
-// General:
-// %{id} Sequence number for log message (uint64).
-// %{pid} Process id (int)
-// %{time} Time when log occurred (time.Time)
-// %{level} Log level (Level)
-// %{module} Module (string)
-// %{program} Basename of os.Args[0] (string)
-// %{message} Message (string)
-// %{longfile} Full file name and line number: /a/b/c/d.go:23
-// %{shortfile} Final file name element and line number: d.go:23
-// %{callpath} Callpath like main.a.b.c...c "..." meaning recursive call
-// %{color} ANSI color based on log level
-//
-// For normal types, the output can be customized by using the 'verbs' defined
-// in the fmt package, eg. '%{id:04d}' to make the id output be '%04d' as the
-// format string.
-//
-// For time.Time, use the same layout as time.Format to change the time format
-// when output, eg "2006-01-02T15:04:05.999Z-07:00".
-//
-// For the 'color' verb, the output can be adjusted to either use bold colors,
-// i.e., '%{color:bold}' or to reset the ANSI attributes, i.e.,
-// '%{color:reset}' Note that if you use the color verb explicitly, be sure to
-// reset it or else the color state will persist past your log message. e.g.,
-// "%{color:bold}%{time:15:04:05} %{level:-8s}%{color:reset} %{message}" will
-// just colorize the time and level, leaving the message uncolored.
-//
-// Colors on Windows is unfortunately not supported right now and is currently
-// a no-op.
-//
-// There's also a couple of experimental 'verbs'. These are exposed to get
-// feedback and needs a bit of tinkering. Hence, they might change in the
-// future.
-//
-// Experimental:
-// %{longpkg} Full package path, eg. github.com/go-logging
-// %{shortpkg} Base package path, eg. go-logging
-// %{longfunc} Full function name, eg. littleEndian.PutUint32
-// %{shortfunc} Base function name, eg. PutUint32
-// %{callpath} Call function path, eg. main.a.b.c
-func NewStringFormatter(format string) (Formatter, error) {
- var fmter = &stringFormatter{}
-
- // Find the boundaries of all %{vars}
- matches := formatRe.FindAllStringSubmatchIndex(format, -1)
- if matches == nil {
- return nil, errors.New("logger: invalid log format: " + format)
- }
-
- // Collect all variables and static text for the format
- prev := 0
- for _, m := range matches {
- start, end := m[0], m[1]
- if start > prev {
- fmter.add(fmtVerbStatic, format[prev:start])
- }
-
- name := format[m[2]:m[3]]
- verb := getFmtVerbByName(name)
- if verb == fmtVerbUnknown {
- return nil, errors.New("logger: unknown variable: " + name)
- }
-
- // Handle layout customizations or use the default. If this is not for the
- // time or color formatting, we need to prefix with %.
- layout := defaultVerbsLayout[verb]
- if m[4] != -1 {
- layout = format[m[4]:m[5]]
- }
- if verb != fmtVerbTime && verb != fmtVerbLevelColor {
- layout = "%" + layout
- }
-
- fmter.add(verb, layout)
- prev = end
- }
- end := format[prev:]
- if end != "" {
- fmter.add(fmtVerbStatic, end)
- }
-
- // Make a test run to make sure we can format it correctly.
- t, err := time.Parse(time.RFC3339, "2010-02-04T21:00:57-08:00")
- if err != nil {
- panic(err)
- }
- r := &Record{
- Id: 12345,
- Time: t,
- Module: "logger",
- Args: []interface{}{"go"},
- fmt: "hello %s",
- }
- if err := fmter.Format(0, r, &bytes.Buffer{}); err != nil {
- return nil, err
- }
-
- return fmter, nil
-}
-
-// MustStringFormatter is equivalent to NewStringFormatter with a call to panic
-// on error.
-func MustStringFormatter(format string) Formatter {
- f, err := NewStringFormatter(format)
- if err != nil {
- panic("Failed to initialized string formatter: " + err.Error())
- }
- return f
-}
-
-func (f *stringFormatter) add(verb fmtVerb, layout string) {
- f.parts = append(f.parts, part{verb, layout})
-}
-
-func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) error {
- for _, part := range f.parts {
- if part.verb == fmtVerbStatic {
- output.Write([]byte(part.layout))
- } else if part.verb == fmtVerbTime {
- output.Write([]byte(r.Time.Format(part.layout)))
- } else if part.verb == fmtVerbLevelColor {
- doFmtVerbLevelColor(part.layout, r.Level, output)
- } else {
- var v interface{}
- switch part.verb {
- case fmtVerbLevel:
- v = r.Level
- break
- case fmtVerbID:
- v = r.Id
- break
- case fmtVerbPid:
- v = pid
- break
- case fmtVerbProgram:
- v = program
- break
- case fmtVerbModule:
- v = r.Module
- break
- case fmtVerbMessage:
- v = r.Message()
- break
- case fmtVerbLongfile, fmtVerbShortfile:
- _, file, line, ok := runtime.Caller(calldepth + 1)
- if !ok {
- file = "???"
- line = 0
- } else if part.verb == fmtVerbShortfile {
- file = filepath.Base(file)
- }
- v = fmt.Sprintf("%s:%d", file, line)
- case fmtVerbLongfunc, fmtVerbShortfunc,
- fmtVerbLongpkg, fmtVerbShortpkg:
- // TODO cache pc
- v = "???"
- if pc, _, _, ok := runtime.Caller(calldepth + 1); ok {
- if f := runtime.FuncForPC(pc); f != nil {
- v = formatFuncName(part.verb, f.Name())
- }
- }
- case fmtVerbCallpath:
- v = formatCallpath(calldepth + 1)
- default:
- panic("unhandled format part")
- }
- fmt.Fprintf(output, part.layout, v)
- }
- }
- return nil
-}
-
-// formatFuncName tries to extract certain part of the runtime formatted
-// function name to some pre-defined variation.
-//
-// This function is known to not work properly if the package path or name
-// contains a dot.
-func formatFuncName(v fmtVerb, f string) string {
- i := strings.LastIndex(f, "/")
- j := strings.Index(f[i+1:], ".")
- if j < 1 {
- return "???"
- }
- pkg, fun := f[:i+j+1], f[i+j+2:]
- switch v {
- case fmtVerbLongpkg:
- return pkg
- case fmtVerbShortpkg:
- return path.Base(pkg)
- case fmtVerbLongfunc:
- return fun
- case fmtVerbShortfunc:
- i = strings.LastIndex(fun, ".")
- return fun[i+1:]
- }
- panic("unexpected func formatter")
-}
-
-func formatCallpath(calldepth int) string {
- v := ""
- callers := make([]uintptr, 64)
- n := runtime.Callers(calldepth+2, callers)
- oldPc := callers[n-1]
-
- recursiveCall := false
- for i := n - 3; i >= 0; i-- {
- pc := callers[i]
- if oldPc == pc {
- recursiveCall = true
- continue
- }
- oldPc = pc
- if recursiveCall {
- recursiveCall = false
- v += ".."
- }
- if i < n-3 {
- v += "."
- }
- if f := runtime.FuncForPC(pc); f != nil {
- v += formatFuncName(fmtVerbShortfunc, f.Name())
- }
- }
- return v
-}
-
-// backendFormatter combines a backend with a specific formatter making it
-// possible to have different log formats for different backends.
-type backendFormatter struct {
- b Backend
- f Formatter
-}
-
-// NewBackendFormatter creates a new backend which makes all records that
-// passes through it beeing formatted by the specific formatter.
-func NewBackendFormatter(b Backend, f Formatter) Backend {
- return &backendFormatter{b, f}
-}
-
-// Log implements the Log function required by the Backend interface.
-func (bf *backendFormatter) Log(level Level, calldepth int, r *Record) error {
- // Make a shallow copy of the record and replace any formatter
- r2 := *r
- r2.formatter = bf.f
- return bf.b.Log(level, calldepth+1, &r2)
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/level.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/level.go
deleted file mode 100644
index 98dd191873a..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/level.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logging
-
-import (
- "errors"
- "strings"
- "sync"
-)
-
-// ErrInvalidLogLevel is used when an invalid log level has been used.
-var ErrInvalidLogLevel = errors.New("logger: invalid log level")
-
-// Level defines all available log levels for log messages.
-type Level int
-
-// Log levels.
-const (
- CRITICAL Level = iota
- ERROR
- WARNING
- NOTICE
- INFO
- DEBUG
-)
-
-var levelNames = []string{
- "CRITICAL",
- "ERROR",
- "WARNING",
- "NOTICE",
- "INFO",
- "DEBUG",
-}
-
-// String returns the string representation of a logging level.
-func (p Level) String() string {
- return levelNames[p]
-}
-
-// LogLevel returns the log level from a string representation.
-func LogLevel(level string) (Level, error) {
- for i, name := range levelNames {
- if strings.EqualFold(name, level) {
- return Level(i), nil
- }
- }
- return ERROR, ErrInvalidLogLevel
-}
-
-// Leveled interface is the interface required to be able to add leveled
-// logging.
-type Leveled interface {
- GetLevel(string) Level
- SetLevel(Level, string)
- IsEnabledFor(Level, string) bool
-}
-
-// LeveledBackend is a log backend with additional knobs for setting levels on
-// individual modules to different levels.
-type LeveledBackend interface {
- Backend
- Leveled
-}
-
-type moduleLeveled struct {
- levels map[string]Level
- backend Backend
- formatter Formatter
- once sync.Once
-}
-
-// AddModuleLevel wraps a log backend with knobs to have different log levels
-// for different modules.
-func AddModuleLevel(backend Backend) LeveledBackend {
- var leveled LeveledBackend
- var ok bool
- if leveled, ok = backend.(LeveledBackend); !ok {
- leveled = &moduleLeveled{
- levels: make(map[string]Level),
- backend: backend,
- }
- }
- return leveled
-}
-
-// GetLevel returns the log level for the given module.
-func (l *moduleLeveled) GetLevel(module string) Level {
- level, exists := l.levels[module]
- if exists == false {
- level, exists = l.levels[""]
- // no configuration exists, default to debug
- if exists == false {
- level = DEBUG
- }
- }
- return level
-}
-
-// SetLevel sets the log level for the given module.
-func (l *moduleLeveled) SetLevel(level Level, module string) {
- l.levels[module] = level
-}
-
-// IsEnabledFor will return true if logging is enabled for the given module.
-func (l *moduleLeveled) IsEnabledFor(level Level, module string) bool {
- return level <= l.GetLevel(module)
-}
-
-func (l *moduleLeveled) Log(level Level, calldepth int, rec *Record) (err error) {
- if l.IsEnabledFor(level, rec.Module) {
- // TODO get rid of traces of formatter here. BackendFormatter should be used.
- rec.formatter = l.getFormatterAndCacheCurrent()
- err = l.backend.Log(level, calldepth+1, rec)
- }
- return
-}
-
-func (l *moduleLeveled) getFormatterAndCacheCurrent() Formatter {
- l.once.Do(func() {
- if l.formatter == nil {
- l.formatter = getFormatter()
- }
- })
- return l.formatter
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/log_nix.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/log_nix.go
deleted file mode 100644
index 4ff2ab1ab8e..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/log_nix.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// +build !windows
-
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logging
-
-import (
- "bytes"
- "fmt"
- "io"
- "log"
-)
-
-type color int
-
-const (
- ColorBlack = iota + 30
- ColorRed
- ColorGreen
- ColorYellow
- ColorBlue
- ColorMagenta
- ColorCyan
- ColorWhite
-)
-
-var (
- colors = []string{
- CRITICAL: ColorSeq(ColorMagenta),
- ERROR: ColorSeq(ColorRed),
- WARNING: ColorSeq(ColorYellow),
- NOTICE: ColorSeq(ColorGreen),
- DEBUG: ColorSeq(ColorCyan),
- }
- boldcolors = []string{
- CRITICAL: ColorSeqBold(ColorMagenta),
- ERROR: ColorSeqBold(ColorRed),
- WARNING: ColorSeqBold(ColorYellow),
- NOTICE: ColorSeqBold(ColorGreen),
- DEBUG: ColorSeqBold(ColorCyan),
- }
-)
-
-// LogBackend utilizes the standard log module.
-type LogBackend struct {
- Logger *log.Logger
- Color bool
- ColorConfig []string
-}
-
-// NewLogBackend creates a new LogBackend.
-func NewLogBackend(out io.Writer, prefix string, flag int) *LogBackend {
- return &LogBackend{Logger: log.New(out, prefix, flag)}
-}
-
-// Log implements the Backend interface.
-func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error {
- if b.Color {
- col := colors[level]
- if len(b.ColorConfig) > int(level) && b.ColorConfig[level] != "" {
- col = b.ColorConfig[level]
- }
-
- buf := &bytes.Buffer{}
- buf.Write([]byte(col))
- buf.Write([]byte(rec.Formatted(calldepth + 1)))
- buf.Write([]byte("\033[0m"))
- // For some reason, the Go logger arbitrarily decided "2" was the correct
- // call depth...
- return b.Logger.Output(calldepth+2, buf.String())
- }
-
- return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1))
-}
-
-// ConvertColors takes a list of ints representing colors for log levels and
-// converts them into strings for ANSI color formatting
-func ConvertColors(colors []int, bold bool) []string {
- converted := []string{}
- for _, i := range colors {
- if bold {
- converted = append(converted, ColorSeqBold(color(i)))
- } else {
- converted = append(converted, ColorSeq(color(i)))
- }
- }
-
- return converted
-}
-
-func ColorSeq(color color) string {
- return fmt.Sprintf("\033[%dm", int(color))
-}
-
-func ColorSeqBold(color color) string {
- return fmt.Sprintf("\033[%d;1m", int(color))
-}
-
-func doFmtVerbLevelColor(layout string, level Level, output io.Writer) {
- if layout == "bold" {
- output.Write([]byte(boldcolors[level]))
- } else if layout == "reset" {
- output.Write([]byte("\033[0m"))
- } else {
- output.Write([]byte(colors[level]))
- }
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/log_windows.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/log_windows.go
deleted file mode 100644
index b8dc92c67a1..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/log_windows.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// +build windows
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logging
-
-import (
- "bytes"
- "io"
- "log"
- "syscall"
-)
-
-var (
- kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
- setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
-)
-
-// Character attributes
-// Note:
-// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
-// Clearing all foreground or background colors results in black; setting all creates white.
-// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
-const (
- fgBlack = 0x0000
- fgBlue = 0x0001
- fgGreen = 0x0002
- fgCyan = 0x0003
- fgRed = 0x0004
- fgMagenta = 0x0005
- fgYellow = 0x0006
- fgWhite = 0x0007
- fgIntensity = 0x0008
- fgMask = 0x000F
-)
-
-var (
- colors = []uint16{
- INFO: fgWhite,
- CRITICAL: fgMagenta,
- ERROR: fgRed,
- WARNING: fgYellow,
- NOTICE: fgGreen,
- DEBUG: fgCyan,
- }
- boldcolors = []uint16{
- INFO: fgWhite | fgIntensity,
- CRITICAL: fgMagenta | fgIntensity,
- ERROR: fgRed | fgIntensity,
- WARNING: fgYellow | fgIntensity,
- NOTICE: fgGreen | fgIntensity,
- DEBUG: fgCyan | fgIntensity,
- }
-)
-
-type file interface {
- Fd() uintptr
-}
-
-// LogBackend utilizes the standard log module.
-type LogBackend struct {
- Logger *log.Logger
- Color bool
-
- // f is set to a non-nil value if the underlying writer which logs writes to
- // implements the file interface. This makes us able to colorise the output.
- f file
-}
-
-// NewLogBackend creates a new LogBackend.
-func NewLogBackend(out io.Writer, prefix string, flag int) *LogBackend {
- b := &LogBackend{Logger: log.New(out, prefix, flag)}
-
- // Unfortunately, the API used only takes an io.Writer where the Windows API
- // need the actual fd to change colors.
- if f, ok := out.(file); ok {
- b.f = f
- }
-
- return b
-}
-
-func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error {
- if b.Color && b.f != nil {
- buf := &bytes.Buffer{}
- setConsoleTextAttribute(b.f, colors[level])
- buf.Write([]byte(rec.Formatted(calldepth + 1)))
- err := b.Logger.Output(calldepth+2, buf.String())
- setConsoleTextAttribute(b.f, fgWhite)
- return err
- }
- return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1))
-}
-
-// setConsoleTextAttribute sets the attributes of characters written to the
-// console screen buffer by the WriteFile or WriteConsole function.
-// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
-func setConsoleTextAttribute(f file, attribute uint16) bool {
- ok, _, _ := setConsoleTextAttributeProc.Call(f.Fd(), uintptr(attribute), 0)
- return ok != 0
-}
-
-func doFmtVerbLevelColor(layout string, level Level, output io.Writer) {
- // TODO not supported on Windows since the io.Writer here is actually a
- // bytes.Buffer.
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/logger.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/logger.go
deleted file mode 100644
index 8e4ebab9628..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/logger.go
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package logging implements a logging infrastructure for Go. It supports
-// different logging backends like syslog, file and memory. Multiple backends
-// can be utilized with different log levels per backend and logger.
-package logging
-
-import (
- "bytes"
- "fmt"
- "log"
- "os"
- "strings"
- "sync/atomic"
- "time"
-)
-
-// Redactor is an interface for types that may contain sensitive information
-// (like passwords), which shouldn't be printed to the log. The idea was found
-// in relog as part of the vitness project.
-type Redactor interface {
- Redacted() interface{}
-}
-
-// Redact returns a string of * having the same length as s.
-func Redact(s string) string {
- return strings.Repeat("*", len(s))
-}
-
-var (
- // Sequence number is incremented and utilized for all log records created.
- sequenceNo uint64
-
- // timeNow is a customizable for testing purposes.
- timeNow = time.Now
-)
-
-// Record represents a log record and contains the timestamp when the record
-// was created, an increasing id, filename and line and finally the actual
-// formatted log line.
-type Record struct {
- Id uint64
- Time time.Time
- Module string
- Level Level
- Args []interface{}
-
- // message is kept as a pointer to have shallow copies update this once
- // needed.
- message *string
- fmt string
- formatter Formatter
- formatted string
-}
-
-// Formatted returns the formatted log record string.
-func (r *Record) Formatted(calldepth int) string {
- if r.formatted == "" {
- var buf bytes.Buffer
- r.formatter.Format(calldepth+1, r, &buf)
- r.formatted = buf.String()
- }
- return r.formatted
-}
-
-// Message returns the log record message.
-func (r *Record) Message() string {
- if r.message == nil {
- // Redact the arguments that implements the Redactor interface
- for i, arg := range r.Args {
- if redactor, ok := arg.(Redactor); ok == true {
- r.Args[i] = redactor.Redacted()
- }
- }
- msg := fmt.Sprintf(r.fmt, r.Args...)
- r.message = &msg
- }
- return *r.message
-}
-
-// Logger is the actual logger which creates log records based on the functions
-// called and passes them to the underlying logging backend.
-type Logger struct {
- Module string
- backend LeveledBackend
- haveBackend bool
-
- // ExtraCallDepth can be used to add additional call depth when getting the
- // calling function. This is normally used when wrapping a logger.
- ExtraCalldepth int
-}
-
-// SetBackend overrides any previously defined backend for this logger.
-func (l *Logger) SetBackend(backend LeveledBackend) {
- l.backend = backend
- l.haveBackend = true
-}
-
-// TODO call NewLogger and remove MustGetLogger?
-
-// GetLogger creates and returns a Logger object based on the module name.
-func GetLogger(module string) (*Logger, error) {
- return &Logger{Module: module}, nil
-}
-
-// MustGetLogger is like GetLogger but panics if the logger can't be created.
-// It simplifies safe initialization of a global logger for eg. a package.
-func MustGetLogger(module string) *Logger {
- logger, err := GetLogger(module)
- if err != nil {
- panic("logger: " + module + ": " + err.Error())
- }
- return logger
-}
-
-// Reset restores the internal state of the logging library.
-func Reset() {
- // TODO make a global Init() method to be less magic? or make it such that
- // if there's no backends at all configured, we could use some tricks to
- // automatically setup backends based if we have a TTY or not.
- sequenceNo = 0
- b := SetBackend(NewLogBackend(os.Stderr, "", log.LstdFlags))
- b.SetLevel(DEBUG, "")
- SetFormatter(DefaultFormatter)
- timeNow = time.Now
-}
-
-// IsEnabledFor returns true if the logger is enabled for the given level.
-func (l *Logger) IsEnabledFor(level Level) bool {
- return defaultBackend.IsEnabledFor(level, l.Module)
-}
-
-func (l *Logger) log(lvl Level, format string, args ...interface{}) {
- if !l.IsEnabledFor(lvl) {
- return
- }
-
- // Create the logging record and pass it in to the backend
- record := &Record{
- Id: atomic.AddUint64(&sequenceNo, 1),
- Time: timeNow(),
- Module: l.Module,
- Level: lvl,
- fmt: format,
- Args: args,
- }
-
- // TODO use channels to fan out the records to all backends?
- // TODO in case of errors, do something (tricky)
-
- // calldepth=2 brings the stack up to the caller of the level
- // methods, Info(), Fatal(), etc.
- // ExtraCallDepth allows this to be extended further up the stack in case we
- // are wrapping these methods, eg. to expose them package level
- if l.haveBackend {
- l.backend.Log(lvl, 2+l.ExtraCalldepth, record)
- return
- }
-
- defaultBackend.Log(lvl, 2+l.ExtraCalldepth, record)
-}
-
-// Fatal is equivalent to l.Critical(fmt.Sprint()) followed by a call to os.Exit(1).
-func (l *Logger) Fatal(args ...interface{}) {
- s := fmt.Sprint(args...)
- l.log(CRITICAL, "%s", s)
- os.Exit(1)
-}
-
-// Fatalf is equivalent to l.Critical followed by a call to os.Exit(1).
-func (l *Logger) Fatalf(format string, args ...interface{}) {
- l.log(CRITICAL, format, args...)
- os.Exit(1)
-}
-
-// Panic is equivalent to l.Critical(fmt.Sprint()) followed by a call to panic().
-func (l *Logger) Panic(args ...interface{}) {
- s := fmt.Sprint(args...)
- l.log(CRITICAL, "%s", s)
- panic(s)
-}
-
-// Panicf is equivalent to l.Critical followed by a call to panic().
-func (l *Logger) Panicf(format string, args ...interface{}) {
- s := fmt.Sprintf(format, args...)
- l.log(CRITICAL, "%s", s)
- panic(s)
-}
-
-// Critical logs a message using CRITICAL as log level.
-func (l *Logger) Critical(format string, args ...interface{}) {
- l.log(CRITICAL, format, args...)
-}
-
-// Error logs a message using ERROR as log level.
-func (l *Logger) Error(format string, args ...interface{}) {
- l.log(ERROR, format, args...)
-}
-
-// Errorf logs a message using ERROR as log level.
-func (l *Logger) Errorf(format string, args ...interface{}) {
- l.log(ERROR, format, args...)
-}
-
-// Warning logs a message using WARNING as log level.
-func (l *Logger) Warning(format string, args ...interface{}) {
- l.log(WARNING, format, args...)
-}
-
-// Warningf logs a message using WARNING as log level.
-func (l *Logger) Warningf(format string, args ...interface{}) {
- l.log(WARNING, format, args...)
-}
-
-// Notice logs a message using NOTICE as log level.
-func (l *Logger) Notice(format string, args ...interface{}) {
- l.log(NOTICE, format, args...)
-}
-
-// Noticef logs a message using NOTICE as log level.
-func (l *Logger) Noticef(format string, args ...interface{}) {
- l.log(NOTICE, format, args...)
-}
-
-// Info logs a message using INFO as log level.
-func (l *Logger) Info(format string, args ...interface{}) {
- l.log(INFO, format, args...)
-}
-
-// Infof logs a message using INFO as log level.
-func (l *Logger) Infof(format string, args ...interface{}) {
- l.log(INFO, format, args...)
-}
-
-// Debug logs a message using DEBUG as log level.
-func (l *Logger) Debug(format string, args ...interface{}) {
- l.log(DEBUG, format, args...)
-}
-
-// Debugf logs a message using DEBUG as log level.
-func (l *Logger) Debugf(format string, args ...interface{}) {
- l.log(DEBUG, format, args...)
-}
-
-func init() {
- Reset()
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/memory.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/memory.go
deleted file mode 100644
index 8d5152c0ba1..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/memory.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !appengine
-
-package logging
-
-import (
- "sync"
- "sync/atomic"
- "time"
- "unsafe"
-)
-
-// TODO pick one of the memory backends and stick with it or share interface.
-
-// InitForTesting is a convenient method when using logging in a test. Once
-// called, the time will be frozen to January 1, 1970 UTC.
-func InitForTesting(level Level) *MemoryBackend {
- Reset()
-
- memoryBackend := NewMemoryBackend(10240)
-
- leveledBackend := AddModuleLevel(memoryBackend)
- leveledBackend.SetLevel(level, "")
- SetBackend(leveledBackend)
-
- timeNow = func() time.Time {
- return time.Unix(0, 0).UTC()
- }
- return memoryBackend
-}
-
-// Node is a record node pointing to an optional next node.
-type node struct {
- next *node
- Record *Record
-}
-
-// Next returns the next record node. If there's no node available, it will
-// return nil.
-func (n *node) Next() *node {
- return n.next
-}
-
-// MemoryBackend is a simple memory based logging backend that will not produce
-// any output but merly keep records, up to the given size, in memory.
-type MemoryBackend struct {
- size int32
- maxSize int32
- head, tail unsafe.Pointer
-}
-
-// NewMemoryBackend creates a simple in-memory logging backend.
-func NewMemoryBackend(size int) *MemoryBackend {
- return &MemoryBackend{maxSize: int32(size)}
-}
-
-// Log implements the Log method required by Backend.
-func (b *MemoryBackend) Log(level Level, calldepth int, rec *Record) error {
- var size int32
-
- n := &node{Record: rec}
- np := unsafe.Pointer(n)
-
- // Add the record to the tail. If there's no records available, tail and
- // head will both be nil. When we successfully set the tail and the previous
- // value was nil, it's safe to set the head to the current value too.
- for {
- tailp := b.tail
- swapped := atomic.CompareAndSwapPointer(
- &b.tail,
- tailp,
- np,
- )
- if swapped == true {
- if tailp == nil {
- b.head = np
- } else {
- (*node)(tailp).next = n
- }
- size = atomic.AddInt32(&b.size, 1)
- break
- }
- }
-
- // Since one record was added, we might have overflowed the list. Remove
- // a record if that is the case. The size will fluctate a bit, but
- // eventual consistent.
- if b.maxSize > 0 && size > b.maxSize {
- for {
- headp := b.head
- head := (*node)(b.head)
- if head.next == nil {
- break
- }
- swapped := atomic.CompareAndSwapPointer(
- &b.head,
- headp,
- unsafe.Pointer(head.next),
- )
- if swapped == true {
- atomic.AddInt32(&b.size, -1)
- break
- }
- }
- }
- return nil
-}
-
-// Head returns the oldest record node kept in memory. It can be used to
-// iterate over records, one by one, up to the last record.
-//
-// Note: new records can get added while iterating. Hence the number of records
-// iterated over might be larger than the maximum size.
-func (b *MemoryBackend) Head() *node {
- return (*node)(b.head)
-}
-
-type event int
-
-const (
- eventFlush event = iota
- eventStop
-)
-
-// ChannelMemoryBackend is very similar to the MemoryBackend, except that it
-// internally utilizes a channel.
-type ChannelMemoryBackend struct {
- maxSize int
- size int
- incoming chan *Record
- events chan event
- mu sync.Mutex
- running bool
- flushWg sync.WaitGroup
- stopWg sync.WaitGroup
- head, tail *node
-}
-
-// NewChannelMemoryBackend creates a simple in-memory logging backend which
-// utilizes a go channel for communication.
-//
-// Start will automatically be called by this function.
-func NewChannelMemoryBackend(size int) *ChannelMemoryBackend {
- backend := &ChannelMemoryBackend{
- maxSize: size,
- incoming: make(chan *Record, 1024),
- events: make(chan event),
- }
- backend.Start()
- return backend
-}
-
-// Start launches the internal goroutine which starts processing data from the
-// input channel.
-func (b *ChannelMemoryBackend) Start() {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- // Launch the goroutine unless it's already running.
- if b.running != true {
- b.running = true
- b.stopWg.Add(1)
- go b.process()
- }
-}
-
-func (b *ChannelMemoryBackend) process() {
- defer b.stopWg.Done()
- for {
- select {
- case rec := <-b.incoming:
- b.insertRecord(rec)
- case e := <-b.events:
- switch e {
- case eventStop:
- return
- case eventFlush:
- for len(b.incoming) > 0 {
- b.insertRecord(<-b.incoming)
- }
- b.flushWg.Done()
- }
- }
- }
-}
-
-func (b *ChannelMemoryBackend) insertRecord(rec *Record) {
- prev := b.tail
- b.tail = &node{Record: rec}
- if prev == nil {
- b.head = b.tail
- } else {
- prev.next = b.tail
- }
-
- if b.maxSize > 0 && b.size >= b.maxSize {
- b.head = b.head.next
- } else {
- b.size++
- }
-}
-
-// Flush waits until all records in the buffered channel have been processed.
-func (b *ChannelMemoryBackend) Flush() {
- b.flushWg.Add(1)
- b.events <- eventFlush
- b.flushWg.Wait()
-}
-
-// Stop signals the internal goroutine to exit and waits until it have.
-func (b *ChannelMemoryBackend) Stop() {
- b.mu.Lock()
- if b.running == true {
- b.running = false
- b.events <- eventStop
- }
- b.mu.Unlock()
- b.stopWg.Wait()
-}
-
-// Log implements the Log method required by Backend.
-func (b *ChannelMemoryBackend) Log(level Level, calldepth int, rec *Record) error {
- b.incoming <- rec
- return nil
-}
-
-// Head returns the oldest record node kept in memory. It can be used to
-// iterate over records, one by one, up to the last record.
-//
-// Note: new records can get added while iterating. Hence the number of records
-// iterated over might be larger than the maximum size.
-func (b *ChannelMemoryBackend) Head() *node {
- return b.head
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/multi.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/multi.go
deleted file mode 100644
index 3731653e68b..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/multi.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package logging
-
-// TODO remove Level stuff from the multi logger. Do one thing.
-
-// multiLogger is a log multiplexer which can be used to utilize multiple log
-// backends at once.
-type multiLogger struct {
- backends []LeveledBackend
-}
-
-// MultiLogger creates a logger which contain multiple loggers.
-func MultiLogger(backends ...Backend) LeveledBackend {
- var leveledBackends []LeveledBackend
- for _, backend := range backends {
- leveledBackends = append(leveledBackends, AddModuleLevel(backend))
- }
- return &multiLogger{leveledBackends}
-}
-
-// Log passes the log record to all backends.
-func (b *multiLogger) Log(level Level, calldepth int, rec *Record) (err error) {
- for _, backend := range b.backends {
- if backend.IsEnabledFor(level, rec.Module) {
- // Shallow copy of the record for the formatted cache on Record and get the
- // record formatter from the backend.
- r2 := *rec
- if e := backend.Log(level, calldepth+1, &r2); e != nil {
- err = e
- }
- }
- }
- return
-}
-
-// GetLevel returns the highest level enabled by all backends.
-func (b *multiLogger) GetLevel(module string) Level {
- var level Level
- for _, backend := range b.backends {
- if backendLevel := backend.GetLevel(module); backendLevel > level {
- level = backendLevel
- }
- }
- return level
-}
-
-// SetLevel propagates the same level to all backends.
-func (b *multiLogger) SetLevel(level Level, module string) {
- for _, backend := range b.backends {
- backend.SetLevel(level, module)
- }
-}
-
-// IsEnabledFor returns true if any of the backends are enabled for it.
-func (b *multiLogger) IsEnabledFor(level Level, module string) bool {
- for _, backend := range b.backends {
- if backend.IsEnabledFor(level, module) {
- return true
- }
- }
- return false
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/syslog.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/syslog.go
deleted file mode 100644
index 4faa5317092..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/syslog.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//+build !windows,!plan9
-
-package logging
-
-import "log/syslog"
-
-// SyslogBackend is a simple logger to syslog backend. It automatically maps
-// the internal log levels to appropriate syslog log levels.
-type SyslogBackend struct {
- Writer *syslog.Writer
-}
-
-// NewSyslogBackend connects to the syslog daemon using UNIX sockets with the
-// given prefix. If prefix is not given, the prefix will be derived from the
-// launched command.
-func NewSyslogBackend(prefix string) (b *SyslogBackend, err error) {
- var w *syslog.Writer
- w, err = syslog.New(syslog.LOG_CRIT, prefix)
- return &SyslogBackend{w}, err
-}
-
-// NewSyslogBackendPriority is the same as NewSyslogBackend, but with custom
-// syslog priority, like syslog.LOG_LOCAL3|syslog.LOG_DEBUG etc.
-func NewSyslogBackendPriority(prefix string, priority syslog.Priority) (b *SyslogBackend, err error) {
- var w *syslog.Writer
- w, err = syslog.New(priority, prefix)
- return &SyslogBackend{w}, err
-}
-
-// Log implements the Backend interface.
-func (b *SyslogBackend) Log(level Level, calldepth int, rec *Record) error {
- line := rec.Formatted(calldepth + 1)
- switch level {
- case CRITICAL:
- return b.Writer.Crit(line)
- case ERROR:
- return b.Writer.Err(line)
- case WARNING:
- return b.Writer.Warning(line)
- case NOTICE:
- return b.Writer.Notice(line)
- case INFO:
- return b.Writer.Info(line)
- case DEBUG:
- return b.Writer.Debug(line)
- default:
- }
- panic("unhandled log level")
-}
diff --git a/hack/tools/vendor/gopkg.in/op/go-logging.v1/syslog_fallback.go b/hack/tools/vendor/gopkg.in/op/go-logging.v1/syslog_fallback.go
deleted file mode 100644
index 91bc18de638..00000000000
--- a/hack/tools/vendor/gopkg.in/op/go-logging.v1/syslog_fallback.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013, Örjan Persson. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//+build windows plan9
-
-package logging
-
-import (
- "fmt"
-)
-
-type Priority int
-
-type SyslogBackend struct {
-}
-
-func NewSyslogBackend(prefix string) (b *SyslogBackend, err error) {
- return nil, fmt.Errorf("Platform does not support syslog")
-}
-
-func NewSyslogBackendPriority(prefix string, priority Priority) (b *SyslogBackend, err error) {
- return nil, fmt.Errorf("Platform does not support syslog")
-}
-
-func (b *SyslogBackend) Log(level Level, calldepth int, rec *Record) error {
- return fmt.Errorf("Platform does not support syslog")
-}
diff --git a/hack/tools/vendor/modules.txt b/hack/tools/vendor/modules.txt
index 4848b0be636..689edf19b4d 100644
--- a/hack/tools/vendor/modules.txt
+++ b/hack/tools/vendor/modules.txt
@@ -7,6 +7,9 @@
# cel.dev/expr v0.25.1
## explicit; go 1.23.0
cel.dev/expr
+# charm.land/lipgloss/v2 v2.0.3
+## explicit; go 1.25.0
+charm.land/lipgloss/v2
# codeberg.org/chavacava/garif v0.2.0
## explicit; go 1.23
codeberg.org/chavacava/garif
@@ -57,10 +60,15 @@ github.com/Antonboom/testifylint/internal/testify
## explicit; go 1.18
github.com/BurntSushi/toml
github.com/BurntSushi/toml/internal
+# github.com/ClickHouse/clickhouse-go-linter v1.2.0
+## explicit; go 1.24.0
+github.com/ClickHouse/clickhouse-go-linter/internal/util
+github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose
+github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr
# github.com/Djarvur/go-err113 v0.1.1
## explicit; go 1.23.0
github.com/Djarvur/go-err113
-# github.com/Masterminds/semver/v3 v3.4.0
+# github.com/Masterminds/semver/v3 v3.5.0
## explicit; go 1.21
github.com/Masterminds/semver/v3
# github.com/Microsoft/go-winio v0.6.2
@@ -104,13 +112,16 @@ github.com/ProtonMail/go-crypto/openpgp/packet
github.com/ProtonMail/go-crypto/openpgp/s2k
github.com/ProtonMail/go-crypto/openpgp/x25519
github.com/ProtonMail/go-crypto/openpgp/x448
-# github.com/a8m/envsubst v1.4.2
-## explicit; go 1.17
+# github.com/a8m/envsubst v1.4.3
+## explicit; go 1.24
github.com/a8m/envsubst/parse
+# github.com/agext/levenshtein v1.2.1
+## explicit
+github.com/agext/levenshtein
# github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
## explicit; go 1.15
github.com/ahmetb/gen-crd-api-reference-docs
-# github.com/alecthomas/chroma/v2 v2.23.1
+# github.com/alecthomas/chroma/v2 v2.24.1
## explicit; go 1.22
github.com/alecthomas/chroma/v2
github.com/alecthomas/chroma/v2/formatters
@@ -122,7 +133,7 @@ github.com/alecthomas/chroma/v2/styles
# github.com/alecthomas/go-check-sumtype v0.3.1
## explicit; go 1.22.0
github.com/alecthomas/go-check-sumtype
-# github.com/alecthomas/participle/v2 v2.1.1
+# github.com/alecthomas/participle/v2 v2.1.4
## explicit; go 1.18
github.com/alecthomas/participle/v2/lexer
# github.com/alexkohler/nakedret/v2 v2.0.6
@@ -144,15 +155,15 @@ github.com/alingse/nilnesserr/internal/typeparams
# github.com/antlr4-go/antlr/v4 v4.13.1
## explicit; go 1.22
github.com/antlr4-go/antlr/v4
-# github.com/ashanbrown/forbidigo/v2 v2.3.0
+# github.com/apparentlymart/go-textseg/v15 v15.0.0
+## explicit; go 1.16
+github.com/apparentlymart/go-textseg/v15/textseg
+# github.com/ashanbrown/forbidigo/v2 v2.3.1
## explicit; go 1.24.0
github.com/ashanbrown/forbidigo/v2/forbidigo
-# github.com/ashanbrown/makezero/v2 v2.1.0
+# github.com/ashanbrown/makezero/v2 v2.2.1
## explicit; go 1.24.0
github.com/ashanbrown/makezero/v2/makezero
-# github.com/aymanbagabas/go-osc52/v2 v2.0.1
-## explicit; go 1.16
-github.com/aymanbagabas/go-osc52/v2
# github.com/beorn7/perks v1.0.1
## explicit; go 1.11
github.com/beorn7/perks/quantile
@@ -171,8 +182,8 @@ github.com/blizzy78/varnamelen
# github.com/bombsimon/wsl/v4 v4.7.0
## explicit; go 1.23
github.com/bombsimon/wsl/v4
-# github.com/bombsimon/wsl/v5 v5.6.0
-## explicit; go 1.24.0
+# github.com/bombsimon/wsl/v5 v5.8.0
+## explicit; go 1.25.0
github.com/bombsimon/wsl/v5
# github.com/breml/bidichk v0.3.3
## explicit; go 1.23.0
@@ -180,8 +191,8 @@ github.com/breml/bidichk/pkg/bidichk
# github.com/breml/errchkjson v0.4.1
## explicit; go 1.23.0
github.com/breml/errchkjson
-# github.com/butuzov/ireturn v0.4.0
-## explicit; go 1.23.0
+# github.com/butuzov/ireturn v0.4.1
+## explicit; go 1.25.0
github.com/butuzov/ireturn/analyzer
github.com/butuzov/ireturn/analyzer/internal/config
github.com/butuzov/ireturn/analyzer/internal/types
@@ -212,25 +223,35 @@ github.com/cespare/xxhash/v2
# github.com/charithe/durationcheck v0.0.11
## explicit; go 1.16
github.com/charithe/durationcheck
-# github.com/charmbracelet/colorprofile v0.3.1
-## explicit; go 1.23.0
+# github.com/charmbracelet/colorprofile v0.4.3
+## explicit; go 1.25.0
github.com/charmbracelet/colorprofile
-# github.com/charmbracelet/lipgloss v1.1.0
-## explicit; go 1.18
-github.com/charmbracelet/lipgloss
-# github.com/charmbracelet/x/ansi v0.10.1
-## explicit; go 1.23.0
+# github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318
+## explicit; go 1.24.2
+github.com/charmbracelet/ultraviolet
+# github.com/charmbracelet/x/ansi v0.11.7
+## explicit; go 1.24.2
github.com/charmbracelet/x/ansi
+github.com/charmbracelet/x/ansi/kitty
github.com/charmbracelet/x/ansi/parser
-# github.com/charmbracelet/x/cellbuf v0.0.13
-## explicit; go 1.18
-github.com/charmbracelet/x/cellbuf
-# github.com/charmbracelet/x/term v0.2.1
-## explicit; go 1.18
+# github.com/charmbracelet/x/term v0.2.2
+## explicit; go 1.24.0
github.com/charmbracelet/x/term
+# github.com/charmbracelet/x/termios v0.1.1
+## explicit; go 1.18
+github.com/charmbracelet/x/termios
+# github.com/charmbracelet/x/windows v0.2.2
+## explicit; go 1.23.0
+github.com/charmbracelet/x/windows
# github.com/ckaznocha/intrange v0.3.1
## explicit; go 1.23.0
github.com/ckaznocha/intrange
+# github.com/clipperhouse/displaywidth v0.11.0
+## explicit; go 1.18
+github.com/clipperhouse/displaywidth
+# github.com/clipperhouse/uax29/v2 v2.7.0
+## explicit; go 1.18
+github.com/clipperhouse/uax29/v2/graphemes
# github.com/cloudflare/circl v1.6.3
## explicit; go 1.22.0
github.com/cloudflare/circl/dh/x25519
@@ -283,14 +304,14 @@ github.com/denis-tingaikin/go-header
# github.com/dimchansky/utfbom v1.1.1
## explicit
github.com/dimchansky/utfbom
-# github.com/dlclark/regexp2 v1.11.5
+# github.com/dlclark/regexp2 v1.12.0
## explicit; go 1.13
github.com/dlclark/regexp2
github.com/dlclark/regexp2/syntax
# github.com/dnephin/pflag v1.0.7
## explicit; go 1.12
github.com/dnephin/pflag
-# github.com/elliotchance/orderedmap v1.6.0
+# github.com/elliotchance/orderedmap v1.8.0
## explicit; go 1.12
github.com/elliotchance/orderedmap
# github.com/emicklei/go-restful/v3 v3.12.2
@@ -405,6 +426,9 @@ github.com/go-git/go-git/v5/utils/merkletrie/internal/frame
github.com/go-git/go-git/v5/utils/merkletrie/noder
github.com/go-git/go-git/v5/utils/sync
github.com/go-git/go-git/v5/utils/trace
+# github.com/go-ini/ini v1.67.0
+## explicit
+github.com/go-ini/ini
# github.com/go-logr/logr v1.4.3
## explicit; go 1.18
github.com/go-logr/logr
@@ -467,7 +491,7 @@ 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/goccy/go-json v0.10.3
+# github.com/goccy/go-json v0.10.6
## explicit; go 1.19
github.com/goccy/go-json
github.com/goccy/go-json/internal/decoder
@@ -478,7 +502,7 @@ github.com/goccy/go-json/internal/encoder/vm_color_indent
github.com/goccy/go-json/internal/encoder/vm_indent
github.com/goccy/go-json/internal/errors
github.com/goccy/go-json/internal/runtime
-# github.com/goccy/go-yaml v1.18.0
+# github.com/goccy/go-yaml v1.19.2
## explicit; go 1.21.0
github.com/goccy/go-yaml
github.com/goccy/go-yaml/ast
@@ -544,7 +568,7 @@ github.com/golang/groupcache/lru
# github.com/golangci/asciicheck v0.5.0
## explicit; go 1.23.0
github.com/golangci/asciicheck
-# github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32
+# github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202
## explicit; go 1.22.0
github.com/golangci/dupl/job
github.com/golangci/dupl/lib
@@ -558,7 +582,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.11.4
+# github.com/golangci/golangci-lint/v2 v2.12.2
## explicit; go 1.25.0
github.com/golangci/golangci-lint/v2/cmd/golangci-lint
github.com/golangci/golangci-lint/v2/internal/cache
@@ -571,6 +595,7 @@ github.com/golangci/golangci-lint/v2/internal/go/quoted
github.com/golangci/golangci-lint/v2/internal/x/tools/diff
github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs
github.com/golangci/golangci-lint/v2/internal/x/tools/driverutil
+github.com/golangci/golangci-lint/v2/jsonschema
github.com/golangci/golangci-lint/v2/pkg/commands
github.com/golangci/golangci-lint/v2/pkg/commands/internal
github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate
@@ -603,6 +628,7 @@ github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck
github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk
github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose
github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader
+github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint
github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx
github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck
github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar
@@ -743,6 +769,9 @@ github.com/golangci/plugin-module-register/register
# github.com/golangci/revgrep v0.8.0
## explicit; go 1.21
github.com/golangci/revgrep
+# github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba
+## explicit; go 1.25.0
+github.com/golangci/rowserrcheck/passes/rowserr
# github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e
## explicit; go 1.23.0
github.com/golangci/swaggoswag
@@ -818,13 +847,19 @@ github.com/grpc-ecosystem/grpc-gateway/v2/utilities
# github.com/hashicorp/go-immutable-radix/v2 v2.1.0
## explicit; go 1.18
github.com/hashicorp/go-immutable-radix/v2
-# github.com/hashicorp/go-version v1.8.0
+# github.com/hashicorp/go-version v1.9.0
## explicit
github.com/hashicorp/go-version
# github.com/hashicorp/golang-lru/v2 v2.0.7
## explicit; go 1.18
github.com/hashicorp/golang-lru/v2/internal
github.com/hashicorp/golang-lru/v2/simplelru
+# github.com/hashicorp/hcl/v2 v2.24.0
+## explicit; go 1.23.0
+github.com/hashicorp/hcl/v2
+github.com/hashicorp/hcl/v2/ext/customdecode
+github.com/hashicorp/hcl/v2/hclsyntax
+github.com/hashicorp/hcl/v2/hclwrite
# github.com/hexops/gotextdiff v1.0.3
## explicit; go 1.16
github.com/hexops/gotextdiff
@@ -839,12 +874,9 @@ github.com/jbenet/go-context/io
# github.com/jessevdk/go-flags v1.6.1
## explicit; go 1.20
github.com/jessevdk/go-flags
-# github.com/jgautheron/goconst v1.8.2
-## explicit; go 1.16
+# github.com/jgautheron/goconst v1.10.0
+## explicit; go 1.23
github.com/jgautheron/goconst
-# github.com/jingyugao/rowserrcheck v1.1.1
-## explicit; go 1.13
-github.com/jingyugao/rowserrcheck/passes/rowserr
# github.com/jinzhu/copier v0.4.0
## explicit; go 1.13
github.com/jinzhu/copier
@@ -914,13 +946,13 @@ github.com/leonklingele/grouper/pkg/analyzer/globals
github.com/leonklingele/grouper/pkg/analyzer/imports
github.com/leonklingele/grouper/pkg/analyzer/types
github.com/leonklingele/grouper/pkg/analyzer/vars
-# github.com/lucasb-eyer/go-colorful v1.2.0
+# github.com/lucasb-eyer/go-colorful v1.4.0
## explicit; go 1.12
github.com/lucasb-eyer/go-colorful
# github.com/macabu/inamedparam v0.2.0
## explicit; go 1.23.0
github.com/macabu/inamedparam
-# github.com/magiconair/properties v1.8.7
+# github.com/magiconair/properties v1.8.10
## explicit; go 1.19
github.com/magiconair/properties
# github.com/mailru/easyjson v0.9.0
@@ -932,8 +964,8 @@ github.com/mailru/easyjson/jwriter
## explicit; go 1.23.0
github.com/manuelarte/embeddedstructfieldcheck/analyzer
github.com/manuelarte/embeddedstructfieldcheck/internal
-# github.com/manuelarte/funcorder v0.5.0
-## explicit; go 1.23.0
+# github.com/manuelarte/funcorder v0.6.0
+## explicit; go 1.25.0
github.com/manuelarte/funcorder/analyzer
github.com/manuelarte/funcorder/internal
# github.com/maratori/testableexamples v1.0.1
@@ -951,8 +983,8 @@ github.com/mattn/go-colorable
# github.com/mattn/go-isatty v0.0.20
## explicit; go 1.15
github.com/mattn/go-isatty
-# github.com/mattn/go-runewidth v0.0.16
-## explicit; go 1.9
+# github.com/mattn/go-runewidth v0.0.23
+## explicit; go 1.20
github.com/mattn/go-runewidth
# github.com/mgechev/revive v1.15.0
## explicit; go 1.25.0
@@ -966,14 +998,17 @@ github.com/mgechev/revive/internal/typeparams
github.com/mgechev/revive/lint
github.com/mgechev/revive/logging
github.com/mgechev/revive/rule
-# github.com/mikefarah/yq/v4 v4.44.5
-## explicit; go 1.21.0
+# github.com/mikefarah/yq/v4 v4.53.2
+## explicit; go 1.25.0
github.com/mikefarah/yq/v4
github.com/mikefarah/yq/v4/cmd
github.com/mikefarah/yq/v4/pkg/yqlib
# github.com/mitchellh/go-homedir v1.1.0
## explicit
github.com/mitchellh/go-homedir
+# github.com/mitchellh/go-wordwrap v1.0.1
+## explicit; go 1.14
+github.com/mitchellh/go-wordwrap
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
## explicit
github.com/modern-go/concurrent
@@ -985,9 +1020,9 @@ github.com/modern-go/reflect2
github.com/moricho/tparallel
github.com/moricho/tparallel/pkg/ssafunc
github.com/moricho/tparallel/pkg/ssainstr
-# github.com/muesli/termenv v0.16.0
+# github.com/muesli/cancelreader v0.2.2
## explicit; go 1.17
-github.com/muesli/termenv
+github.com/muesli/cancelreader
# github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
## explicit
github.com/munnerz/goautoneg
@@ -1041,11 +1076,10 @@ github.com/openshift/crd-schema-checker/pkg/cmd/options
github.com/openshift/crd-schema-checker/pkg/defaultcomparators
github.com/openshift/crd-schema-checker/pkg/manifestcomparators
github.com/openshift/crd-schema-checker/pkg/resourceread
-# github.com/pelletier/go-toml/v2 v2.2.4
+# github.com/pelletier/go-toml/v2 v2.3.1
## explicit; go 1.21.0
github.com/pelletier/go-toml/v2
github.com/pelletier/go-toml/v2/internal/characters
-github.com/pelletier/go-toml/v2/internal/danger
github.com/pelletier/go-toml/v2/internal/tracker
github.com/pelletier/go-toml/v2/unstable
# github.com/pjbgf/sha1cd v0.6.0
@@ -1137,6 +1171,9 @@ github.com/russross/blackfriday/v2
# github.com/ryancurrah/gomodguard v1.4.1
## explicit; go 1.23.0
github.com/ryancurrah/gomodguard
+# github.com/ryancurrah/gomodguard/v2 v2.1.3
+## explicit; go 1.25.0
+github.com/ryancurrah/gomodguard/v2
# github.com/ryanrolds/sqlclosecheck v0.6.0
## explicit; go 1.25.0
github.com/ryanrolds/sqlclosecheck/pkg/analyzer
@@ -1157,7 +1194,7 @@ github.com/sashamelentyev/interfacebloat/pkg/analyzer
## explicit; go 1.23.0
github.com/sashamelentyev/usestdlibvars/pkg/analyzer
github.com/sashamelentyev/usestdlibvars/pkg/analyzer/internal/mapping
-# github.com/securego/gosec/v2 v2.24.8-0.20260309165252-619ce2117e08
+# github.com/securego/gosec/v2 v2.26.1
## explicit; go 1.25.0
github.com/securego/gosec/v2
github.com/securego/gosec/v2/analyzers
@@ -1190,8 +1227,8 @@ github.com/sourcegraph/conc
github.com/sourcegraph/conc/internal/multierror
github.com/sourcegraph/conc/iter
github.com/sourcegraph/conc/panics
-# github.com/sourcegraph/go-diff v0.7.0
-## explicit; go 1.14
+# github.com/sourcegraph/go-diff v0.8.0
+## explicit; go 1.20
github.com/sourcegraph/go-diff/diff
# github.com/spf13/afero v1.15.0
## explicit; go 1.23.0
@@ -1235,11 +1272,11 @@ github.com/stretchr/testify/mock
# github.com/subosito/gotenv v1.6.0
## explicit; go 1.18
github.com/subosito/gotenv
-# github.com/tetafro/godot v1.5.4
+# github.com/tetafro/godot v1.5.6
## explicit; go 1.22
github.com/tetafro/godot
-# github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67
-## explicit; go 1.12
+# github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4
+## explicit; go 1.22
github.com/timakin/bodyclose/passes/bodyclose
# github.com/timonwong/loggercheck v0.11.0
## explicit; go 1.22.0
@@ -1266,7 +1303,7 @@ github.com/ultraware/whitespace
# github.com/uudashr/gocognit v1.2.1
## explicit; go 1.24.0
github.com/uudashr/gocognit
-# github.com/uudashr/iface v1.4.1
+# github.com/uudashr/iface v1.4.2
## explicit; go 1.23.0
github.com/uudashr/iface/identical
github.com/uudashr/iface/internal/directive
@@ -1300,20 +1337,31 @@ github.com/yeya24/promlinter
# github.com/ykadowak/zerologlint v0.1.5
## explicit; go 1.19
github.com/ykadowak/zerologlint
-# github.com/yuin/gopher-lua v1.1.1
-## explicit; go 1.17
+# github.com/yuin/gopher-lua v1.1.2
+## explicit; go 1.23
github.com/yuin/gopher-lua
github.com/yuin/gopher-lua/ast
github.com/yuin/gopher-lua/parse
github.com/yuin/gopher-lua/pm
+# github.com/zclconf/go-cty v1.18.0
+## explicit; go 1.25
+github.com/zclconf/go-cty/cty
+github.com/zclconf/go-cty/cty/convert
+github.com/zclconf/go-cty/cty/ctymarks
+github.com/zclconf/go-cty/cty/ctystrings
+github.com/zclconf/go-cty/cty/function
+github.com/zclconf/go-cty/cty/function/stdlib
+github.com/zclconf/go-cty/cty/gocty
+github.com/zclconf/go-cty/cty/json
+github.com/zclconf/go-cty/cty/set
# gitlab.com/bosi/decorder v0.4.2
## explicit; go 1.20
gitlab.com/bosi/decorder
# go-simpler.org/musttag v0.14.0
## explicit; go 1.23.0
go-simpler.org/musttag
-# go-simpler.org/sloglint v0.11.1
-## explicit; go 1.23.0
+# go-simpler.org/sloglint v0.12.0
+## explicit; go 1.24.0
go-simpler.org/sloglint
# go.augendre.info/arangolint v0.4.0
## explicit; go 1.24.0
@@ -1416,6 +1464,10 @@ go.yaml.in/yaml/v2
# go.yaml.in/yaml/v3 v3.0.4
## explicit; go 1.16
go.yaml.in/yaml/v3
+# go.yaml.in/yaml/v4 v4.0.0-rc.4
+## explicit; go 1.18
+go.yaml.in/yaml/v4
+go.yaml.in/yaml/v4/internal/libyaml
# golang.org/x/crypto v0.50.0
## explicit; go 1.25.0
golang.org/x/crypto/argon2
@@ -1440,7 +1492,7 @@ golang.org/x/exp/slices
# golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358
## explicit; go 1.24.0
golang.org/x/exp/typeparams
-# golang.org/x/mod v0.35.0
+# golang.org/x/mod v0.36.0
## explicit; go 1.25.0
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile
@@ -1520,6 +1572,7 @@ golang.org/x/text/width
golang.org/x/time/rate
# golang.org/x/tools v0.44.0
## explicit; go 1.25.0
+golang.org/x/tools/cmd/stringer
golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/passes/appends
golang.org/x/tools/go/analysis/passes/asmdecl
@@ -1544,7 +1597,9 @@ golang.org/x/tools/go/analysis/passes/hostport
golang.org/x/tools/go/analysis/passes/httpmux
golang.org/x/tools/go/analysis/passes/httpresponse
golang.org/x/tools/go/analysis/passes/ifaceassert
+golang.org/x/tools/go/analysis/passes/inline
golang.org/x/tools/go/analysis/passes/inspect
+golang.org/x/tools/go/analysis/passes/internal/gofixdirective
golang.org/x/tools/go/analysis/passes/loopclosure
golang.org/x/tools/go/analysis/passes/lostcancel
golang.org/x/tools/go/analysis/passes/modernize
@@ -1592,6 +1647,7 @@ golang.org/x/tools/internal/aliases
golang.org/x/tools/internal/analysis/analyzerutil
golang.org/x/tools/internal/analysis/typeindex
golang.org/x/tools/internal/astutil
+golang.org/x/tools/internal/astutil/free
golang.org/x/tools/internal/event
golang.org/x/tools/internal/event/core
golang.org/x/tools/internal/event/keys
@@ -1607,6 +1663,7 @@ golang.org/x/tools/internal/packagepath
golang.org/x/tools/internal/packagesinternal
golang.org/x/tools/internal/pkgbits
golang.org/x/tools/internal/refactor
+golang.org/x/tools/internal/refactor/inline
golang.org/x/tools/internal/stdlib
golang.org/x/tools/internal/typeparams
golang.org/x/tools/internal/typesinternal
@@ -1734,9 +1791,6 @@ google.golang.org/protobuf/types/known/wrapperspb
# gopkg.in/inf.v0 v0.9.1
## explicit
gopkg.in/inf.v0
-# gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
-## explicit
-gopkg.in/op/go-logging.v1
# gopkg.in/warnings.v0 v0.1.2
## explicit
gopkg.in/warnings.v0