diff --git a/Makefile b/Makefile index 81731554e..46fc090d3 100644 --- a/Makefile +++ b/Makefile @@ -1,197 +1,293 @@ -# BUNDLE_VERSION defines the project version for the bundle. -# Update this value when you upgrade the version of your project. -# To re-generate a bundle for another specific version without changing the standard setup, you can: -# - use the BUNDLE_VERSION as arg of the bundle target (e.g make bundle BUNDLE_VERSION=0.0.2) -# - use environment variables to overwrite this value (e.g export BUNDLE_VERSION=0.0.2) -BUNDLE_VERSION ?= 1.19.0 -CERT_MANAGER_VERSION ?= "v1.19.2" -ISTIO_CSR_VERSION ?= "v0.15.0" +# Project path. +PROJECT_ROOT := $(shell git rev-parse --show-toplevel) -# CHANNELS define the bundle channels used in the bundle. -# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") -# To re-generate a bundle for other specific channels without changing the standard setup, you can: -# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) -# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") -CHANNELS ?= "stable-v1,stable-v1.19" -ifneq ($(origin CHANNELS), undefined) -BUNDLE_CHANNELS := --channels=$(CHANNELS) -endif +# Warn when an undefined variable is referenced, helping catch typos and missing definitions. +MAKEFLAGS += --warn-undefined-variables -# DEFAULT_CHANNEL defines the default channel used in the bundle. -# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") -# To re-generate a bundle for any other default channel without changing the default setup, you can: -# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) -# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") -DEFAULT_CHANNEL ?= stable-v1 -ifneq ($(origin DEFAULT_CHANNEL), undefined) -BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) -endif -BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) +# Setting SHELL to bash allows bash commands to be executed by recipes. +# Options are set to exit when a recipe line exits non-zero or a piped command fails. +SHELL := /usr/bin/env bash +.SHELLFLAGS := -euo pipefail -c -# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. -# This variable is used to construct full image tags for bundle and catalog images. -# -# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both -# openshift.io/cert-manager-operator-bundle:$VERSION and openshift.io/cert-manager-operator-catalog:$VERSION. -IMAGE_TAG_BASE ?= openshift.io/cert-manager-operator +# Ensure cache and config directories are writable (needed for CI environments where +# HOME may be unset or pointing to a non-writable directory like /). +export XDG_CACHE_HOME ?= $(PROJECT_ROOT)/_output/.cache +export XDG_CONFIG_HOME ?= $(PROJECT_ROOT)/_output/.config -# BUNDLE_IMG defines the image:tag used for the bundle. -# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) -BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(BUNDLE_VERSION) +# ============================================================================ +# Version Configuration +# ============================================================================ -# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command -BUNDLE_GEN_FLAGS ?= -q --overwrite=false --version $(BUNDLE_VERSION) $(BUNDLE_METADATA_OPTS) +# DEFAULT_VERSION is the default version to use for image tags when not set. +DEFAULT_VERSION := 1.19.0 -# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests -# You can enable this value if you would like to use SHA Based Digests -# To enable set flag to true -USE_IMAGE_DIGESTS ?= false -ifeq ($(USE_IMAGE_DIGESTS), true) - BUNDLE_GEN_FLAGS += --use-image-digests +# Helper function to validate semver (Major.Minor.Patch format) +# Returns 'valid' if the version matches semver (X.Y.Z) or 'latest', empty string otherwise +define validate-semver +$(shell echo '$(1)' | grep -Eq '^([0-9]+\.[0-9]+\.[0-9]+|latest)$$' && echo valid) +endef + +# Formats version for image tags: adds 'v' prefix for semver, keeps 'latest' as-is +# Usage: $(call format-image-tag,1.0.0) -> v1.0.0 +# $(call format-image-tag,latest) -> latest +define format-image-tag +$(shell if [ '$(1)' = 'latest' ]; then echo '$(1)'; else echo 'v$(1)'; fi) +endef + +# --- Project Versions --- + +# BUNDLE_VERSION defines the version for the operator bundle (must be valid semver: Major.Minor.Patch). +BUNDLE_VERSION ?= $(DEFAULT_VERSION) +ifneq ($(call validate-semver,$(BUNDLE_VERSION)),valid) +$(error BUNDLE_VERSION '$(BUNDLE_VERSION)' is not valid semver (expected: Major.Minor.Patch)) endif -# Image URL to use all building/pushing image targets -IMG ?= $(IMAGE_TAG_BASE):$(IMG_VERSION) +# IMG_VERSION defines the version tag for the operator image (must be valid semver: Major.Minor.Patch). +IMG_VERSION ?= latest +ifneq ($(call validate-semver,$(IMG_VERSION)),valid) +$(error IMG_VERSION '$(IMG_VERSION)' is not valid semver (expected: Major.Minor.Patch)) +endif + +# CATALOG_VERSION defines the version for the OLM catalog/index image (must be valid semver: Major.Minor.Patch). +CATALOG_VERSION ?= $(DEFAULT_VERSION) +ifneq ($(call validate-semver,$(CATALOG_VERSION)),valid) +$(error CATALOG_VERSION '$(CATALOG_VERSION)' is not valid semver (expected: Major.Minor.Patch)) +endif + +# --- Operand Versions --- + +# Versions of the cert-manager components managed by this operator +CERT_MANAGER_VERSION ?= v1.19.2 +ISTIO_CSR_VERSION ?= v0.15.0 + +# --- Test Versions --- # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.25.0 +ENVTEST_K8S_VERSION ?= 1.25.0 + +# ============================================================================ +# Path Configuration +# ============================================================================ + +# Package name. +PACKAGE := github.com/openshift/cert-manager-operator + +# Output directories +BIN_DIR := $(PROJECT_ROOT)/bin +OUTPUT_DIR := $(PROJECT_ROOT)/_output +ENVTEST_ASSETS_DIR := $(PROJECT_ROOT)/testbin + +# Binary name derived from package +BIN := $(PROJECT_ROOT)/$(lastword $(subst /, ,$(PACKAGE))) # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) -GOBIN=$(shell go env GOPATH)/bin +GOBIN := $(shell go env GOPATH)/bin else -GOBIN=$(shell go env GOBIN) +GOBIN := $(shell go env GOBIN) endif -PACKAGE=github.com/openshift/cert-manager-operator -PROJECT_ROOT := $(shell pwd) +# Tool binary paths (all built from vendor for consistency and performance) +CONTROLLER_GEN := $(BIN_DIR)/controller-gen +GOLANGCI_LINT := $(BIN_DIR)/golangci-lint +GOVULNCHECK := $(BIN_DIR)/govulncheck +HELM := $(BIN_DIR)/helm +KUSTOMIZE := $(BIN_DIR)/kustomize +OPERATOR_SDK := $(BIN_DIR)/operator-sdk +OPM := $(BIN_DIR)/opm +SETUP_ENVTEST := $(BIN_DIR)/setup-envtest +JSONNET := $(BIN_DIR)/jsonnet -BIN=$(lastword $(subst /, ,$(PACKAGE))) -BIN_DIR=$(PROJECT_ROOT)/bin -TOOLS_DIR=$(PROJECT_ROOT)/tools +# ============================================================================ +# Image Configuration +# ============================================================================ -GOLANGCI_LINT := $(BIN_DIR)/golangci-lint +# IMAGE_TAG_BASE defines the registry namespace and base name for all images. +# This is used to construct full image tags for operator, bundle, and catalog images. +IMAGE_TAG_BASE ?= openshift.io/cert-manager-operator -CONTROLLER_GEN := cd $(TOOLS_DIR) && GOFLAGS="" go run sigs.k8s.io/controller-tools/cmd/controller-gen +# Operator image +# Fixing the tag to latest, to align with the tag in config/manager/kustomization.yaml +IMG ?= $(IMAGE_TAG_BASE):$(call format-image-tag,$(IMG_VERSION)) -SETUP_ENVTEST := cd $(TOOLS_DIR) && GOFLAGS="" go run sigs.k8s.io/controller-runtime/tools/setup-envtest +# Bundle image (OLM operator bundle) +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:$(call format-image-tag,$(BUNDLE_VERSION)) -KUSTOMIZE := $(BIN_DIR)/kustomize +# Catalog/Index image (OLM catalog containing bundles) +CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:$(call format-image-tag,$(CATALOG_VERSION)) -# Setting SHELL to bash allows bash commands to be executed by recipes. -# Options are set to exit when a recipe line exits non-zero or a piped command fails. -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec +# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests. +# To enable: make bundle USE_IMAGE_DIGESTS=true +USE_IMAGE_DIGESTS ?= false + +# ============================================================================ +# Bundle / OLM Configuration +# ============================================================================ + +# CHANNELS define the bundle channels used in the bundle. +# To override: make bundle CHANNELS=candidate,fast,stable or export CHANNELS="candidate,fast,stable" +CHANNELS ?= stable-v1,stable-v1.19 +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# To override: make bundle DEFAULT_CHANNEL=stable or export DEFAULT_CHANNEL="stable" +DEFAULT_CHANNEL ?= stable-v1 +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif + +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command +BUNDLE_GEN_FLAGS ?= -q --overwrite=false --version $(BUNDLE_VERSION) $(BUNDLE_METADATA_OPTS) +ifeq ($(USE_IMAGE_DIGESTS), true) + BUNDLE_GEN_FLAGS += --use-image-digests +endif + +# ============================================================================ +# Container Configuration +# ============================================================================ +# Container engine to use for building and pushing images CONTAINER_ENGINE ?= podman -CONTAINER_PUSH_ARGS ?= $(if $(filter ${CONTAINER_ENGINE}, docker), , --tls-verify=${TLS_VERIFY}) -TLS_VERIFY ?= true -CONTAINER_IMAGE_NAME ?= registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.21 -BUNDLE_DIR := bundle -BUNDLE_MANIFEST_DIR := $(BUNDLE_DIR)/manifests -BUNDLE_IMG ?= olm-bundle:latest -INDEX_IMG ?= olm-bundle-index:latest -OPM_VERSION ?= v1.23.0 +# TLS verification for container pushes (disable for local registries) +TLS_VERIFY ?= true +CONTAINER_PUSH_ARGS ?= $(if $(filter $(CONTAINER_ENGINE),docker),,--tls-verify=$(TLS_VERIFY)) -OPERATOR_SDK_BIN=$(BIN_DIR)/operator-sdk +# Container image used for running make targets in a container +CONTAINER_IMAGE_NAME ?= registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.21 -HELM_BIN=$(BIN_DIR)/helm +# ============================================================================ +# Build Configuration +# ============================================================================ +# Git information for version embedding COMMIT ?= $(shell git rev-parse HEAD) SHORTCOMMIT ?= $(shell git rev-parse --short HEAD) -GOBUILD_VERSION_ARGS = -ldflags "-X $(PACKAGE)/pkg/version.SHORTCOMMIT=$(SHORTCOMMIT) -X $(PACKAGE)/pkg/version.COMMIT=$(COMMIT)" +# Go build flags +GOBUILD_VERSION_ARGS := -ldflags "-X $(PACKAGE)/pkg/version.SHORTCOMMIT=$(SHORTCOMMIT) -X $(PACKAGE)/pkg/version.COMMIT=$(COMMIT)" +GO := GO111MODULE=on CGO_ENABLED=1 go + +# ============================================================================ +# Test Configuration +# ============================================================================ + +# E2E test timeout E2E_TIMEOUT ?= 2h -# E2E_GINKGO_LABEL_FILTER is ginkgo label query for selecting tests. See -# https://onsi.github.io/ginkgo/#spec-labels. The default is to run tests on the AWS platform. -E2E_GINKGO_LABEL_FILTER ?= "Platform: isSubsetOf {AWS} && CredentialsMode: isSubsetOf {Mint}" -MANIFEST_SOURCE = https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml +# E2E_GINKGO_LABEL_FILTER is ginkgo label query for selecting tests. +# See https://onsi.github.io/ginkgo/#spec-labels +# The default is to run tests on the AWS platform. +E2E_GINKGO_LABEL_FILTER ?= Platform: isSubsetOf {AWS} && CredentialsMode: isSubsetOf {Mint} -##@ Development +# ============================================================================ +# Default Target +# ============================================================================ + +.PHONY: all +all: build verify + +# ============================================================================ +# Help +# ============================================================================ + +##@ General + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-25s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +# ============================================================================ +# Build Machinery Includes +# ============================================================================ # Include the library makefiles include $(addprefix ./vendor/github.com/openshift/build-machinery-go/make/, \ targets/openshift/bindata.mk \ ) -# generate bindata targets +# Generate bindata targets $(call add-bindata,assets,./bindata/...,bindata,assets,pkg/operator/assets/bindata.go) +# ============================================================================ +# Development +# ============================================================================ + +##@ Development + .PHONY: manifests -manifests: ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="$(PROJECT_ROOT)/..." output:crd:artifacts:config=$(PROJECT_ROOT)/config/crd/bases output:rbac:artifacts:config=$(PROJECT_ROOT)/config/rbac +manifests: $(CONTROLLER_GEN) ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. + $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="$(PROJECT_ROOT)/..." \ + output:crd:artifacts:config=$(PROJECT_ROOT)/config/crd/bases \ + output:rbac:artifacts:config=$(PROJECT_ROOT)/config/rbac .PHONY: generate -generate: ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. +generate: $(CONTROLLER_GEN) ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. $(CONTROLLER_GEN) object:headerFile="$(PROJECT_ROOT)/hack/boilerplate.go.txt" paths="$(PROJECT_ROOT)/api/..." hack/update-clientgen.sh +# Targets that need Go workspace mode (CI sets GOFLAGS=-mod=vendor which conflicts with go.work) +fmt vet test test-e2e run update-vendor update-dep: GOFLAGS= + .PHONY: fmt fmt: ## Run go fmt against code. - GOFLAGS="" go fmt ./... + go fmt ./... .PHONY: vet vet: ## Run go vet against code. - GOFLAGS="" go vet ./... + go vet ./... -ENVTEST_ASSETS_DIR ?= $(PROJECT_ROOT)/testbin .PHONY: test -test: manifests generate fmt vet ## Run tests. +test: manifests generate fmt vet $(SETUP_ENVTEST) ## Run unit tests. mkdir -p "$(ENVTEST_ASSETS_DIR)" - KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(ENVTEST_ASSETS_DIR) -p path)" GOFLAGS="" go test ./... -coverprofile cover.out - -update-manifests: $(HELM_BIN) - hack/update-cert-manager-manifests.sh $(MANIFEST_SOURCE) - hack/update-istio-csr-manifests.sh $(ISTIO_CSR_VERSION) -.PHONY: update-manifests - -.PHONY: update -update: generate update-manifests update-bindata - -.PHONY: update-with-container -update-with-container: - $(CONTAINER_ENGINE) run -ti --rm -v $(PROJECT_ROOT):/go/src/github.com/openshift/cert-manager-operator:z -w /go/src/github.com/openshift/cert-manager-operator $(CONTAINER_IMAGE_NAME) make update - -verify-scripts: verify-bindata - hack/verify-deepcopy.sh - hack/verify-clientgen.sh - hack/verify-bundle.sh -.PHONY: verify-scripts + KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(ENVTEST_ASSETS_DIR) -p path)" \ + go test ./... -coverprofile cover.out -.PHONY: verify -verify: verify-scripts verify-deps fmt vet +# Test name pattern for -run flag (TEST="TestIssuer|TestCertificate" or TEST="" to run all) +TEST ?= +.PHONY: test-e2e +test-e2e: test-e2e-wait-for-stable-state ## Run end-to-end tests. + go test -C $(PROJECT_ROOT)/test/e2e \ + -timeout $(E2E_TIMEOUT) \ + -count 1 -v -p 1 \ + -tags e2e -run "$(TEST)" . \ + -ginkgo.label-filter=$(E2E_GINKGO_LABEL_FILTER) -.PHONY: verify-with-container -verify-with-container: - $(CONTAINER_ENGINE) run -ti --rm -v $(PROJECT_ROOT):/go/src/github.com/openshift/cert-manager-operator:z -w /go/src/github.com/openshift/cert-manager-operator $(CONTAINER_IMAGE_NAME) make verify +.PHONY: test-e2e-wait-for-stable-state +test-e2e-wait-for-stable-state: + @echo "---- Waiting for stable state ----" + @# This ensures the test-e2e-debug-cluster is called if a timeout is reached. + oc wait --for=condition=Available=true deployment/cert-manager-cainjector -n cert-manager --timeout=120s || $(MAKE) test-e2e-debug-cluster + oc wait --for=condition=Available=true deployment/cert-manager -n cert-manager --timeout=120s || $(MAKE) test-e2e-debug-cluster + oc wait --for=condition=Available=true deployment/cert-manager-webhook -n cert-manager --timeout=120s || $(MAKE) test-e2e-debug-cluster + @echo "---- /Waiting for stable state ----" -.PHONY: verify-deps -verify-deps: - hack/verify-deps.sh +.PHONY: test-e2e-debug-cluster +test-e2e-debug-cluster: + @echo "---- Debugging the current state ----" + -oc get pod -n cert-manager-operator + -oc get pod -n cert-manager + -oc get co + -oc get csv --all-namespaces + -oc get crd | grep -i cert + -oc get subscriptions --all-namespaces + -oc logs deployment/cert-manager-operator -n cert-manager-operator + @echo "---- /Debugging the current state ----" -.PHONY: update-vendor -update-vendor: ## Update vendor directory for all modules in the workspace. - go mod tidy - cd tools && go mod tidy - cd test/e2e && go mod tidy - go work vendor +.PHONY: lint +lint: $(GOLANGCI_LINT) ## Run golangci-lint linter. + $(GOLANGCI_LINT) run --verbose --config $(PROJECT_ROOT)/.golangci.yaml $(PROJECT_ROOT)/... -.PHONY: update-dep -update-dep: ## Update a dependency across all modules. Usage: make update-dep PKG=k8s.io/api@v0.35.0 - @if [ -z "$(PKG)" ]; then echo "Usage: make update-dep PKG=package@version"; exit 1; fi - @echo "Updating $(PKG) in main module..." - go get $(PKG) - @echo "Updating $(PKG) in tools module..." - -cd tools && go get $(PKG) - @echo "Updating $(PKG) in test/e2e module..." - -cd test/e2e && go get $(PKG) - @echo "Running update-vendor..." - $(MAKE) update-vendor +.PHONY: lint-fix +lint-fix: $(GOLANGCI_LINT) ## Run golangci-lint linter and fix issues. + $(GOLANGCI_LINT) run --config $(PROJECT_ROOT)/.golangci.yaml --fix $(PROJECT_ROOT)/... .PHONY: local-run -local-run: build +local-run: build ## Run the operator locally against the cluster configured in ~/.kube/config. RELATED_IMAGE_CERT_MANAGER_WEBHOOK=quay.io/jetstack/cert-manager-webhook:$(CERT_MANAGER_VERSION) \ RELATED_IMAGE_CERT_MANAGER_CA_INJECTOR=quay.io/jetstack/cert-manager-cainjector:$(CERT_MANAGER_VERSION) \ RELATED_IMAGE_CERT_MANAGER_CONTROLLER=quay.io/jetstack/cert-manager-controller:$(CERT_MANAGER_VERSION) \ @@ -204,37 +300,35 @@ local-run: build --config=./hack/local-run-config.yaml \ --kubeconfig=$${KUBECONFIG:-$$HOME/.kube/config} \ --namespace=cert-manager-operator -.PHONY: local-run +# ============================================================================ +# Build +# ============================================================================ ##@ Build -GO=GO111MODULE=on CGO_ENABLED=1 go -# Check for required tools -.PHONY: check-tools -check-tools: - @command -v go >/dev/null 2>&1 || { echo "WARNING: go is not installed. Please install it to avoid issues."; } - @command -v $(CONTAINER_ENGINE) >/dev/null 2>&1 || { echo "WARNING: $(CONTAINER_ENGINE) is not installed. Please install it to avoid issues."; } - @command -v kubectl >/dev/null 2>&1 || { echo "WARNING: kubectl is not installed. Please install it to avoid issues."; } +.PHONY: build +build: generate fmt vet build-operator ## Build operator binary with all checks and code generation. .PHONY: build-operator -build-operator: ## Build operator binary, no additional checks or code generation +build-operator: ## Build operator binary only (no checks or code generation). @GOFLAGS="-mod=vendor" source hack/go-fips.sh && $(GO) build $(GOBUILD_VERSION_ARGS) -o $(BIN) -.PHONY: build -build: check-tools generate fmt vet build-operator ## Build operator binary. - .PHONY: run -run: check-tools manifests generate fmt vet ## Run a controller from your host. +run: manifests generate fmt vet ## Run the operator from your host (for development). go run $(PACKAGE) .PHONY: image-build -image-build: check-tools ## Build container image with the operator. - $(CONTAINER_ENGINE) build -t ${IMG} . +image-build: ## Build container image with the operator. + $(CONTAINER_ENGINE) build -t $(IMG) . .PHONY: image-push -image-push: check-tools ## Push container image with the operator. - $(CONTAINER_ENGINE) push ${IMG} ${CONTAINER_PUSH_ARGS} +image-push: ## Push container image with the operator. + $(CONTAINER_ENGINE) push $(IMG) $(CONTAINER_PUSH_ARGS) + +# ============================================================================ +# Deployment +# ============================================================================ ##@ Deployment @@ -244,7 +338,7 @@ deploy: $(KUSTOMIZE) manifests ## Deploy controller to the K8s cluster specified echo "Namespace 'cert-manager-operator' does not exist. Creating it..."; \ kubectl create namespace cert-manager-operator; \ } - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) $(KUSTOMIZE) build config/default | kubectl apply -f - .PHONY: undeploy @@ -252,101 +346,180 @@ undeploy: $(KUSTOMIZE) ## Undeploy controller from the K8s cluster specified in $(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found -f - kubectl delete namespace cert-manager-operator --ignore-not-found +# ============================================================================ +# Bundle / OLM +# ============================================================================ + +##@ Bundle / OLM + .PHONY: bundle -bundle: check-tools $(OPERATOR_SDK_BIN) $(KUSTOMIZE) manifests - $(OPERATOR_SDK_BIN) generate kustomize manifests -q +bundle: $(OPERATOR_SDK) $(KUSTOMIZE) manifests ## Generate bundle manifests and metadata, then validate generated files. + $(OPERATOR_SDK) generate kustomize manifests -q cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) - $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK_BIN) generate bundle -q --version $(BUNDLE_VERSION) $(BUNDLE_METADATA_OPTS) - $(OPERATOR_SDK_BIN) bundle validate $(BUNDLE_DIR) + $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + $(OPERATOR_SDK) bundle validate ./bundle + +.PHONY: bundle-build +bundle-build: bundle ## Build the bundle image. + $(CONTAINER_ENGINE) build -t $(BUNDLE_IMG) -f bundle.Dockerfile . + +.PHONY: bundle-push +bundle-push: ## Push the bundle image. + $(CONTAINER_ENGINE) push $(BUNDLE_IMG) $(CONTAINER_PUSH_ARGS) + +.PHONY: catalog-build +catalog-build: $(OPM) ## Build the OLM catalog image. + $(OPM) index add --container-tool $(CONTAINER_ENGINE) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMG) + +.PHONY: catalog-push +catalog-push: ## Push the OLM catalog image. + $(CONTAINER_ENGINE) push $(CATALOG_IMG) $(CONTAINER_PUSH_ARGS) + +# ============================================================================ +# Verification +# ============================================================================ + +##@ Verification + +.PHONY: verify +verify: verify-scripts verify-deps fmt vet ## Run all verification checks. + +.PHONY: verify-scripts +verify-scripts: verify-bindata ## Run script-based verification checks. + hack/verify-deepcopy.sh + hack/verify-clientgen.sh + hack/verify-bundle.sh + +.PHONY: verify-deps +verify-deps: ## Verify Go module dependencies are correct. + hack/verify-deps.sh + +.PHONY: verify-with-container +verify-with-container: ## Run verification in a container. + $(CONTAINER_ENGINE) run -ti --rm \ + -v $(PROJECT_ROOT):/go/src/github.com/openshift/cert-manager-operator:z \ + -w /go/src/github.com/openshift/cert-manager-operator \ + $(CONTAINER_IMAGE_NAME) make verify -.PHONY: bundle-image-build -bundle-image-build: check-tools bundle - $(CONTAINER_ENGINE) build -t ${BUNDLE_IMG} -f bundle.Dockerfile . +.PHONY: govulncheck +govulncheck: $(GOVULNCHECK) $(OUTPUT_DIR) ## Run govulncheck vulnerability scan. + @./hack/govulncheck.sh $(GOVULNCHECK) $(OUTPUT_DIR) -.PHONY: bundle-image-push -bundle-image-push: check-tools - $(CONTAINER_ENGINE) push ${BUNDLE_IMG} +# ============================================================================ +# Maintenance +# ============================================================================ -.PHONY: index-image-build -index-image-build: check-tools opm - $(OPM) index add --container-tool $(CONTAINER_ENGINE) --mode semver --tag $(INDEX_IMG) --bundles $(BUNDLE_IMG) +##@ Maintenance -.PHONY: index-image-push -index-image-push: check-tools - $(CONTAINER_ENGINE) push ${INDEX_IMG} +.PHONY: update +update: generate update-manifests update-bindata ## Update all generated code and manifests. -OPM=$(BIN_DIR)/opm -.PHONY: opm -opm: ## Download opm locally if necessary. - $(call get-bin,$(OPM),$(BIN_DIR),https://github.com/operator-framework/operator-registry/releases/download/$(OPM_VERSION)/linux-amd64-opm) +.PHONY: update-manifests +update-manifests: $(HELM) $(JSONNET) ## Update cert-manager and istio-csr operand manifests. + hack/update-cert-manager-manifests.sh $(CERT_MANAGER_VERSION) + hack/update-istio-csr-manifests.sh $(ISTIO_CSR_VERSION) +.PHONY: update-vendor +update-vendor: ## Update vendor directory for all modules in the workspace. + go mod tidy + go mod tidy -C $(PROJECT_ROOT)/test + go mod tidy -C $(PROJECT_ROOT)/tools + go work sync + go work vendor + +PKG ?= +.PHONY: update-dep +update-dep: ## Update a dependency across all modules. Usage: make update-dep PKG=k8s.io/api@v0.35.0 + @if [ -z "$(PKG)" ]; then echo "Usage: make update-dep PKG=package@version"; exit 1; fi + @echo "Updating $(PKG) in main module..." + go get $(PKG) + @echo "Updating $(PKG) in test module..." + go get -C $(PROJECT_ROOT)/test $(PKG) + @echo "Updating $(PKG) in tools module..." + go get -C $(PROJECT_ROOT)/tools $(PKG) + @echo "Running update-vendor..." + $(MAKE) update-vendor + +.PHONY: update-with-container +update-with-container: ## Run update targets in a container. + $(CONTAINER_ENGINE) run -ti --rm \ + -v $(PROJECT_ROOT):/go/src/github.com/openshift/cert-manager-operator:z \ + -w /go/src/github.com/openshift/cert-manager-operator \ + $(CONTAINER_IMAGE_NAME) make update + +.PHONY: clean +clean: ## Clean up generated files and build artifacts. + @echo "Cleaning up build artifacts..." + go clean + rm -rf $(BIN_DIR) $(OUTPUT_DIR) $(ENVTEST_ASSETS_DIR) cover.out $(BIN) + +# ============================================================================ +# Tool Installation +# ============================================================================ + +##@ Tools + +# go-install-tool will 'go build' any package from vendor with custom target and name of the binary. +# $1 - target path with name of binary +# $2 - package path in vendor +define go-install-tool +@{ \ + bin_path=$(1); \ + package=$(2); \ + echo "Building $${package}..."; \ + mkdir -p $$(dirname $${bin_path}); \ + rm -f $${bin_path} 2>/dev/null || true; \ + go build -mod=vendor -o $${bin_path} $${package}; \ +} +endef + +# get-bin downloads a binary from a URL if it doesn't exist. +# $1 - target path with name of binary +# $2 - target directory +# $3 - download URL +# $4 - (optional) SHA256 checksum for verification define get-bin @[ -f "$(1)" ] || { \ - [ ! -d "$(2)" ] && mkdir -p "$(2)" || true ;\ - echo "Downloading $(3)" ;\ - curl -fL $(3) -o "$(1)" ;\ - chmod +x "$(1)" ;\ + mkdir -p "$(2)"; \ + echo "Downloading $(3)..."; \ + curl -fsSL "$(3)" -o "$(1)"; \ + if [ -n "$(4)" ]; then echo "$(4) $(1)" | sha256sum -c -; fi; \ + chmod +x "$(1)"; \ } endef -.PHONY: test-e2e -test-e2e: test-e2e-wait-for-stable-state - cd test/e2e && GOFLAGS="" go test \ - -timeout $(E2E_TIMEOUT) \ - -count 1 \ - -v \ - -p 1 \ - -tags e2e \ - -run "$(TEST)" \ - . \ - -ginkgo.label-filter=$(E2E_GINKGO_LABEL_FILTER) +## Location to install dependencies to +$(BIN_DIR): + mkdir -p $(BIN_DIR) -.PHONY: test-e2e-wait-for-stable-state -test-e2e-wait-for-stable-state: - @echo "---- Waiting for stable state ----" - # This ensures the test-e2e-debug-cluster is called if a timeout is reached. - oc wait --for=condition=Available=true deployment/cert-manager-cainjector -n cert-manager --timeout=120s || $(MAKE) test-e2e-debug-cluster - oc wait --for=condition=Available=true deployment/cert-manager -n cert-manager --timeout=120s || $(MAKE) test-e2e-debug-cluster - oc wait --for=condition=Available=true deployment/cert-manager-webhook -n cert-manager --timeout=120s || $(MAKE) test-e2e-debug-cluster - @echo "---- /Waiting for stable state ----" +$(OUTPUT_DIR): + @mkdir -p $(OUTPUT_DIR) -.PHONY: test-e2e-debug-cluster -test-e2e-debug-cluster: - @echo "---- Debugging the current state ----" - - oc get pod -n cert-manager-operator - - oc get pod -n cert-manager - - oc get co - - oc get csv --all-namespaces - - oc get crd | grep -i cert - - oc get subscriptions --all-namespaces - - oc logs deployment/cert-manager-operator -n cert-manager-operator - @echo "---- /Debugging the current state ----" - -.PHONY: lint -lint: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) run --verbose --config $(PROJECT_ROOT)/.golangci.yaml $(PROJECT_ROOT)/... +# Tools built from vendor +$(CONTROLLER_GEN): $(BIN_DIR) ## Build controller-gen from vendor. + $(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen) -.PHONY: lint-fix -lint-fix: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) run --config $(PROJECT_ROOT)/.golangci.yaml --fix $(PROJECT_ROOT)/... +$(GOLANGCI_LINT): $(BIN_DIR) ## Build golangci-lint from vendor. + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint) -$(GOLANGCI_LINT): - mkdir -p $(BIN_DIR) - cd $(TOOLS_DIR) && GOFLAGS="" go build -o $(GOLANGCI_LINT) github.com/golangci/golangci-lint/v2/cmd/golangci-lint +$(KUSTOMIZE): $(BIN_DIR) ## Build kustomize from vendor. + $(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5) -$(OPERATOR_SDK_BIN): - mkdir -p $(BIN_DIR) - hack/operator-sdk.sh $(OPERATOR_SDK_BIN) +$(SETUP_ENVTEST): $(BIN_DIR) ## Build setup-envtest from vendor. + $(call go-install-tool,$(SETUP_ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest) -$(HELM_BIN): - mkdir -p $(BIN_DIR) - hack/helm.sh $(HELM_BIN) +$(GOVULNCHECK): $(BIN_DIR) ## Build govulncheck from vendor. + $(call go-install-tool,$(GOVULNCHECK),golang.org/x/vuln/cmd/govulncheck) -$(KUSTOMIZE): - mkdir -p $(BIN_DIR) - cd $(TOOLS_DIR) && GOFLAGS="" go build -o $(KUSTOMIZE) sigs.k8s.io/kustomize/kustomize/v5 +$(JSONNET): $(BIN_DIR) ## Build jsonnet from vendor. + $(call go-install-tool,$(JSONNET),github.com/google/go-jsonnet/cmd/jsonnet) -.PHONY: clean -clean: - go clean - rm -f $(BIN) +# Tools downloaded as binaries (with checksum verification) +$(HELM): ## Download helm locally if necessary. + hack/download-tools.sh helm $(HELM) + +$(OPERATOR_SDK): ## Download operator-sdk locally if necessary. + hack/download-tools.sh operator-sdk $(OPERATOR_SDK) + +$(OPM): ## Download opm locally if necessary. + hack/download-tools.sh opm $(OPM) diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index b24731044..7b37fddcf 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -12,7 +12,7 @@ namePrefix: cert-manager-operator- #commonLabels: # someName: someValue -bases: +resources: - ../crd - ../rbac - ../manager @@ -33,33 +33,3 @@ bases: # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. # 'CERTMANAGER' needs to be enabled to use ca injection #- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -vars: [] -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index ab5ff95a7..28132145a 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -5,3 +5,4 @@ kind: Kustomization images: - name: controller newName: openshift.io/cert-manager-operator + newTag: latest diff --git a/config/scorecard/kustomization.yaml b/config/scorecard/kustomization.yaml index 50cd2d084..a9a84a85a 100644 --- a/config/scorecard/kustomization.yaml +++ b/config/scorecard/kustomization.yaml @@ -1,6 +1,6 @@ resources: - bases/config.yaml -patchesJson6902: +patches: - path: patches/basic.config.yaml target: group: scorecard.operatorframework.io @@ -13,4 +13,4 @@ patchesJson6902: version: v1alpha3 kind: Configuration name: config -#+kubebuilder:scaffold:patchesJson6902 +#+kubebuilder:scaffold:patches diff --git a/go.mod b/go.mod index fef1554ec..38bd70aac 100644 --- a/go.mod +++ b/go.mod @@ -4,28 +4,24 @@ go 1.25.0 require ( github.com/cert-manager/cert-manager v1.19.2 - github.com/go-bindata/go-bindata v3.1.2+incompatible github.com/go-logr/logr v1.4.3 github.com/google/go-cmp v0.7.0 github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b - github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee github.com/openshift/client-go v0.0.0-20251205093018-96a6cbc1420c github.com/openshift/library-go v0.0.0-20251205073205-ab8d51820e0b - github.com/operator-framework/operator-lib v0.11.0 - github.com/spf13/cobra v1.10.1 + github.com/operator-framework/operator-lib v0.19.0 + github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 - golang.org/x/tools v0.38.0 k8s.io/api v0.34.1 k8s.io/apiextensions-apiserver v0.34.1 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 - k8s.io/code-generator v0.34.1 k8s.io/component-base v0.34.1 k8s.io/klog/v2 v2.130.1 k8s.io/kubernetes v1.34.1 - k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d - sigs.k8s.io/controller-runtime v0.22.3 + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 + sigs.k8s.io/controller-runtime v0.22.4 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 ) @@ -70,8 +66,8 @@ require ( 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/ginkgo/v2 v2.23.3 // indirect - github.com/onsi/gomega v1.36.3 // indirect + github.com/onsi/ginkgo/v2 v2.27.5 // indirect + github.com/onsi/gomega v1.39.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -99,18 +95,18 @@ require ( go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.45.0 // indirect + golang.org/x/crypto v0.47.0 // indirect golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.47.0 // indirect + golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.31.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.13.0 // indirect + golang.org/x/tools v0.41.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250721164621-a45f3dfb1074 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect @@ -121,9 +117,8 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiserver v0.34.1 // indirect - k8s.io/component-helpers v0.32.1 // indirect + k8s.io/component-helpers v0.34.1 // indirect k8s.io/controller-manager v0.32.1 // indirect - k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d // indirect k8s.io/kms v0.34.1 // indirect k8s.io/kube-aggregator v0.34.1 // indirect k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect diff --git a/go.sum b/go.sum index 6b949c8e2..b3f35dd53 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,8 @@ cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +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/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= @@ -49,8 +52,6 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= -github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE= -github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -138,28 +139,22 @@ 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/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/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.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= -github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE= +github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b h1:yfjc5FZliZbhtT+VxUK5qfCbO9yXMmdJTsOJ7ilA7RQ= github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= -github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee h1:+Sp5GGnjHDhT/a/nQ1xdp43UscBMr7G5wxsYotyhzJ4= -github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20251205093018-96a6cbc1420c h1:TBE0Gl+oCo/SNEhLKZQNNH/SWHXrpGyhAw7P0lAqdHg= github.com/openshift/client-go v0.0.0-20251205093018-96a6cbc1420c/go.mod h1:IsynOWZAfdH+BgWimcFQRtI41Id9sgdhsCEjIk8ACLw= github.com/openshift/jetstack-cert-manager v1.19.2 h1:P/NabqqbsL+MzeODK8nAcVdzDenaSMWVYKvYlsBWfJI= github.com/openshift/jetstack-cert-manager v1.19.2/go.mod h1:e9NzLtOKxTw7y99qLyWGmPo6mrC1Nh0EKKcMkRfK+GE= github.com/openshift/library-go v0.0.0-20251205073205-ab8d51820e0b h1:Fh2PJw4DP4zylB7oOu2T1C5rxhI0G36aj1D71vwS5S4= github.com/openshift/library-go v0.0.0-20251205073205-ab8d51820e0b/go.mod h1:ErDfiIrPHH+menTP/B4LKd0nxFDdvCbTamAc6SWMIh8= -github.com/operator-framework/operator-lib v0.11.0 h1:eYzqpiOfq9WBI4Trddisiq/X9BwCisZd3rIzmHRC9Z8= -github.com/operator-framework/operator-lib v0.11.0/go.mod h1:RpyKhFAoG6DmKTDIwMuO6pI3LRc8IE9rxEYWy476o6g= +github.com/operator-framework/operator-lib v0.19.0 h1:az6ogYj21rtU0SF9uYctRLyKp2dtlqTsmpfehFy6Ce8= +github.com/operator-framework/operator-lib v0.19.0/go.mod h1:KxycAjFnHt0DBtHmH3Jm7yHcY5sdrshPKTqM/HKAQ08= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -187,8 +182,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -256,34 +251,34 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +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= 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.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4= golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc= 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.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= 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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -291,26 +286,22 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= -golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= -golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= -golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= -golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -336,8 +327,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -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/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -351,16 +340,12 @@ k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA= k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0= k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= -k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc= -k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= -k8s.io/component-helpers v0.32.1 h1:TwdsSM1vW9GjnfX18lkrZbwE5G9psCIS2/rhenTDXd8= -k8s.io/component-helpers v0.32.1/go.mod h1:1JT1Ei3FD29yFQ18F3laj1WyvxYdHIhyxx6adKMFQXI= +k8s.io/component-helpers v0.34.1 h1:gWhH3CCdwAx5P3oJqZKb4Lg5FYZTWVbdWtOI8n9U4XY= +k8s.io/component-helpers v0.34.1/go.mod h1:4VgnUH7UA/shuBur+OWoQC0xfb69sy/93ss0ybZqm3c= k8s.io/controller-manager v0.32.1 h1:z3oQp1O5l0cSzM/MKf8V4olhJ9TmnELoJRPcV/v1s+Y= k8s.io/controller-manager v0.32.1/go.mod h1:dVA1UZPbqHH4hEhrrnLvQ4d5qVQCklNB8GEzYV59v/4= -k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0= -k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kms v0.34.1 h1:iCFOvewDPzWM9fMTfyIPO+4MeuZ0tcZbugxLNSHFG4w= @@ -373,12 +358,12 @@ k8s.io/kubelet v0.32.1 h1:bB91GvMsZb+LfzBxnjPEr1Fal/sdxZtYphlfwAaRJGw= k8s.io/kubelet v0.32.1/go.mod h1:4sAEZ6PlewD0GroV3zscY7llym6kmNNTVmUI/Qshm6w= k8s.io/kubernetes v1.34.1 h1:F3p8dtpv+i8zQoebZeK5zBqM1g9x1aIdnA5vthvcuUk= k8s.io/kubernetes v1.34.1/go.mod h1:iu+FhII+Oc/1gGWLJcer6wpyih441aNFHl7Pvm8yPto= -k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= -k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 h1:qPrZsv1cwQiFeieFlRqT627fVZ+tyfou/+S5S0H5ua0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y= -sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= +sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= +sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= sigs.k8s.io/gateway-api v1.4.0 h1:ZwlNM6zOHq0h3WUX2gfByPs2yAEsy/EenYJB78jpQfQ= sigs.k8s.io/gateway-api v1.4.0/go.mod h1:AR5RSqciWP98OPckEjOjh2XJhAe2Na4LHyXD2FUY7Qk= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= diff --git a/go.work b/go.work index 9973b5f8e..a8642068d 100644 --- a/go.work +++ b/go.work @@ -2,6 +2,6 @@ go 1.25.0 use ( . + ./test ./tools - ./test/e2e ) diff --git a/go.work.sum b/go.work.sum index 90a8c1a90..25b7a39d9 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,15 +1,24 @@ bitbucket.org/bertimus9/systemstat v0.5.0/go.mod h1:EkUWPp8lKFPMXP8vnbpT5JDI0W/sTiLZAvN8ONWErHY= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20250130201111-63bb56e20495.1/go.mod h1:novQBstnxcGpfKf8qGRATqn1anQKwMJIbH5Q581jibU= +cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.112.2 h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go v0.121.2 h1:v2qQpN6Dx9x2NmwrqlesOt3Ys4ol5/lFZ6Mg1B7OJCg= +cloud.google.com/go v0.121.2/go.mod h1:nRFlrHq39MNVWu+zESP2PosMWA0ryJw8KUBZ2iZpxbw= cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE= cloud.google.com/go/compute v1.6.1 h1:2sMmt8prCn7DPaG4Pmh0N3Inmc8cT8ae5k1M6VJ9Wqc= cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= codeberg.org/go-fonts/liberation v0.5.0/go.mod h1:zS/2e1354/mJ4pGzIIaEtm/59VFCFnYC7YV6YdGl5GU= @@ -47,15 +56,19 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/anthropics/anthropic-sdk-go v1.19.0/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4/go.mod h1:xNLZLn4SusktBQ5moqUOgiDKGz3a7vHwF4W0KD+WBPc= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bufbuild/protovalidate-go v0.9.1/go.mod h1:5jptBxfvlY51RhX32zR6875JfPBRXUsQjyZjm/NqkLQ= github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= @@ -63,7 +76,15 @@ github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +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/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.9.2 h1:92AGsQmNTRMzuzHEYfCdjQeUzTrgE1vfO5/7fEVoXdY= +github.com/charmbracelet/x/ansi v0.9.2/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/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -77,6 +98,7 @@ github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsx github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/corefile-migration v1.0.26/go.mod h1:56DPqONc3njpVPsdilEnfijCwNGC3/kTJLl7i7SPavY= github.com/coreos/go-oidc v2.3.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cristalhq/acmd v0.12.0/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= @@ -86,6 +108,7 @@ github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHz github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/elastic/crd-ref-docs v0.2.0/go.mod h1:0bklkJhTG7nC6AVsdDi0wt5bGoqvzdZSzMMQkilZ6XM= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -96,9 +119,9 @@ github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1 github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= @@ -113,17 +136,21 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 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.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/goccmack/gocc v0.0.0-20230228185258-2292f9e40198/go.mod h1:DTh/Y2+NbnOVVoypCCQrovMPDKUGp4yZpSbWg5D0XIM= -github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= @@ -150,24 +177,28 @@ github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhS github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= github.com/google/cadvisor v0.52.1/go.mod h1:OAhPcx1nOm5YwMh/JhpUOMKyv1YKLRtS9KgzWPndHmA= +github.com/google/cel-go v0.23.0/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo= github.com/google/certificate-transparency-go v1.3.1/go.mod h1:gg+UQlx6caKEDQ9EElFOujyxEQEfOiQzAt6782Bvi8k= github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gookit/color v1.6.0/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= @@ -192,12 +223,14 @@ github.com/hashicorp/vault/sdk v0.20.0/go.mod h1:xEjAt/n/2lHBAkYiRPRmvf1d5B6Hlis github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/ishidawataru/sctp v0.0.0-20250521072954-ae8eb7fa7995/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -207,25 +240,33 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/dots v1.0.0/go.mod h1:rykuMydC9t3wfkM+ccYH3U3ss03vZGg6h3hmOznXLH0= github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/ipvs v1.1.0/go.mod h1:4VJMWuf098bsUMmZEiD4Tjk/O7mOn3l1PTD3s4OoYAs= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= @@ -236,20 +277,26 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= +github.com/mozilla/tls-observatory v0.0.0-20250923143331-eef96233227e/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/openai/openai-go/v3 v3.8.1/go.mod h1:UOpNxkqC9OdNXNUfpNByKOtB4jAL0EssQXq5p8gO0Xs= github.com/opencontainers/cgroups v0.0.1/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/operator-framework/api v0.15.0/go.mod h1:scnY9xqSeCsOdtJtNoHIXd7OtHZ14gj1hkDA4+DlgLY= +github.com/operator-framework/api v0.31.0/go.mod h1:57oCiHNeWcxmzu1Se8qlnwEKr/GGXnuHvspIYFCcXmY= github.com/otiai10/mint v1.3.1 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -258,12 +305,15 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -276,35 +326,62 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= +github.com/shirou/gopsutil/v4 v4.25.11/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= +github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA= +go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ= +go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8= +go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk= go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= +go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U= +go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo= +go.etcd.io/etcd/pkg/v3 v3.6.5/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU= +go.etcd.io/etcd/server/v3 v3.6.5/go.mod h1:PLuhyVXz8WWRhzXDsl3A3zv/+aK9e4A9lpQkqawIaH0= go.etcd.io/gofail v0.2.0/go.mod h1:nL3ILMGfkXTekKI3clMBNazKnjUZjYLKmBHzsVAnC1o= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= @@ -316,15 +393,19 @@ go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zL go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= @@ -333,19 +414,24 @@ golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/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-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -359,18 +445,32 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/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-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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= @@ -380,16 +480,22 @@ golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0 golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/plot v0.15.2/go.mod h1:DX+x+DWso3LTha+AdkJEv5Txvi+Tql3KAGkehP0/Ubg= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genai v1.37.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk= google.golang.org/genproto v0.0.0-20230525234025-438c736192d0 h1:x1vNwUhVOcsYoKyEGCZBH694SBmmBjA2EfauFVEI2+M= +google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20250929231259-57b25ae835d4/go.mod h1:YUQUKndxDbAanQC0ln4pZ3Sis3N5sqgDte2XQqufkJc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= @@ -397,7 +503,9 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= @@ -410,12 +518,17 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -424,9 +537,13 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= k8s.io/cri-api v0.32.1/go.mod h1:DCzMuTh2padoinefWME0G678Mc3QFbLMF2vEweGzBAI= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0= +k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kms v0.35.0 h1:/x87FED2kDSo66csKtcYCEHsxF/DBlNl7LfJ1fVQs1o= +k8s.io/kms v0.35.0/go.mod h1:VT+4ekZAdrZDMgShK37vvlyHUVhwI9t/9tvh0AyCWmQ= k8s.io/system-validators v1.10.1/go.mod h1:awfSS706v9R12VC7u7K89FKfqVy44G+E0L1A0FX9Wmw= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= @@ -434,6 +551,7 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h6 sigs.k8s.io/knftables v0.0.17/go.mod h1:f/5ZLKYEUPUhVjUCg6l80ACdL7CIIyeL0DxfgojGRTk= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/structured-merge-diff/v6 v6.2.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= software.sslmate.com/src/go-pkcs12 v0.6.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= diff --git a/hack/download-tools.sh b/hack/download-tools.sh new file mode 100755 index 000000000..5a0df8444 --- /dev/null +++ b/hack/download-tools.sh @@ -0,0 +1,204 @@ +#!/bin/bash +# +# Downloads and verifies external tool binaries. +# Usage: +# ./hack/download-tools.sh [tool] [output_path] +# ./hack/download-tools.sh # Download all tools to default paths +# ./hack/download-tools.sh helm # Download helm to default path +# ./hack/download-tools.sh helm ./bin/helm # Download helm to specified path +# +# Supported tools: helm, opm, operator-sdk + +set -eou pipefail + +# Tool versions +HELM_VERSION="${HELM_VERSION:-v3.17.1}" +OPM_VERSION="${OPM_VERSION:-v1.23.0}" +OPERATOR_SDK_VERSION="${OPERATOR_SDK_VERSION:-v1.25.1}" + +# Default output directory +DEFAULT_BIN_DIR="${BIN_DIR:-./bin}" + +# Platform detection +GOOS=$(go env GOOS) +GOARCH=$(go env GOARCH) + +# Validate platform +validate_platform() { + if [[ "$GOOS" != "linux" && "$GOOS" != "darwin" ]]; then + echo "ERROR: Unsupported OS: $GOOS" + exit 1 + fi + if [[ "$GOARCH" != "amd64" && "$GOARCH" != "arm64" && "$GOARCH" != "ppc64le" && "$GOARCH" != "s390x" ]]; then + echo "ERROR: Unsupported architecture: $GOARCH" + exit 1 + fi +} + +# Verify checksum of a downloaded file +# Args: $1 = file path, $2 = expected hash +verify_checksum() { + local file="$1" + local expected_hash="$2" + + if [[ -z "${expected_hash}" ]]; then + echo "ERROR: Empty checksum provided" + return 1 + fi + + if command -v sha256sum >/dev/null 2>&1; then + echo "${expected_hash} ${file}" | sha256sum -c - + elif command -v shasum >/dev/null 2>&1; then + echo "${expected_hash} ${file}" | shasum -a 256 -c - + else + echo "ERROR: sha256sum or shasum is required for checksum verification" + return 1 + fi +} + +# Extract checksum from checksums file +# Args: $1 = checksums file, $2 = binary name pattern +extract_checksum() { + local checksums_file="$1" + local pattern="$2" + + grep "${pattern}$" "${checksums_file}" | awk '{print $1}' +} + +# Download helm +download_helm() { + local output_path="${1:-${DEFAULT_BIN_DIR}/helm}" + local version="${HELM_VERSION}" + + local tar_filename="helm-${version}-${GOOS}-${GOARCH}.tar.gz" + local download_url="https://get.helm.sh/${tar_filename}" + local checksum_url="${download_url}.sha256sum" + + local tempdir + tempdir=$(mktemp -d) + # shellcheck disable=SC2064 # Intentionally expand tempdir now, not at trap time + trap "rm -rf '${tempdir}'" RETURN + + echo "> downloading helm ${version}" + curl --silent --location -o "${tempdir}/${tar_filename}" "${download_url}" + + echo "> verifying checksum" + curl --silent --location -o "${tempdir}/checksum.sha256" "${checksum_url}" + local expected_hash + expected_hash=$(awk '{print $1}' "${tempdir}/checksum.sha256") + verify_checksum "${tempdir}/${tar_filename}" "${expected_hash}" + + echo "> extracting binary" + tar -C "${tempdir}" -xzf "${tempdir}/${tar_filename}" + mkdir -p "$(dirname "${output_path}")" + mv "${tempdir}/${GOOS}-${GOARCH}/helm" "${output_path}" + chmod +x "${output_path}" + + echo "> helm available at ${output_path}" +} + +# Download opm +download_opm() { + local output_path="${1:-${DEFAULT_BIN_DIR}/opm}" + local version="${OPM_VERSION}" + + local bin_name="${GOOS}-${GOARCH}-opm" + local download_url="https://github.com/operator-framework/operator-registry/releases/download/${version}" + + local tempdir + tempdir=$(mktemp -d) + # shellcheck disable=SC2064 # Intentionally expand tempdir now, not at trap time + trap "rm -rf '${tempdir}'" RETURN + + echo "> downloading opm ${version}" + curl --silent --location -o "${tempdir}/${bin_name}" "${download_url}/${bin_name}" + + echo "> verifying checksum" + curl --silent --location -o "${tempdir}/checksums.txt" "${download_url}/checksums.txt" + local expected_hash + expected_hash=$(extract_checksum "${tempdir}/checksums.txt" "${bin_name}") + if [[ -z "${expected_hash}" ]]; then + echo "ERROR: Could not find checksum for ${bin_name}" + exit 1 + fi + verify_checksum "${tempdir}/${bin_name}" "${expected_hash}" + + echo "> installing binary" + mkdir -p "$(dirname "${output_path}")" + mv "${tempdir}/${bin_name}" "${output_path}" + chmod +x "${output_path}" + + echo "> opm available at ${output_path}" +} + +# Download operator-sdk +download_operator_sdk() { + local output_path="${1:-${DEFAULT_BIN_DIR}/operator-sdk}" + local version="${OPERATOR_SDK_VERSION}" + + local bin_name="operator-sdk_${GOOS}_${GOARCH}" + local download_url="https://github.com/operator-framework/operator-sdk/releases/download/${version}" + + local tempdir + tempdir=$(mktemp -d) + # shellcheck disable=SC2064 # Intentionally expand tempdir now, not at trap time + trap "rm -rf '${tempdir}'" RETURN + + echo "> downloading operator-sdk ${version}" + curl --silent --location -o "${tempdir}/${bin_name}" "${download_url}/${bin_name}" + + echo "> verifying checksum" + curl --silent --location -o "${tempdir}/checksums.txt" "${download_url}/checksums.txt" + local expected_hash + expected_hash=$(extract_checksum "${tempdir}/checksums.txt" "${bin_name}") + if [[ -z "${expected_hash}" ]]; then + echo "ERROR: Could not find checksum for ${bin_name}" + exit 1 + fi + verify_checksum "${tempdir}/${bin_name}" "${expected_hash}" + + echo "> installing binary" + mkdir -p "$(dirname "${output_path}")" + mv "${tempdir}/${bin_name}" "${output_path}" + chmod +x "${output_path}" + + echo "> operator-sdk available at ${output_path}" +} + +# Download all tools +download_all() { + download_helm + download_opm + download_operator_sdk +} + +# Main +main() { + command -v curl &> /dev/null || { echo "ERROR: curl command not found" && exit 1; } + validate_platform + + local tool="${1:-all}" + local output_path="${2:-}" + + case "${tool}" in + helm) + download_helm "${output_path}" + ;; + opm) + download_opm "${output_path}" + ;; + operator-sdk) + download_operator_sdk "${output_path}" + ;; + all) + download_all + ;; + *) + echo "ERROR: Unknown tool '${tool}'" + echo "Supported tools: helm, opm, operator-sdk, all" + exit 1 + ;; + esac +} + +main "$@" diff --git a/hack/govulncheck.sh b/hack/govulncheck.sh new file mode 100755 index 000000000..31af2ec48 --- /dev/null +++ b/hack/govulncheck.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash + +set -o nounset +set -o pipefail +set -o errexit + +# Script to run govulncheck and filter known vulnerabilities. +# Usage: ./hack/govulncheck.sh +# +# Arguments: +# govulncheck_binary: Path to the govulncheck binary +# output_dir: Directory to store results +# +# Environment variables: +# ARTIFACT_DIR: If set and directory exists, results are copied there for CI artifact collection + +# Known vulnerabilities to ignore (in vendored packages, not operator code). +# Each vulnerability ID has been reviewed and deemed acceptable. +# +## Below vulnerabilities are in the kubernetes package, which impacts the server and not the operator, which is the client. +# - https://pkg.go.dev/vuln/GO-2025-3547 - Kubernetes kube-apiserver Vulnerable to Race Condition in k8s.io/kubernetes +# - https://pkg.go.dev/vuln/GO-2025-3521 - Kubernetes GitRepo Volume Inadvertent Local Repository Access in k8s.io/kubernetes +# - https://pkg.go.dev/vuln/GO-2025-4240 - Half-blind Server Side Request Forgery in kube-controller-manager through in-tree Portworx StorageClass in k8s.io/kubernetes +# +## Below vulnerabilities are in the go packages, which impacts the operator code and fixed in 1.25.6, but is not available downstream yet. +# - https://pkg.go.dev/vuln/GO-2026-4341 - Memory exhaustion in query parameter parsing in net/url +# - https://pkg.go.dev/vuln/GO-2026-4340 - Handshake messages may be processed at the incorrect encryption level in crypto/tls +# - https://pkg.go.dev/vuln/GO-2025-4175 - Improper application of excluded DNS name constraints when verifying wildcard names in crypto/x509 +# - https://pkg.go.dev/vuln/GO-2025-4155 - Excessive resource consumption when printing error string for host certificate validation in crypto/x509 +KNOWN_VULNS_PATTERN="GO-2025-3547|GO-2025-3521|GO-2025-4240|GO-2026-4341|GO-2026-4340|GO-2025-4175|GO-2025-4155" + +GOVULNCHECK_BIN="${1:-}" +OUTPUT_DIR="${2:-}" + +if [[ -z "${GOVULNCHECK_BIN}" ]] || [[ -z "${OUTPUT_DIR}" ]]; then + echo "Usage: $0 " + exit 1 +fi + +RESULTS_FILE="${OUTPUT_DIR}/govulncheck.results" + +echo "Running govulncheck vulnerability scan..." +mkdir -p "${OUTPUT_DIR}" + +# Run govulncheck and capture output (don't fail on vulnerabilities found) +"${GOVULNCHECK_BIN}" ./... > "${RESULTS_FILE}" 2>&1 || true + +# Copy results to ARTIFACT_DIR if in CI environment +if [[ -n "${ARTIFACT_DIR:-}" ]] && [[ -d "${ARTIFACT_DIR}" ]]; then + cp "${RESULTS_FILE}" "${ARTIFACT_DIR}/" + echo "Results copied to ${ARTIFACT_DIR}/govulncheck.results" +fi + +# Verify govulncheck actually ran successfully +if ! grep -q "pkg.go.dev" "${RESULTS_FILE}"; then + echo "" + echo "-- ERROR -- govulncheck may have failed to run" + echo "Please review ${RESULTS_FILE} for details" + echo "" + cat "${RESULTS_FILE}" + exit 1 +fi + +echo "Filtering known vulnerabilities and counting new ones..." + +# Find new vulnerabilities (not in known list) +if [[ -n "${KNOWN_VULNS_PATTERN}" ]]; then + new_vulns=$(grep "pkg.go.dev" "${RESULTS_FILE}" | grep -Ev "${KNOWN_VULNS_PATTERN}" || true) +else + new_vulns=$(grep "pkg.go.dev" "${RESULTS_FILE}" || true) +fi + +if [[ -n "${new_vulns}" ]]; then + reported=$(echo "${new_vulns}" | wc -l) + echo "" + echo "-- ERROR -- ${reported} new vulnerabilities reported:" + echo "${new_vulns}" + echo "" + echo "Please review ${RESULTS_FILE} for details" + echo "To ignore these vulnerabilities, add them to KNOWN_VULNS_PATTERN with valid justification" + echo "" + exit 1 +else + echo "✓ Vulnerability scan passed - no new issues found" +fi diff --git a/hack/helm.sh b/hack/helm.sh deleted file mode 100755 index 04bd330ad..000000000 --- a/hack/helm.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -eou pipefail - -OUTPUT_PATH=${1:-./bin/helm} -VERSION="v3.17.1" - -GOOS=$(go env GOOS) -GOARCH=$(go env GOARCH) - -TAR_FILENAME="helm-${VERSION}-${GOOS}-${GOARCH}.tar.gz" -TAR_DL_URL="https://get.helm.sh/${TAR_FILENAME}" - -TEMP_DIR=$(mktemp -d) - -echo "> downloading helm binary" - -curl --silent --location -o "${TEMP_DIR}/${TAR_FILENAME}" "${TAR_DL_URL}" -tar -C "${TEMP_DIR}" -xzf "${TEMP_DIR}/${TAR_FILENAME}" -mv "${TEMP_DIR}/${GOOS}-${GOARCH}/helm" "${OUTPUT_PATH}" - -echo "> helm binary available at ${OUTPUT_PATH}" diff --git a/hack/lib/init.sh b/hack/lib/init.sh index 49e0178ee..baf3fc147 100644 --- a/hack/lib/init.sh +++ b/hack/lib/init.sh @@ -12,5 +12,4 @@ set -o pipefail API_GROUP_VERSIONS=" operator/v1alpha1 " -API_PACKAGES=" -" +API_PACKAGES="" diff --git a/hack/operator-sdk.sh b/hack/operator-sdk.sh deleted file mode 100755 index 9cb0888bb..000000000 --- a/hack/operator-sdk.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -e - -VERSION="1.25.1" - -OUTPUT_PATH=${1:-./bin/operator-sdk} - -GOOS=$(go env GOOS) -GOARCH=$(go env GOARCH) -BIN="operator-sdk" -BIN_ARCH="${BIN}_${GOOS}_${GOARCH}" -OPERATOR_SDK_DL_URL="https://github.com/operator-framework/operator-sdk/releases/download/v${VERSION}" - -if [[ "$GOOS" != "linux" && "$GOOS" != "darwin" ]]; then - echo "Unsupported OS $GOOS" - exit 1 -fi - -if [[ "$GOARCH" != "amd64" && "$GOARCH" != "arm64" && "$GOARCH" != "ppc64le" && "$GOARCH" != "s390x" ]]; then - echo "Unsupported architecture $GOARCH" - exit 1 -fi - -command -v curl &> /dev/null || { echo "can't find curl command" && exit 1; } - -TEMPDIR=$(mktemp -d) -BIN_PATH="${TEMPDIR}/${BIN_ARCH}" - -echo "> downloading binary" -curl --silent --location -o "${BIN_PATH}" "${OPERATOR_SDK_DL_URL}/operator-sdk_${GOOS}_${GOARCH}" - -echo "> installing binary" -mv "${BIN_PATH}" "${OUTPUT_PATH}" -chmod +x "${OUTPUT_PATH}" -rm -rf "${TEMPDIR}" - -echo "> operator-sdk binary available at ${OUTPUT_PATH}" diff --git a/hack/update-cert-manager-manifests.sh b/hack/update-cert-manager-manifests.sh index 3402e921c..d607c5a8c 100755 --- a/hack/update-cert-manager-manifests.sh +++ b/hack/update-cert-manager-manifests.sh @@ -5,15 +5,14 @@ set -e source "$(dirname "${BASH_SOURCE}")/lib/init.sh" source "$(dirname "${BASH_SOURCE}")/lib/yq.sh" -MANIFEST_SOURCE=${1:?"missing Cert Manager manifest url. You can use either http:// or file://"} +CERT_MANAGER_VERSION=${1:?"missing cert-manager version. Please specify a version from https://github.com/cert-manager/cert-manager/releases"} +MANIFEST_SOURCE="https://github.com/cert-manager/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml" mkdir -p ./_output echo "---- Downloading manifest file from $MANIFEST_SOURCE ----" curl -NLs "$MANIFEST_SOURCE" -o ./_output/manifest.yaml -GOFLAGS="" go install -C tools github.com/google/go-jsonnet/cmd/jsonnet - echo "---- Patching manifest ----" # Upstream manifest includes yaml items in a single file as separate yaml documents. # JSON cannot handle this so create one yaml document which includes an array of items instead. @@ -25,7 +24,7 @@ echo "---- Patching manifest ----" # Patch manifest using jsonnet. # This produces a map of patched target items having the filename as key and the patched item as value. -jsonnet \ +./bin/jsonnet \ --tla-code-file manifest=_output/manifest_as_array.json \ jsonnet/main.jsonnet \ | ./bin/yq e '.' - \ diff --git a/hack/update-clientgen.sh b/hack/update-clientgen.sh index e12b78de5..bee08c416 100755 --- a/hack/update-clientgen.sh +++ b/hack/update-clientgen.sh @@ -4,8 +4,15 @@ set -o errexit set -o nounset set -o pipefail -SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. -CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../../../k8s.io/code-generator)} +# kube_codegen.sh runs from module cache which has no vendor directory +# so all Go commands it runs need module mode +export GOFLAGS="" + +SCRIPT_ROOT=$(git rev-parse --show-toplevel) + +# code-generator shell scripts aren't vendored (go work vendor only copies .go files) +# so we fetch the module path from the module cache +CODEGEN_PKG=${CODEGEN_PKG:-$(go mod download -json k8s.io/code-generator | grep '"Dir"' | cut -d'"' -f4)} source "${CODEGEN_PKG}/kube_codegen.sh" diff --git a/hack/update-protobuf.sh b/hack/update-protobuf.sh index d2eb319df..5be19447a 100755 --- a/hack/update-protobuf.sh +++ b/hack/update-protobuf.sh @@ -2,7 +2,7 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" -SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. +SCRIPT_ROOT=$(git rev-parse --show-toplevel) if [[ "$(protoc --version)" != "libprotoc 3."* ]]; then echo "Generating protobuf requires protoc 3.0.x. Please download and @@ -17,11 +17,13 @@ fi rm -rf go-to-protobuf rm -rf protoc-gen-gogo -GOFLAGS="" go build -C tools -o ../_output/bin/go-to-protobuf k8s.io/code-generator/cmd/go-to-protobuf -GOFLAGS="" go build -C tools -o ../_output/bin/protoc-gen-gogo k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo +# Build from root to use workspace vendor +mkdir -p _output/bin +go build -mod=vendor -o _output/bin/go-to-protobuf k8s.io/code-generator/cmd/go-to-protobuf +go build -mod=vendor -o _output/bin/protoc-gen-gogo k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo PATH="$PATH:_output/bin" go-to-protobuf \ - --output-base="${GOPATH}/src" \ + --output-dir="${GOPATH}/src" \ --apimachinery-packages='-k8s.io/apimachinery/pkg/util/intstr,-k8s.io/apimachinery/pkg/api/resource,-k8s.io/apimachinery/pkg/runtime/schema,-k8s.io/apimachinery/pkg/runtime,-k8s.io/apimachinery/pkg/apis/meta/v1,-k8s.io/apimachinery/pkg/apis/meta/v1beta1,-k8s.io/api/core/v1,-k8s.io/api/rbac/v1' \ --go-header-file=${SCRIPT_ROOT}/hack/empty.txt \ --proto-import=${SCRIPT_ROOT}/third_party/protobuf \ diff --git a/hack/update-swagger-docs.sh b/hack/update-swagger-docs.sh index d72c92dce..1eaaaf511 100755 --- a/hack/update-swagger-docs.sh +++ b/hack/update-swagger-docs.sh @@ -2,7 +2,7 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" -SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. +SCRIPT_ROOT=$(git rev-parse --show-toplevel) # Generates types_swagger_doc_generated file for the given group version. # $1: Name of the group version diff --git a/hack/verify-clientgen.sh b/hack/verify-clientgen.sh index 8360ddd56..20fc8b68d 100755 --- a/hack/verify-clientgen.sh +++ b/hack/verify-clientgen.sh @@ -4,7 +4,7 @@ set -o errexit set -o nounset set -o pipefail -SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. +SCRIPT_ROOT=$(git rev-parse --show-toplevel) "${SCRIPT_ROOT}/hack/update-clientgen.sh" diff --git a/hack/verify-crds-version-upgrade.sh b/hack/verify-crds-version-upgrade.sh index 362d0c480..c2eaebf6c 100755 --- a/hack/verify-crds-version-upgrade.sh +++ b/hack/verify-crds-version-upgrade.sh @@ -7,7 +7,7 @@ # 3. apply all the v1 crds from the current head, and dump the spec of each crd to #crdName-after file. # 4. compare #crdName-before and #crdName-after for v1beta1 crd if it is switched to v1 in dev branch. -SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. +SCRIPT_ROOT=$(git rev-parse --show-toplevel) TMP_ROOT="${SCRIPT_ROOT}/_tmp" KUBECTL="./_output/tools/kubebuilder/kubectl --server=http://127.0.0.1:8080" mkdir -p "${TMP_ROOT}" diff --git a/hack/verify-deps.sh b/hack/verify-deps.sh index 3d3d68dce..f23ea23e2 100755 --- a/hack/verify-deps.sh +++ b/hack/verify-deps.sh @@ -1,26 +1,87 @@ -#!/bin/bash -set -euo pipefail - -function print_failure { - echo "There are unexpected changes to the vendor tree following 'go work vendor' and 'go mod tidy'. Please" - echo "run these commands locally and double-check the Git repository for unexpected changes which may" - echo "need to be committed." - exit 1 +#!/usr/bin/env bash + +set -o nounset +set -o pipefail +set -o errexit + +# Check for packages with multiple versions in vendor/modules.txt +# This can cause build failures due to API incompatibilities between versions +function check_vendor_version_conflicts { + local modules_txt="vendor/modules.txt" + if [[ ! -f "$modules_txt" ]]; then + echo "Warning: $modules_txt not found, skipping version conflict check" + return 0 + fi + + # Extract package names (without versions) and find duplicates + # Exclude lines with "=>" (replace directives) as they create expected "duplicates" + local duplicates + duplicates=$(grep "^# " "$modules_txt" | grep -v "=>" | awk '{print $2}' | sort | uniq -d) + + if [[ -z "$duplicates" ]]; then + echo "No duplicate package versions found in vendor" + return 0 + fi + + # All duplicates are now treated as errors to keep versions uniform + echo "ERROR: Found packages with multiple versions in vendor!" + echo "This can cause build failures or unexpected behavior." + echo "" + echo "Affected packages:" + for pkg in $duplicates; do + grep "^# $pkg " "$modules_txt" + done + echo "" + echo "To fix, align package versions across all workspace modules:" + echo " 1. Identify which module has the older version" + echo " 2. Run: go get -C @" + echo " 3. Run: go mod tidy && go mod tidy -C tools && go mod tidy -C test" + echo " 4. Run: go work vendor" + return 1 } -if [ "${OPENSHIFT_CI:-false}" = true ]; then - # Clear GOFLAGS to ensure workspace mode works correctly with go.work - # (CI sets GOFLAGS=-mod=vendor which conflicts with go.work) - export GOFLAGS="" +# Updates the dependencies in all go modules to verify, there are no +# uncommitted changed. +function update_deps { + if [ "${OPENSHIFT_CI:-false}" = true ]; then + # Clear GOFLAGS to ensure workspace mode works correctly with go.work + # (CI sets GOFLAGS=-mod=vendor which conflicts with go.work) + export GOFLAGS="" + + # Tidy all modules + go mod tidy + go mod tidy -C ./test + go mod tidy -C ./tools - # Tidy all modules - go mod tidy - (cd tools && go mod tidy) - (cd test/e2e && go mod tidy) + # Sync all module versions in the workspace + go work sync - # Vendor all workspace modules into a single vendor directory - go work vendor + # Vendor all workspace modules into a single vendor directory + go work vendor - test -z "$(git status --porcelain | \grep -v '^??')" || print_failure - echo "verified Go modules" + check_vendor_version_conflicts + + # Check for any changes including untracked files (for CI environments) + changes=$(git status --porcelain) + + if [[ -n "${changes}" ]]; then + echo "ERROR: There are uncommitted or untracked changes. Please commit or remove them." + echo "Changed files:" + git status --short + exit 1 + fi + fi +} + +############################################## +############### MAIN ####################### +############################################## + +# Allow running just the version check locally with: ./hack/verify-deps.sh --check-versions +if [[ "${1:-}" == "--check-versions" ]]; then + check_vendor_version_conflicts + exit $? fi + +# Check all dependenices are committed +update_deps diff --git a/hack/verify-protobuf.sh b/hack/verify-protobuf.sh index e05f4e7b7..8201fb8bb 100755 --- a/hack/verify-protobuf.sh +++ b/hack/verify-protobuf.sh @@ -2,7 +2,7 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" -SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. +SCRIPT_ROOT=$(git rev-parse --show-toplevel) TMP_ROOT="${SCRIPT_ROOT}/_tmp" cleanup() { diff --git a/hack/verify-swagger-docs.sh b/hack/verify-swagger-docs.sh index 7dbbc925c..c4edfd87d 100755 --- a/hack/verify-swagger-docs.sh +++ b/hack/verify-swagger-docs.sh @@ -2,7 +2,7 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" -SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. +SCRIPT_ROOT=$(git rev-parse --show-toplevel) TMP_ROOT="${SCRIPT_ROOT}/_tmp" cleanup() { diff --git a/hack/verify-types.sh b/hack/verify-types.sh index 0e410b63e..469e0fc98 100755 --- a/hack/verify-types.sh +++ b/hack/verify-types.sh @@ -1,7 +1,9 @@ #!/bin/sh -eu +SCRIPT_ROOT=$(git rev-parse --show-toplevel) + builtins='[a-z0-9]+|struct{}' -pkgs='k8s\.io/api/.*|k8s\.io/apimachinery/.*|github\.com/openshift/api/.*' +pkgs='k8s\.io/api/.*|k8s\.io/apimachinery/.*|github\.com/openshift/api/.*|github\.com/openshift/cert-manager-operator/api/.*|github\.com/cert-manager/cert-manager/pkg/apis/.*' # Check that types used in OpenShift API are designed to be used in API. # @@ -16,10 +18,10 @@ pkgs='k8s\.io/api/.*|k8s\.io/apimachinery/.*|github\.com/openshift/api/.*' # * types that are defined in this package (FooSpec, FooStatus, etc.) # * types from k8s.io API packages # -go run ./hack/typelinter \ +go run -C tools ./typelinter \ -whitelist="^(?:\[]|\*|map\[string])*(?:$builtins|(?:$pkgs)\.[A-Za-z0-9]+)\$" \ -excluded=github.com/openshift/api/build/v1.BuildStatus:Duration \ -excluded=github.com/openshift/api/image/dockerpre012.Config:ExposedPorts \ -excluded=github.com/openshift/api/image/dockerpre012.ImagePre012:Created \ -excluded=github.com/openshift/api/imageregistry/v1.ImagePrunerSpec:KeepYoungerThan \ - ./... + "${SCRIPT_ROOT}"/api/... diff --git a/pkg/dependencymagnet/dependencymagnet.go b/pkg/dependencymagnet/dependencymagnet.go deleted file mode 100644 index e8cd54746..000000000 --- a/pkg/dependencymagnet/dependencymagnet.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build dependencymagnet -// +build dependencymagnet - -// Package dependencymagnet is used to ensure packages required by build scripts -// but not directly imported by Go code are included in go.mod and vendored. -package dependencymagnet - -import ( - // go-bindata is needed by bindata.mk for generating bindata - _ "github.com/go-bindata/go-bindata/go-bindata" - - // build-machinery-go is needed for Makefile includes (bindata.mk) - _ "github.com/openshift/build-machinery-go" - - // code-generator is needed by hack/update-clientgen.sh (kube_codegen.sh) - _ "k8s.io/code-generator" -) diff --git a/test/e2e/go.mod b/test/go.mod similarity index 87% rename from test/e2e/go.mod rename to test/go.mod index 2dcddb3a9..c8cbedde6 100644 --- a/test/e2e/go.mod +++ b/test/go.mod @@ -1,4 +1,4 @@ -module github.com/openshift/cert-manager-operator/test/e2e +module github.com/openshift/cert-manager-operator/test go 1.25.0 @@ -9,19 +9,20 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 github.com/cert-manager/cert-manager v1.19.2 github.com/google/go-cmp v0.7.0 - github.com/onsi/ginkgo/v2 v2.25.1 - github.com/onsi/gomega v1.38.1 + github.com/onsi/ginkgo/v2 v2.27.5 + github.com/onsi/gomega v1.39.0 github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b github.com/openshift/cert-manager-operator v0.0.0-00010101000000-000000000000 github.com/openshift/client-go v0.0.0-20251205093018-96a6cbc1420c + github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 google.golang.org/api v0.251.0 k8s.io/api v0.34.1 k8s.io/apiextensions-apiserver v0.34.1 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 - k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d - sigs.k8s.io/controller-runtime v0.22.3 + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 + sigs.k8s.io/controller-runtime v0.22.4 sigs.k8s.io/yaml v1.6.0 ) @@ -81,27 +82,26 @@ require ( github.com/prometheus/common v0.66.1 // indirect github.com/prometheus/procfs v0.17.0 // indirect github.com/spf13/pflag v1.0.10 // indirect - github.com/stretchr/testify v1.11.1 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/net v0.47.0 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.31.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.13.0 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/tools v0.41.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect google.golang.org/grpc v1.75.1 // indirect @@ -111,7 +111,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiserver v0.34.1 // indirect k8s.io/component-base v0.34.1 // indirect - k8s.io/component-helpers v0.32.1 // indirect + k8s.io/component-helpers v0.34.1 // indirect k8s.io/controller-manager v0.32.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect @@ -123,6 +123,6 @@ require ( sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) -replace github.com/openshift/cert-manager-operator => ../.. +replace github.com/openshift/cert-manager-operator => ../ replace github.com/cert-manager/cert-manager => github.com/openshift/jetstack-cert-manager v1.19.2 diff --git a/test/e2e/go.sum b/test/go.sum similarity index 87% rename from test/e2e/go.sum rename to test/go.sum index 78f556ece..205878e59 100644 --- a/test/e2e/go.sum +++ b/test/go.sum @@ -60,6 +60,12 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= +github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= +github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= +github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= +github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -77,6 +83,8 @@ github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNj github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= 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/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/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -104,6 +112,8 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= +github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -118,6 +128,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 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/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= +github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= +github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -130,10 +144,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY= -github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= -github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk= -github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g= +github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE= +github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b h1:yfjc5FZliZbhtT+VxUK5qfCbO9yXMmdJTsOJ7ilA7RQ= @@ -147,8 +161,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= @@ -171,8 +183,11 @@ github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -191,57 +206,57 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +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= 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.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= 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.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= 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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -283,8 +298,8 @@ k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= -k8s.io/component-helpers v0.32.1 h1:TwdsSM1vW9GjnfX18lkrZbwE5G9psCIS2/rhenTDXd8= -k8s.io/component-helpers v0.32.1/go.mod h1:1JT1Ei3FD29yFQ18F3laj1WyvxYdHIhyxx6adKMFQXI= +k8s.io/component-helpers v0.34.1 h1:gWhH3CCdwAx5P3oJqZKb4Lg5FYZTWVbdWtOI8n9U4XY= +k8s.io/component-helpers v0.34.1/go.mod h1:4VgnUH7UA/shuBur+OWoQC0xfb69sy/93ss0ybZqm3c= k8s.io/controller-manager v0.32.1 h1:z3oQp1O5l0cSzM/MKf8V4olhJ9TmnELoJRPcV/v1s+Y= k8s.io/controller-manager v0.32.1/go.mod h1:dVA1UZPbqHH4hEhrrnLvQ4d5qVQCklNB8GEzYV59v/4= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= @@ -295,10 +310,10 @@ k8s.io/kubelet v0.32.1 h1:bB91GvMsZb+LfzBxnjPEr1Fal/sdxZtYphlfwAaRJGw= k8s.io/kubelet v0.32.1/go.mod h1:4sAEZ6PlewD0GroV3zscY7llym6kmNNTVmUI/Qshm6w= k8s.io/kubernetes v1.34.1 h1:F3p8dtpv+i8zQoebZeK5zBqM1g9x1aIdnA5vthvcuUk= k8s.io/kubernetes v1.34.1/go.mod h1:iu+FhII+Oc/1gGWLJcer6wpyih441aNFHl7Pvm8yPto= -k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= -k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y= -sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= +sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= sigs.k8s.io/gateway-api v1.4.0 h1:ZwlNM6zOHq0h3WUX2gfByPs2yAEsy/EenYJB78jpQfQ= sigs.k8s.io/gateway-api v1.4.0/go.mod h1:AR5RSqciWP98OPckEjOjh2XJhAe2Na4LHyXD2FUY7Qk= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= diff --git a/tools/go.mod b/tools/go.mod index 4247cb70d..482c49907 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -3,10 +3,14 @@ module github.com/openshift/cert-manager-operator/tools go 1.25.0 require ( - github.com/golangci/golangci-lint/v2 v2.1.6 + github.com/go-bindata/go-bindata v3.1.2+incompatible + github.com/golangci/golangci-lint/v2 v2.7.2 github.com/google/go-jsonnet v0.21.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 - github.com/openshift/api v0.0.0-20260114133223-6ab113cb7368 + github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b + github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af + golang.org/x/tools v0.41.0 + golang.org/x/vuln v1.1.4 k8s.io/code-generator v0.34.1 sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230912183013-811757733433 sigs.k8s.io/controller-tools v0.19.0 @@ -16,47 +20,55 @@ require ( require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect - github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.1.0 // indirect - github.com/Antonboom/nilnil v1.1.0 // indirect - github.com/Antonboom/testifylint v1.6.1 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect + dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect + dev.gaijin.team/go/golib v0.6.0 // indirect + github.com/4meepo/tagalign v1.4.3 // indirect + github.com/Abirdcfly/dupword v0.1.7 // indirect + github.com/AdminBenni/iota-mixing v1.0.0 // indirect + github.com/AlwxSin/noinlineerr v1.0.5 // indirect + github.com/Antonboom/errname v1.1.1 // indirect + github.com/Antonboom/nilnil v1.1.1 // indirect + github.com/Antonboom/testifylint v1.6.4 // indirect github.com/BurntSushi/toml v1.5.0 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Djarvur/go-err113 v0.1.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/MirrexOne/unqueryvet v1.3.0 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.17.2 // indirect + github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.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/beorn7/perks v1.0.1 // 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.3.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/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.9.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // 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.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charithe/durationcheck v0.0.10 // indirect + github.com/charithe/durationcheck v0.0.11 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/lipgloss v1.1.0 // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/chavacava/garif v0.1.0 // indirect github.com/ckaznocha/intrange v0.3.1 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.6 // indirect + github.com/daixiang0/gci v0.13.7 // indirect github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect @@ -65,17 +77,19 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.6 // indirect + github.com/frankban/quicktest v1.14.6 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.15 // indirect - github.com/go-critic/go-critic v0.13.0 // indirect + github.com/ghostiam/protogetter v0.3.17 // indirect + github.com/go-critic/go-critic v0.14.2 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/zapr v1.2.0 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.22.1 // indirect + github.com/go-openapi/jsonreference v0.21.2 // indirect + github.com/go-openapi/swag v0.23.1 // indirect + github.com/go-openapi/swag/jsonname v0.25.1 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -83,63 +97,67 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.12.1 // indirect + github.com/godoc-lint/godoc-lint v0.10.2 // indirect + github.com/gofrs/flock v0.13.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect - github.com/golangci/go-printf-func-name v0.1.0 // 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.0.0-20250217134842-442fd0091d95 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect + 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 github.com/google/go-cmp v0.7.0 // indirect - github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/gostaticanalysis/nilerr v0.1.2 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/hcl v1.0.1-vault-7 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jgautheron/goconst v1.8.1 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/julz/importas v0.2.0 // indirect - github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect + github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect github.com/kisielk/errcheck v1.9.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.14 // indirect + github.com/kulti/thelper v0.7.1 // indirect + github.com/kunwardeep/paralleltest v1.0.15 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.3 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect - github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.3 // indirect + github.com/ldez/exptostd v0.4.5 // indirect + github.com/ldez/gomoddirectives v0.7.1 // indirect + github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/tagliatelle v0.7.2 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/macabu/inamedparam v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/manuelarte/funcorder v0.2.1 // indirect - github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.1 // 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/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/mgechev/revive v1.9.0 // indirect + github.com/mgechev/revive v1.13.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -151,19 +169,19 @@ require ( 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.19.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/nunnatsa/ginkgolinter v0.21.2 // indirect + github.com/onsi/ginkgo/v2 v2.27.5 // indirect + github.com/onsi/gomega v1.39.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.8.0 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/quasilyte/go-ruleguard v0.4.4 // indirect - github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.17.0 // indirect + github.com/quasilyte/go-ruleguard v0.4.5 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.23 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect @@ -173,36 +191,36 @@ require ( github.com/ryancurrah/gomodguard v1.4.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.3 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7 // indirect github.com/sergi/go-diff v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.14.0 // indirect + github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.7 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/viper v1.12.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect + github.com/stbenjam/no-sprintf-host-port v0.3.1 // indirect + github.com/stoewer/go-strcase v1.3.1 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/stretchr/testify v1.10.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/subosito/gotenv v1.4.1 // indirect - github.com/tdakkota/asciicheck v0.4.1 // indirect - github.com/tetafro/godot v1.5.1 // indirect + github.com/tetafro/godot v1.5.4 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect github.com/timonwong/loggercheck v0.11.0 // indirect - github.com/tomarrell/wrapcheck/v2 v2.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.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect + github.com/uudashr/iface v1.4.1 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xen0n/gosmopolitan v1.3.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect @@ -211,41 +229,49 @@ require ( github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.1 // indirect - go-simpler.org/sloglint v0.11.0 // indirect - go.augendre.info/fatcontext v0.8.0 // indirect + go-simpler.org/musttag v0.14.0 // indirect + go-simpler.org/sloglint v0.11.1 // indirect + go.augendre.info/arangolint v0.3.1 // indirect + go.augendre.info/fatcontext v0.9.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect + go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.46.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/text v0.30.0 // indirect - golang.org/x/tools v0.37.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect - google.golang.org/protobuf v1.36.7 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect + golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 // indirect + golang.org/x/text v0.33.0 // indirect + golang.org/x/time v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250721164621-a45f3dfb1074 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect + google.golang.org/grpc v1.75.1 // indirect + google.golang.org/protobuf v1.36.9 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.6.1 // indirect k8s.io/api v0.34.1 // indirect - k8s.io/apiextensions-apiserver v0.34.0 // indirect + k8s.io/apiextensions-apiserver v0.34.1 // indirect k8s.io/apimachinery v0.34.1 // indirect - k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect + k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect - mvdan.cc/gofumpt v0.8.0 // indirect - mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + mvdan.cc/gofumpt v0.9.2 // indirect + mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/kustomize/api v0.20.1 // indirect sigs.k8s.io/kustomize/cmd/config v0.20.1 // indirect sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect @@ -254,4 +280,6 @@ require ( sigs.k8s.io/yaml v1.6.0 // indirect ) -replace github.com/tdakkota/asciicheck => github.com/golangci/asciicheck v0.1.1 +// Resolve ambiguous import: cloud.google.com/go/compute v1.6.1 contained metadata as a subpackage, +// but it was later split into a separate module. Exclude the old version to use the new metadata module. +exclude cloud.google.com/go/compute v1.6.1 diff --git a/tools/go.sum b/tools/go.sum index 10c35d107..c2cedeecf 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -4,51 +4,62 @@ 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= -github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= -github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= -github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= -github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= -github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= -github.com/Antonboom/testifylint v1.6.1 h1:6ZSytkFWatT8mwZlmRCHkWz1gPi+q6UBSbieji2Gj/o= -github.com/Antonboom/testifylint v1.6.1/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= +dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= +dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= +github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= +github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= +github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ= +github.com/Abirdcfly/dupword v0.1.7/go.mod h1:K0DkBeOebJ4VyOICFdppB23Q0YMOgVafM0zYW0n9lF4= +github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo= +github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY= +github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= +github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= +github.com/Antonboom/errname v1.1.1 h1:bllB7mlIbTVzO9jmSWVWLjxTEbGBVQ1Ff/ClQgtPw9Q= +github.com/Antonboom/errname v1.1.1/go.mod h1:gjhe24xoxXp0ScLtHzjiXp0Exi1RFLKJb0bVBtWKCWQ= +github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksufQ= +github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II= +github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= +github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +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/MirrexOne/unqueryvet v1.3.0 h1:5slWSomgqpYU4zFuZ3NNOfOUxVPlXFDBPAVasZOGlAY= +github.com/MirrexOne/unqueryvet v1.3.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= -github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= 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/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= +github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= -github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +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/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/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= @@ -59,6 +70,8 @@ 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.3.0 h1:nZWREJFL6U3vgW/B1lfDOigl+tEF6qgs6dGGbFeR0UM= +github.com/bombsimon/wsl/v5 v5.3.0/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= 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= @@ -67,16 +80,16 @@ github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= 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.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= -github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/catenacyber/perfsprint v0.10.1 h1:u7Riei30bk46XsG8nknMhKLXG9BcXz3+3tl/WpKm0PQ= +github.com/catenacyber/perfsprint v0.10.1/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= -github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +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.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= @@ -87,16 +100,14 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/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/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.6 h1:RKuEOSkGpSadkGbvZ6hJ4ddItT3cVZ9Vn9Rybk6xjl8= -github.com/daixiang0/gci v0.13.6/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= +github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= @@ -119,35 +130,36 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= -github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= -github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= -github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= +github.com/ghostiam/protogetter v0.3.17 h1:sjGPErP9o7i2Ym+z3LsQzBdLCNaqbYy2iJQPxGXg04Q= +github.com/ghostiam/protogetter v0.3.17/go.mod h1:AivIX1eKA/TcUmzZdzbl+Tb8tjIe8FcyG6JFyemQAH4= +github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE= +github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= +github.com/go-critic/go-critic v0.14.2 h1:PMvP5f+LdR8p6B29npvChUXbD1vrNlKDf60NJtgMBOo= +github.com/go-critic/go-critic v0.14.2/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= +github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= +github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU= +github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ= +github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= +github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU= +github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= 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= @@ -171,102 +183,108 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= 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/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= -github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/godoc-lint/godoc-lint v0.10.2 h1:dksNgK+zebnVlj4Fx83CRnCmPO0qRat/9xfFsir1nfg= +github.com/godoc-lint/godoc-lint v0.10.2/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golangci/asciicheck v0.1.1 h1:csUCIFYarM5AiFrE6KhXrK55ongOxkhauW5Bi2fjXQs= -github.com/golangci/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +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/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= -github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +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.1.6 h1:LXqShFfAGM5BDzEOWD2SL1IzJAgUOqES/HRBsfKjI+w= -github.com/golangci/golangci-lint/v2 v2.1.6/go.mod h1:EPj+fgv4TeeBq3TcqaKZb3vkiV5dP4hHHKhXhEhzci8= +github.com/golangci/golangci-lint/v2 v2.7.2 h1:AhBC+YeEueec4AGlIbvPym5C70Thx0JykIqXbdIXWx0= +github.com/golangci/golangci-lint/v2 v2.7.2/go.mod h1:pDijleoBu7e8sejMqyZ3L5n6geqe+cVvOAz2QImqqVc= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +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/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= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-jsonnet v0.21.0 h1:43Bk3K4zMRP/aAZm9Po2uSEjY6ALCkYUVIcz9HLGMvA= github.com/google/go-jsonnet v0.21.0/go.mod h1:tCGAu8cpUpEZcdGMmdOu37nh8bGgqubhI5v2iSk3KJQ= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= -github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs= +github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/nilerr v0.1.2 h1:S6nk8a9N8g062nsx63kUkF6AzbHGw7zzyHMcpu52xQU= +github.com/gostaticanalysis/nilerr v0.1.2/go.mod h1:A19UHhoY3y8ahoL7YKz6sdjDtduwTSI4CsymaC2htPA= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= 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.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/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/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 v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= 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= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.8.1 h1:PPqCYp3K/xlOj5JmIe6O1Mj6r1DbkdbLtR3AJuZo414= -github.com/jgautheron/goconst v1.8.1/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= +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/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= -github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= -github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= +github.com/karamaru-alpha/copyloopvar v1.2.2 h1:yfNQvP9YaGQR7VaWLYcfZUlRP2eo2vhExWKxD/fP6q0= +github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M= github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= @@ -274,29 +292,28 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= -github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= +github.com/kulti/thelper v0.7.1 h1:fI8QITAoFVLx+y+vSyuLBP+rcVIB8jKooNSCT2EiI98= +github.com/kulti/thelper v0.7.1/go.mod h1:NsMjfQEy6sd+9Kfw8kCP61W1I0nerGSYSFnGaxQkcbs= +github.com/kunwardeep/paralleltest v1.0.15 h1:ZMk4Qt306tHIgKISHWFJAO1IDQJLc6uDyJMLyncOb6w= +github.com/kunwardeep/paralleltest v1.0.15/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.3 h1:Ag1aGiq2epGePuRJhez2mzOpZ8sI9Gimcb4Sb3+pk9Y= -github.com/ldez/exptostd v0.4.3/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= -github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= -github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k= -github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ= +github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM= +github.com/ldez/gomoddirectives v0.7.1 h1:FaULkvUIG36hj6chpwa+FdCNGZBsD7/fO+p7CCsM6pE= +github.com/ldez/gomoddirectives v0.7.1/go.mod h1:auDNtakWJR1rC+YX7ar+HmveqXATBAyEK1KYpsIRW/8= +github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= +github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= +github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +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= @@ -305,14 +322,16 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/manuelarte/funcorder v0.2.1 h1:7QJsw3qhljoZ5rH0xapIvjw31EcQeFbF31/7kQ/xS34= -github.com/manuelarte/funcorder v0.2.1/go.mod h1:BQQ0yW57+PF9ZpjpeJDKOffEsQbxDFKW8F8zSMe/Zd0= -github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= -github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= -github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +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/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= +github.com/maratori/testpackage v1.1.2/go.mod h1:8F24GdVDFW5Ew43Et02jamrVMNXLUNaOynhDssITGfc= github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= @@ -321,13 +340,12 @@ 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.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 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/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM= github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I= -github.com/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= -github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= +github.com/mgechev/revive v1.13.0 h1:yFbEVliCVKRXY8UgwEO7EOYNopvjb1BFbmYqm9hZjBM= +github.com/mgechev/revive v1.13.0/go.mod h1:efJfeBVCX2JUumNQ7dtOLDja+QKj9mYGgEZA7rt5u+0= 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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -352,20 +370,20 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= -github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= +github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= +github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 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.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk= -github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g= -github.com/openshift/api v0.0.0-20260114133223-6ab113cb7368 h1:kSr3DOlq0NCrHd65HB2o/pBsks7AfRm+fkpf9RLUPoc= -github.com/openshift/api v0.0.0-20260114133223-6ab113cb7368/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= +github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE= +github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b h1:yfjc5FZliZbhtT+VxUK5qfCbO9yXMmdJTsOJ7ilA7RQ= +github.com/openshift/api v0.0.0-20260105191300-d1c4dc4fd37b/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= +github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af h1:UiYYMi/CCV+kwWrXuXfuUSOY2yNXOpWpNVgHc6aLQlE= +github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -377,27 +395,26 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/quasilyte/go-ruleguard v0.4.4 h1:53DncefIeLX3qEpjzlS1lyUmQoUEeOWPFWqaTJq9eAQ= -github.com/quasilyte/go-ruleguard v0.4.4/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= +github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= +github.com/quasilyte/go-ruleguard v0.4.5 h1:AGY0tiOT5hJX9BTdx/xBdoCubQUAE2grkqY2lSwvZcA= +github.com/quasilyte/go-ruleguard v0.4.5/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= +github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY= +github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -409,6 +426,7 @@ github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtz 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.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -418,16 +436,16 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= -github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= -github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= +github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7 h1:rZg6IGn0ySYZwCX8LHwZoYm03JhG/cVAJJ3O+u3Vclo= +github.com/securego/gosec/v2 v2.22.11-0.20251204091113-daccba6b93d7/go.mod h1:9sr22NZO5Kfh7unW/xZxkGYTmj2484/fCiE54gw7UTY= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -436,30 +454,30 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= +github.com/sonatard/noctx v0.4.0/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= 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/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= +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.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= -github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= -github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= -github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= -github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= +github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= +github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ= +github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs= +github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -468,28 +486,26 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= 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.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= -github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= +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/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.11.0 h1:BJSt36snX9+4WTIXeJ7nvHBQBcm1h2SjQMSlmQ6aFSU= -github.com/tomarrell/wrapcheck/v2 v2.11.0/go.mod h1:wFL9pDWDAbXhhPZZt+nG8Fu+h29TtnZ2MW6Lx4BRXIU= +github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVFL27Of9is= +github.com/tomarrell/wrapcheck/v2 v2.12.0/go.mod h1:AQhQuZd0p7b6rfW+vUwHm5OMCGgp63moQ9Qr/0BpIWo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= @@ -498,8 +514,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.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +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/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= @@ -525,44 +541,42 @@ 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.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= -go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= -go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= -go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= -go.augendre.info/fatcontext v0.8.0 h1:2dfk6CQbDGeu1YocF59Za5Pia7ULeAM6friJ3LP7lmk= -go.augendre.info/fatcontext v0.8.0/go.mod h1:oVJfMgwngMsHO+KB2MdgzcO+RvtNdiCEOlWvSFtax/s= +go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= +go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= +go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= +go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go.augendre.info/arangolint v0.3.1 h1:n2E6p8f+zfXSFLa2e2WqFPp4bfvcuRdd50y6cT65pSo= +go.augendre.info/arangolint v0.3.1/go.mod h1:6ZKzEzIZuBQwoSvlKT+qpUfIbBfFCE5gbAoTg0/117g= +go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= +go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +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= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -571,29 +585,25 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4= +golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 h1:HDjDiATsGqvuqvkDvgJjD1IgPrVekcSXVVE21JwvzGE= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= 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.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.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.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= 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= @@ -603,16 +613,14 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 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.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -622,8 +630,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ 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.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -639,86 +647,75 @@ golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/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.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 h1:O1cMQHRfwNpDfDJerqRoE2oD+AFlyid87D40L/OkkJo= +golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 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.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.5/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.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= 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.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= -golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= -golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= +golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/genproto/googleapis/api v0.0.0-20250721164621-a45f3dfb1074 h1:mVXdvnmR3S3BQOqHECm9NGMjYiRtEvDYcqAqedTXY6s= +google.golang.org/genproto/googleapis/api v0.0.0-20250721164621-a45f3dfb1074/go.mod h1:vYFwMYFbmA8vl6Z/krj/h7+U/AqpHknwJX4Uqgfyc7I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.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/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= @@ -726,49 +723,47 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= -k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc= -k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0= +k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= +k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/apiserver v0.34.0 h1:Z51fw1iGMqN7uJ1kEaynf2Aec1Y774PqU+FVWCFV3Jg= -k8s.io/apiserver v0.34.0/go.mod h1:52ti5YhxAvewmmpVRqlASvaqxt0gKJxvCeW7ZrwgazQ= -k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo= -k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY= +k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA= +k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0= +k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= +k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc= k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= -k8s.io/component-base v0.34.0 h1:bS8Ua3zlJzapklsB1dZgjEJuJEeHjj8yTu1gxE2zQX8= -k8s.io/component-base v0.34.0/go.mod h1:RSCqUdvIjjrEm81epPcjQ/DS+49fADvGSCkIP3IC6vg= -k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q= -k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= +k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= +k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0= +k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= -mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= -mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= -mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= +mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 h1:qPrZsv1cwQiFeieFlRqT627fVZ+tyfou/+S5S0H5ua0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230912183013-811757733433 h1:FXcZd0UUR/JUn1Lo3LuKWQuGK2xg4M9FKvJ7AAOA3JU= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230912183013-811757733433/go.mod h1:B6HLcvOy2S1qq2eWOFm9xepiKPMIc8Z9OXSPsnUDaR4= sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI5uk= sigs.k8s.io/controller-tools v0.19.0/go.mod h1:y5HY/iNDFkmFla2CfQoVb2AQXMsBk4ad84iR1PLANB0= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= sigs.k8s.io/kustomize/cmd/config v0.20.1 h1:4APUORmZe2BYrsqgGfEKdd/r7gM6i43egLrUzilpiFo= diff --git a/tools/tools.go b/tools/tools.go index 890976034..323470da5 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -20,13 +20,40 @@ limitations under the License. package tools import ( + // golangci-lint is used for linting the go code _ "github.com/golangci/golangci-lint/v2/cmd/golangci-lint" + + // go-bindata embeds static assets into Go binaries (used by bindata.mk) + // Note: Using +incompatible version (not v3 module) for compatibility with bindata.mk + _ "github.com/go-bindata/go-bindata/go-bindata" + + // jsonnet is used for templating cert-manager manifests (update-cert-manager-manifests.sh) _ "github.com/google/go-jsonnet/cmd/jsonnet" + + // counterfeiter generates test fakes/mocks for interfaces _ "github.com/maxbrunsfeld/counterfeiter/v6" + + // openshift/api/openapi is used for OpenAPI spec generation _ "github.com/openshift/api/openapi" + + // build-machinery-go provides Makefile includes (bindata.mk, targets) + _ "github.com/openshift/build-machinery-go" + + // go-to-protobuf generates protobuf definitions from Go types _ "k8s.io/code-generator/cmd/go-to-protobuf" + + // protoc-gen-gogo is a protobuf compiler plugin for gogo/protobuf _ "k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo" + + // setup-envtest downloads and configures envtest binaries for controller tests _ "sigs.k8s.io/controller-runtime/tools/setup-envtest" + + // controller-gen generates CRDs, RBAC, and webhook manifests from Go types _ "sigs.k8s.io/controller-tools/cmd/controller-gen" + + // kustomize is used for building and customizing Kubernetes manifests _ "sigs.k8s.io/kustomize/kustomize/v5" + + // govulncheck is used for scanning the vulnerabilities in the used go packages + _ "golang.org/x/vuln/cmd/govulncheck" ) diff --git a/hack/typelinter/typelinter.go b/tools/typelinter/typelinter.go similarity index 100% rename from hack/typelinter/typelinter.go rename to tools/typelinter/typelinter.go diff --git a/vendor/github.com/chavacava/garif/.gitignore b/vendor/codeberg.org/chavacava/garif/.gitignore similarity index 100% rename from vendor/github.com/chavacava/garif/.gitignore rename to vendor/codeberg.org/chavacava/garif/.gitignore diff --git a/vendor/github.com/chavacava/garif/LICENSE b/vendor/codeberg.org/chavacava/garif/LICENSE similarity index 100% rename from vendor/github.com/chavacava/garif/LICENSE rename to vendor/codeberg.org/chavacava/garif/LICENSE diff --git a/vendor/github.com/chavacava/garif/README.md b/vendor/codeberg.org/chavacava/garif/README.md similarity index 97% rename from vendor/github.com/chavacava/garif/README.md rename to vendor/codeberg.org/chavacava/garif/README.md index 6a19c6147..c1cc80d3b 100644 --- a/vendor/github.com/chavacava/garif/README.md +++ b/vendor/codeberg.org/chavacava/garif/README.md @@ -1,6 +1,6 @@ # garif -A GO package to create and manipulate SARIF logs. +A Go package to create and manipulate SARIF logs. SARIF, from _Static Analysis Results Interchange Format_, is a standard JSON-based format for the output of static analysis tools defined and promoted by [OASIS](https://www.oasis-open.org/). diff --git a/vendor/github.com/chavacava/garif/constructors.go b/vendor/codeberg.org/chavacava/garif/constructors.go similarity index 100% rename from vendor/github.com/chavacava/garif/constructors.go rename to vendor/codeberg.org/chavacava/garif/constructors.go diff --git a/vendor/github.com/chavacava/garif/decorators.go b/vendor/codeberg.org/chavacava/garif/decorators.go similarity index 100% rename from vendor/github.com/chavacava/garif/decorators.go rename to vendor/codeberg.org/chavacava/garif/decorators.go diff --git a/vendor/github.com/chavacava/garif/doc.go b/vendor/codeberg.org/chavacava/garif/doc.go similarity index 90% rename from vendor/github.com/chavacava/garif/doc.go rename to vendor/codeberg.org/chavacava/garif/doc.go index 50fa6dfe5..5ac5a156a 100644 --- a/vendor/github.com/chavacava/garif/doc.go +++ b/vendor/codeberg.org/chavacava/garif/doc.go @@ -1,4 +1,4 @@ -// Package garif defines all the GO structures required to model a SARIF log file. +// Package garif defines all the Go structures required to model a SARIF log file. // These structures were created using the JSON-schema sarif-schema-2.1.0.json of SARIF logfiles // available at https://github.com/oasis-tcs/sarif-spec/tree/master/Schemata. // diff --git a/vendor/github.com/chavacava/garif/enums.go b/vendor/codeberg.org/chavacava/garif/enums.go similarity index 100% rename from vendor/github.com/chavacava/garif/enums.go rename to vendor/codeberg.org/chavacava/garif/enums.go diff --git a/vendor/github.com/chavacava/garif/io.go b/vendor/codeberg.org/chavacava/garif/io.go similarity index 100% rename from vendor/github.com/chavacava/garif/io.go rename to vendor/codeberg.org/chavacava/garif/io.go diff --git a/vendor/github.com/chavacava/garif/models.go b/vendor/codeberg.org/chavacava/garif/models.go similarity index 98% rename from vendor/github.com/chavacava/garif/models.go rename to vendor/codeberg.org/chavacava/garif/models.go index f16a86136..ed18b04a5 100644 --- a/vendor/github.com/chavacava/garif/models.go +++ b/vendor/codeberg.org/chavacava/garif/models.go @@ -273,7 +273,7 @@ type ExternalProperties struct { // An array of graph objects that will be merged with a separate run. Graphs []*Graph `json:"graphs,omitempty"` - // A stable, unique identifer for this external properties object, in the form of a GUID. + // A stable, unique identifier for this external properties object, in the form of a GUID. Guid string `json:"guid,omitempty"` // Describes the invocation of the analysis tool that will be merged with a separate run. @@ -291,7 +291,7 @@ type ExternalProperties struct { // An array of result objects that will be merged with a separate run. Results []*Result `json:"results,omitempty"` - // A stable, unique identifer for the run associated with this external properties object, in the form of a GUID. + // A stable, unique identifier for the run associated with this external properties object, in the form of a GUID. RunGuid string `json:"runGuid,omitempty"` // The URI of the JSON schema corresponding to the version of the external property file format. @@ -319,7 +319,7 @@ type ExternalProperties struct { // ExternalPropertyFileReference Contains information that enables a SARIF consumer to locate the external property file that contains the value of an externalized property associated with the run. type ExternalPropertyFileReference struct { - // A stable, unique identifer for the external property file in the form of a GUID. + // A stable, unique identifier for the external property file in the form of a GUID. Guid string `json:"guid,omitempty"` // A non-negative integer specifying the number of items contained in the external property file. @@ -835,7 +835,7 @@ type ReportingDescriptor struct { // A description of the report. Should, as far as possible, provide details sufficient to enable resolution of any problem indicated by the result. FullDescription *MultiformatMessageString `json:"fullDescription,omitempty"` - // A unique identifer for the reporting descriptor in the form of a GUID. + // A unique identifier for the reporting descriptor in the form of a GUID. Guid string `json:"guid,omitempty"` // Provides the primary documentation for the report, useful when there is no online documentation. @@ -928,7 +928,7 @@ type Result struct { // An array of zero or more unique graph objects associated with the result. Graphs []*Graph `json:"graphs,omitempty"` - // A stable, unique identifer for the result in the form of a GUID. + // A stable, unique identifier for the result in the form of a GUID. Guid string `json:"guid,omitempty"` // An absolute URI at which the result can be viewed. @@ -1114,7 +1114,7 @@ type RunAutomationDetails struct { // A description of the identity and role played within the engineering system by this object's containing run object. Description *Message `json:"description,omitempty"` - // A stable, unique identifer for this object's containing run object in the form of a GUID. + // A stable, unique identifier for this object's containing run object in the form of a GUID. Guid string `json:"guid,omitempty"` // A hierarchical string that uniquely identifies this object's containing run object. @@ -1169,7 +1169,7 @@ type StackFrame struct { // Suppression A suppression that is relevant to a result. type Suppression struct { - // A stable, unique identifer for the supression in the form of a GUID. + // A stable, unique identifier for the suppression in the form of a GUID. Guid string `json:"guid,omitempty"` // A string representing the justification for the suppression. @@ -1293,7 +1293,7 @@ type ToolComponent struct { // A dictionary, each of whose keys is a resource identifier and each of whose values is a multiformatMessageString object, which holds message strings in plain text and (optionally) Markdown format. The strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments. GlobalMessageStrings map[string]*MultiformatMessageString `json:"globalMessageStrings,omitempty"` - // A unique identifer for the tool component in the form of a GUID. + // A unique identifier for the tool component in the form of a GUID. Guid string `json:"guid,omitempty"` // The absolute URI at which information about this version of the tool component can be found. diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/LICENSE b/vendor/dev.gaijin.team/go/exhaustruct/v4/LICENSE similarity index 100% rename from vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/LICENSE rename to vendor/dev.gaijin.team/go/exhaustruct/v4/LICENSE diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/analyzer/analyzer.go similarity index 52% rename from vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go rename to vendor/dev.gaijin.team/go/exhaustruct/v4/analyzer/analyzer.go index 5be31eb68..a235de385 100644 --- a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go +++ b/vendor/dev.gaijin.team/go/exhaustruct/v4/analyzer/analyzer.go @@ -12,14 +12,12 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" - "github.com/GaijinEntertainment/go-exhaustruct/v3/internal/comment" - "github.com/GaijinEntertainment/go-exhaustruct/v3/internal/pattern" - "github.com/GaijinEntertainment/go-exhaustruct/v3/internal/structure" + "dev.gaijin.team/go/exhaustruct/v4/internal/comment" + "dev.gaijin.team/go/exhaustruct/v4/internal/structure" ) type analyzer struct { - include pattern.List `exhaustruct:"optional"` - exclude pattern.List `exhaustruct:"optional"` + config Config structFields structure.FieldsCache `exhaustruct:"optional"` comments comment.Cache `exhaustruct:"optional"` @@ -28,22 +26,16 @@ type analyzer struct { typeProcessingNeedMu sync.RWMutex `exhaustruct:"optional"` } -func NewAnalyzer(include, exclude []string) (*analysis.Analyzer, error) { - a := analyzer{ - typeProcessingNeed: make(map[string]bool), - comments: comment.Cache{}, - } - - var err error - - a.include, err = pattern.NewList(include...) +func NewAnalyzer(config Config) (*analysis.Analyzer, error) { + err := config.Prepare() if err != nil { - return nil, err //nolint:wrapcheck + return nil, err } - a.exclude, err = pattern.NewList(exclude...) - if err != nil { - return nil, err //nolint:wrapcheck + a := analyzer{ + config: config, + typeProcessingNeed: make(map[string]bool), + comments: comment.Cache{}, } return &analysis.Analyzer{ //nolint:exhaustruct @@ -51,27 +43,10 @@ func NewAnalyzer(include, exclude []string) (*analysis.Analyzer, error) { Doc: "Checks if all structure fields are initialized", Run: a.run, Requires: []*analysis.Analyzer{inspect.Analyzer}, - Flags: a.newFlagSet(), + Flags: *a.config.BindToFlagSet(flag.NewFlagSet("", flag.PanicOnError)), }, nil } -func (a *analyzer) newFlagSet() flag.FlagSet { - fs := flag.NewFlagSet("", flag.PanicOnError) - - fs.Var(&a.include, "i", `Regular expression to match type names, can receive multiple flags. -Anonymous structs can be matched by '' alias. -4ex: - github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer\. - github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer\.TypeInfo`) - fs.Var(&a.exclude, "e", `Regular expression to exclude type names, can receive multiple flags. -Anonymous structs can be matched by '' alias. -4ex: - github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer\. - github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer\.TypeInfo`) - - return *fs -} - func (a *analyzer) run(pass *analysis.Pass) (any, error) { insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) //nolint:forcetypeassert @@ -98,14 +73,8 @@ func (a *analyzer) newVisitor(pass *analysis.Pass) func(n ast.Node, push bool, s return true } - if len(lit.Elts) == 0 { - if ret, ok := stackParentIsReturn(stack); ok { - if returnContainsNonNilError(pass, ret, n) { - // it is okay to return uninitialized structure in case struct's direct parent is - // a return statement containing non-nil error - return true - } - } + if len(lit.Elts) == 0 && a.checkEmptyStructAllowed(pass, stack, typeInfo) { + return true } file := a.comments.Get(pass.Fset, stack[0].(*ast.File)) //nolint:forcetypeassert @@ -113,11 +82,155 @@ func (a *analyzer) newVisitor(pass *analysis.Pass) func(n ast.Node, push bool, s pos, msg := a.processStruct(pass, lit, structTyp, typeInfo, rc) if pos != nil { - pass.Reportf(*pos, msg) + pass.Reportf(*pos, "%s", msg) + } + + return true + } +} + +func (a *analyzer) checkEmptyStructAllowed(pass *analysis.Pass, stack []ast.Node, typeInfo *TypeInfo) bool { + // empty structs are globally allowed + if a.config.AllowEmpty { + return true + } + + // some structs are allowed to be empty, basing on pattern + if a.config.allowEmptyPatterns.MatchFullString(typeInfo.String()) { + return true + } + + if ret, ok := getParentReturnStmt(stack); ok { + // empty structures are allowed in all return statements + if a.config.AllowEmptyReturns { + return true + } + + // empty structures are allowed in error returns + if isErrorReturnStatement(pass, ret, stack[len(stack)-1]) { + return true } + } + // empty structures are allowed in variable declarations + if isChildOfVariableDeclaration(stack) && a.config.AllowEmptyDeclarations { return true } + + return false +} + +// isPartOfVariableDeclaration checks if the node is direct part of variable +// declaration, meaning that it is a first-level RHS child of `:=` or `var` +// declaration. +func isChildOfVariableDeclaration(stack []ast.Node) bool { + if len(stack) < 2 { //nolint:mnd // stack for sure contains at leas current node and its parent (file) + return false + } + + // Start from composite literal and go up the stack + for i := len(stack) - 1; i > 0; i-- { + parent := stack[i-1] + + switch p := parent.(type) { + case *ast.AssignStmt: + if p.Tok == token.DEFINE { + return true + } + + case *ast.ValueSpec: + return true + + case *ast.UnaryExpr: + // Only allow pointer taking (&) + if p.Op == token.AND { + continue + } + + return false + + default: + return false + } + } + + return false +} + +// getParentReturnStmt checks if the direct parent of the current node is a +// return statement and returns it if so. +func getParentReturnStmt(stack []ast.Node) (*ast.ReturnStmt, bool) { + if len(stack) < 2 { //nolint:mnd // stack for sure contains at leas current node and its parent (file) + return nil, false + } + + // Start from composite literal and go up the stack + for i := len(stack) - 1; i > 0; i-- { + parent := stack[i-1] + + switch p := parent.(type) { + case *ast.ReturnStmt: + return p, true + + case *ast.UnaryExpr: + // Only allow pointer taking (&) + if p.Op == token.AND { + continue + } + + return nil, false + + default: + return nil, false + } + } + + return nil, false +} + +// errorIface is an interface type of the [error] interface. +// +//nolint:forcetypeassert,gochecknoglobals +var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) + +// isErrorReturnStatement checks if the return statement is an error return +// statement, meaning that it contains a non-nil value that implements [error]. +func isErrorReturnStatement(pass *analysis.Pass, n *ast.ReturnStmt, currentNode ast.Node) bool { + if len(n.Results) == 0 { + return false + } + + // iterate backwards, since idiomatic position of error is at the end + for i := len(n.Results) - 1; i >= 0; i-- { + ri := n.Results[i] + + // Skip the current node, since it is already being checked + if ri == currentNode { + continue + } + + switch ri := ri.(type) { + case *ast.Ident: + // Skip nil values + if ri.Name == "nil" { + continue + } + + case *ast.UnaryExpr: + // Current node might be under the unary expression + if ri.X == currentNode { + continue + } + } + + // Check if the type implements error interface + resultType := pass.TypesInfo.TypeOf(ri) + if resultType != nil && types.Implements(resultType, errorIface) { + return true + } + } + + return false } // getCompositeLitRelatedComments returns all comments that are related to checked node. We @@ -129,16 +242,23 @@ func getCompositeLitRelatedComments(stack []ast.Node, cm ast.CommentMap) []*ast. for i := len(stack) - 1; i >= 0; i-- { node := stack[i] - switch node.(type) { - case *ast.CompositeLit, // stack[len(stack)-1] - *ast.ReturnStmt, // return ... - *ast.IndexExpr, // map[enum]...{...}[key] - *ast.CallExpr, // myfunc(map...) - *ast.UnaryExpr, // &map... - *ast.AssignStmt, // variable assignment (without var keyword) - *ast.DeclStmt, // var declaration, parent of *ast.GenDecl - *ast.GenDecl, // var declaration, parent of *ast.ValueSpec - *ast.ValueSpec: // var declaration + switch tn := node.(type) { + case *ast.CompositeLit: + // comments on the lines prior to literal + comments = append(comments, cm[node]...) + // comments on the same line as literal type definition + // worth noting that event "typeless" literals have a type + comments = append(comments, cm[tn.Type]...) + + case *ast.ReturnStmt, // return ... + *ast.IndexExpr, // map[enum]...{...}[key] + *ast.CallExpr, // myfunc(map...) + *ast.UnaryExpr, // &map... + *ast.AssignStmt, // variable assignment (without var keyword) + *ast.DeclStmt, // var declaration, parent of *ast.GenDecl + *ast.GenDecl, // var declaration, parent of *ast.ValueSpec + *ast.ValueSpec, // var declaration + *ast.KeyValueExpr: // field declaration comments = append(comments, cm[node]...) default: @@ -179,56 +299,6 @@ func getStructType(pass *analysis.Pass, lit *ast.CompositeLit) (*types.Struct, * } } -func stackParentIsReturn(stack []ast.Node) (*ast.ReturnStmt, bool) { - // it is safe to skip boundary check, since stack always has at least one element - // we also have no reason to check the first element, since it is always a file - for i := len(stack) - 2; i > 0; i-- { - switch st := stack[i].(type) { - case *ast.ReturnStmt: - return st, true - - case *ast.UnaryExpr: - // in case we're dealing with pointers - it is still viable to check pointer's - // parent for return statement - continue - - default: - return nil, false - } - } - - return nil, false -} - -// errorIface is a type that represents [error] interface and all types will be -// compared against. -var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) - -func returnContainsNonNilError(pass *analysis.Pass, ret *ast.ReturnStmt, except ast.Node) bool { - // errors are mostly located at the end of return statement, so we're starting - // from the end. - for i := len(ret.Results) - 1; i >= 0; i-- { - ri := ret.Results[i] - - // skip current node - if ri == except { - continue - } - - if un, ok := ri.(*ast.UnaryExpr); ok { - if un.X == except { - continue - } - } - - if types.Implements(pass.TypesInfo.TypeOf(ri), errorIface) { - return true - } - } - - return false -} - func (a *analyzer) processStruct( pass *analysis.Pass, lit *ast.CompositeLit, @@ -266,7 +336,7 @@ func (a *analyzer) processStruct( // shouldProcessType returns true if type should be processed basing off include // and exclude patterns, defined though constructor and\or flags. func (a *analyzer) shouldProcessType(info *TypeInfo) bool { - if len(a.include) == 0 && len(a.exclude) == 0 { + if len(a.config.includePatterns) == 0 && len(a.config.excludePatterns) == 0 { return true } @@ -278,13 +348,14 @@ func (a *analyzer) shouldProcessType(info *TypeInfo) bool { if !ok { a.typeProcessingNeedMu.Lock() + res = true - if a.include != nil && !a.include.MatchFullString(name) { + if a.config.includePatterns != nil && !a.config.includePatterns.MatchFullString(name) { res = false } - if res && a.exclude != nil && a.exclude.MatchFullString(name) { + if res && a.config.excludePatterns != nil && a.config.excludePatterns.MatchFullString(name) { res = false } diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v4/analyzer/config.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/analyzer/config.go new file mode 100644 index 000000000..0c39cbed8 --- /dev/null +++ b/vendor/dev.gaijin.team/go/exhaustruct/v4/analyzer/config.go @@ -0,0 +1,127 @@ +package analyzer + +import ( + "flag" + "strings" + + "dev.gaijin.team/go/golib/e" + + "dev.gaijin.team/go/exhaustruct/v4/internal/pattern" +) + +type Config struct { + // IncludeRx is a list of regular expressions to match type names that should be + // processed. Anonymous structs can be matched by '' alias. + // + // Each regular expression must match the full type name, including package path. + // For example, to match type `net/http.Cookie` regular expression should be + // `.*/http\.Cookie`, but not `http\.Cookie`. + IncludeRx []string `exhaustruct:"optional"` + includePatterns pattern.List `exhaustruct:"optional"` + + // ExcludeRx is a list of regular expressions to match type names that should be + // excluded from processing. Anonymous structs can be matched by '' + // alias. + // + // Has precedence over IncludeRx. + // + // Each regular expression must match the full type name, including package path. + // For example, to match type `net/http.Cookie` regular expression should be + // `.*/http\.Cookie`, but not `http\.Cookie`. + ExcludeRx []string `exhaustruct:"optional"` + excludePatterns pattern.List `exhaustruct:"optional"` + + // AllowEmpty allows empty structures, effectively excluding them from the check. + AllowEmpty bool `exhaustruct:"optional"` + + // AllowEmptyRx is a list of regular expressions to match type names that should + // be allowed to be empty. Anonymous structs can be matched by '' + // alias. + // + // Each regular expression must match the full type name, including package path. + // For example, to match type `net/http.Cookie` regular expression should be + // `.*/http\.Cookie`, but not `http\.Cookie`. + AllowEmptyRx []string `exhaustruct:"optional"` + allowEmptyPatterns pattern.List `exhaustruct:"optional"` + + // AllowEmptyReturns allows empty structures in return statements. + AllowEmptyReturns bool `exhaustruct:"optional"` + + // AllowEmptyDeclarations allows empty structures in variable declarations. + AllowEmptyDeclarations bool `exhaustruct:"optional"` +} + +// Prepare compiles all regular expression patterns into pattern lists for +// efficient matching. +func (c *Config) Prepare() error { + var err error + + c.includePatterns, err = pattern.NewList(c.IncludeRx...) + if err != nil { + return e.NewFrom("compile include patterns", err) + } + + c.excludePatterns, err = pattern.NewList(c.ExcludeRx...) + if err != nil { + return e.NewFrom("compile exclude patterns", err) + } + + c.allowEmptyPatterns, err = pattern.NewList(c.AllowEmptyRx...) + if err != nil { + return e.NewFrom("compile allow empty patterns", err) + } + + return nil +} + +// stringSliceFlag implements flag.Value interface for []string fields. +type stringSliceFlag struct { + slice *[]string +} + +func (s stringSliceFlag) String() string { + if s.slice == nil { + return "" + } + + return strings.Join(*s.slice, ",") +} + +func (s stringSliceFlag) Set(value string) error { + *s.slice = append(*s.slice, value) + return nil +} + +// BindToFlagSet binds the config fields to the provided flag set. +func (c *Config) BindToFlagSet(fs *flag.FlagSet) *flag.FlagSet { + fs.Var(stringSliceFlag{&c.IncludeRx}, "include-rx", + "Regular expression to match type names that should be processed. "+ + "Anonymous structs can be matched by '' alias. "+ + "Each regex must match the full type name including package path. "+ + "Example: `.*/http\\.Cookie`. Can be used multiple times.") + fs.Var(stringSliceFlag{&c.IncludeRx}, "i", "Short form of -include-rx") + + fs.Var(stringSliceFlag{&c.ExcludeRx}, "exclude-rx", + "Regular expression to exclude type names from processing, has precedence over -include. "+ + "Anonymous structs can be matched by '' alias. "+ + "Each regex must match the full type name including package path. "+ + "Example: `.*/http\\.Cookie`. Can be used multiple times.") + fs.Var(stringSliceFlag{&c.ExcludeRx}, "e", "Short form of -exclude-rx") + + fs.BoolVar(&c.AllowEmpty, "allow-empty", c.AllowEmpty, + "Allow empty structures, effectively excluding them from the check") + + fs.Var(stringSliceFlag{&c.AllowEmptyRx}, "allow-empty-rx", + "Regular expression to match type names that should be allowed to be empty. "+ + "Anonymous structs can be matched by '' alias. "+ + "Each regex must match the full type name including package path. "+ + "Example: `.*/http\\.Cookie`. Can be used multiple times.") + + fs.BoolVar(&c.AllowEmptyReturns, "allow-empty-returns", c.AllowEmptyReturns, + "Allow empty structures in return statements") + + fs.BoolVar(&c.AllowEmptyDeclarations, "allow-empty-declarations", c.AllowEmptyDeclarations, + "Allow empty structures in variable declarations") + + return fs +} diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/comment/cache.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/comment/cache.go similarity index 100% rename from vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/comment/cache.go rename to vendor/dev.gaijin.team/go/exhaustruct/v4/internal/comment/cache.go diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/comment/directive.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/comment/directive.go similarity index 100% rename from vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/comment/directive.go rename to vendor/dev.gaijin.team/go/exhaustruct/v4/internal/comment/directive.go diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/pattern/list.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/pattern/list.go new file mode 100644 index 000000000..26b8ac20d --- /dev/null +++ b/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/pattern/list.go @@ -0,0 +1,91 @@ +package pattern + +import ( + "regexp" + "strings" + + "dev.gaijin.team/go/golib/e" + "dev.gaijin.team/go/golib/fields" +) + +// List represents a collection of compiled regular expressions that can be used +// for pattern matching against strings. It implements the flag.Value interface +// to support command-line flag binding. +type List []*regexp.Regexp //nolint:recvcheck + +// NewList creates a new List from the provided regular expression patterns. +// Each pattern string is compiled into a regular expression. If any pattern +// is empty or fails to compile, an error is returned. +func NewList(patterns ...string) (List, error) { + if len(patterns) == 0 { + return nil, nil + } + + list := make(List, 0, len(patterns)) + + for _, pattern := range patterns { + re, err := parseRx(pattern) + if err != nil { + return nil, err + } + + list = append(list, re) + } + + return list, nil +} + +// MatchFullString checks if any of the regular expressions in the list matches +// the entire input string. A match is considered successful only if the regex +// matches the complete string from start to end, not just a substring. +// +// For example, if a List contains the pattern "test", it will match "test" +// but not "testing" or "contest". +func (l List) MatchFullString(str string) bool { + for i := 0; i < len(l); i++ { + if m := l[i].FindStringSubmatch(str); len(m) > 0 && m[0] == str { + return true + } + } + + return false +} + +// String returns a string representation of the List by joining all regex patterns +// with commas. This method implements the flag.Value interface and is used when +// the List is displayed or serialized. +func (l List) String() string { + patterns := make([]string, len(l)) + for i, re := range l { + patterns[i] = re.String() + } + + return strings.Join(patterns, ",") +} + +// Set adds a new regex pattern to the List by compiling the provided string. +// This method implements the flag.Value interface and is called when the flag +// is set from command-line arguments or programmatically. +func (l *List) Set(value string) error { + re, err := parseRx(value) + if err != nil { + return err + } + + *l = append(*l, re) + + return nil +} + +func parseRx(str string) (*regexp.Regexp, error) { + if str == "" { + return nil, e.New("empty regular expression is not allowed") + } + + re, err := regexp.Compile(str) + if err != nil { + return nil, e.NewFrom("failed to compile regular expression", err, fields.F("pattern", str)) + } + + return re, nil +} diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/structure/fields-cache.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/structure/fields-cache.go similarity index 100% rename from vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/structure/fields-cache.go rename to vendor/dev.gaijin.team/go/exhaustruct/v4/internal/structure/fields-cache.go diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/structure/fields.go b/vendor/dev.gaijin.team/go/exhaustruct/v4/internal/structure/fields.go similarity index 100% rename from vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/structure/fields.go rename to vendor/dev.gaijin.team/go/exhaustruct/v4/internal/structure/fields.go diff --git a/vendor/dev.gaijin.team/go/golib/LICENSE b/vendor/dev.gaijin.team/go/golib/LICENSE new file mode 100644 index 000000000..05a82fec2 --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Gaijin Entertainment + +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/vendor/dev.gaijin.team/go/golib/e/doc.go b/vendor/dev.gaijin.team/go/golib/e/doc.go new file mode 100644 index 000000000..a1582f5c1 --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/e/doc.go @@ -0,0 +1,46 @@ +// Package e provides a custom error type with support for error chaining and +// structured metadata fields. +// +// The main type, Err, enables convenient error wrapping and the attachment of +// key-value metadata fields (fields.Field). Errors can be wrapped to add context +// and enriched with fields for structured logging or diagnostics. +// +// Example: Wrapping errors with context +// +// var ErrJSONParseFailed = e.New("JSON parse failed") +// var val any +// if err := json.Unmarshal([]byte(`["invalid", "json]`), &val); err != nil { +// return ErrJSONParseFailed.Wrap(err) +// // Output: "JSON parse failed: unexpected end of JSON input" +// } +// +// Example: Enriching errors with fields +// +// err := e.New("operation failed").WithField("user_id", 42) +// // Output: "operation failed (user_id=42)" +// +// err = err.Wrap(e.New("db error").WithFields(fields.F("query", "SELECT *"))) +// // Output: "operation failed (user_id=42): db error (query=SELECT *)" +// +// Any error can be converted to an Err using the From function. This does not +// wrap the error; unwrapping will not return the original error. +// +// e.From(errors.New("error")) // "error" +// errors.Unwrap(e.From(errors.New("error"))) // nil +// +// The Err string format is: +// +// (fields...): +// +// Fields are always enclosed in parentheses, and wrapped errors are separated by +// a colon and space. +// +// All methods that return errors create new instances; errors are immutable. +// +// Deprecated methods Unwrap, Is, and As are present for compatibility with the +// errors package, but should not be used directly. Use the errors package +// functions instead. +// +// The Log function logs errors using our logger abstraction - logger.Logger, +// extracting reason, wrapped error, and fields, logging them appropriately. +package e diff --git a/vendor/dev.gaijin.team/go/golib/e/err.go b/vendor/dev.gaijin.team/go/golib/e/err.go new file mode 100644 index 000000000..334dc563c --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/e/err.go @@ -0,0 +1,140 @@ +package e + +import ( + "errors" + "slices" + "strings" + + "dev.gaijin.team/go/golib/fields" +) + +// Err represents a custom error type that supports error chaining and structured metadata fields. +type Err struct { + errs []error + fields fields.List +} + +// New returns a new Err with the given reason and optional fields. +// The returned error can be further wrapped or annotated with additional fields. +func New(reason string, f ...fields.Field) *Err { + return From(errors.New(reason), f...) //nolint:err113 +} + +// NewFrom returns a new Err with the given reason, wrapping the provided error, and optional fields. +// If wrapped is nil, it behaves like New. +func NewFrom(reason string, wrapped error, f ...fields.Field) *Err { + if wrapped == nil { + return New(reason, f...) + } + + return &Err{ + errs: []error{errors.New(reason), wrapped}, //nolint:err113 + fields: f, + } +} + +// From converts any error to an Err, optionally adding fields. This is not true wrapping; +// unwrapping will not return the original error. Passing nil results in an Err with reason "error(nil)". +func From(origin error, f ...fields.Field) *Err { + if origin == nil { + origin = errors.New("error(nil)") //nolint:err113 + } + + return &Err{ + errs: []error{origin}, + fields: f, + } +} + +// Wrap returns a new Err that wraps the provided error with the current Err as context. +// Additional fields can be attached. If err is nil, it is replaced with an Err for "error(nil)". +func (e *Err) Wrap(err error, f ...fields.Field) *Err { + if err == nil { + err = errors.New("error(nil)") //nolint:err113 + } + + return &Err{ + errs: []error{e, err}, + fields: f, + } +} + +// Error returns the string representation of the Err, including reason, fields, and wrapped errors. +func (e *Err) Error() string { + b := &strings.Builder{} + writeTo(b, e) + + return b.String() +} + +func writeTo(b *strings.Builder, err error) { + if b.Len() > 0 { + b.WriteString(": ") + } + + ee, ok := err.(*Err) //nolint:errorlint + if !ok { + b.WriteString(err.Error()) + + return + } + + b.WriteString(ee.Reason()) + + if ee == nil { + return + } + + if len(ee.fields) > 0 { + b.WriteRune(' ') + ee.fields.WriteTo(b) + } + + if len(ee.errs) > 1 { + writeTo(b, ee.errs[1]) + } +} + +// Clone returns a new Err with the same error, wrapped error, and a cloned fields container. +func (e *Err) Clone() *Err { + return &Err{ + errs: slices.Clone(e.errs), + fields: slices.Clone(e.fields), + } +} + +// WithFields returns a new Err with the same error and the provided fields. +func (e *Err) WithFields(f ...fields.Field) *Err { + return From(e, f...) +} + +// WithField returns a new Err with the same error and a single additional field. +func (e *Err) WithField(key string, val any) *Err { + return e.WithFields(fields.F(key, val)) +} + +// Fields returns the metadata fields attached to the Err. +func (e *Err) Fields() fields.List { + return e.fields +} + +// Reason returns the reason string of the Err, without fields or wrapped errors. +// If the Err is nil, returns "(*e.Err)(nil)". If empty, returns "(*e.Err)(empty)". +func (e *Err) Reason() string { + if e == nil { + return "(*e.Err)(nil)" + } + + if len(e.errs) == 0 { + return "(*e.Err)(empty)" + } + + return e.errs[0].Error() +} + +// Unwrap returns the underlying errors for compatibility with errors.Is and errors.As. +// +// Deprecated: This method is for internal use only. Prefer using the errors package directly. +func (e *Err) Unwrap() []error { + return e.errs +} diff --git a/vendor/dev.gaijin.team/go/golib/e/log.go b/vendor/dev.gaijin.team/go/golib/e/log.go new file mode 100644 index 000000000..0caafaab0 --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/e/log.go @@ -0,0 +1,33 @@ +package e + +import ( + "dev.gaijin.team/go/golib/fields" +) + +// ErrorLogger defines a function that logs an error message, an error, and optional fields. +type ErrorLogger func(msg string, err error, fs ...fields.Field) + +// Log logs the provided error using the given ErrorLogger function. +// +// If err is nil, Log does nothing. If err is of type Err, its reason is used as the log message, +// the wrapped error is passed as the error, and its fields are passed as log fields. +// For other error types, err.Error() is used as the message and nil is passed as the error. +func Log(err error, f ErrorLogger) { + if err == nil { + return + } + + // We're not interested in wrapped error, therefore we're only typecasting it. + if e, ok := err.(*Err); ok { //nolint:errorlint + var wrapped error + if len(e.errs) > 1 { + wrapped = e.errs[1] + } + + f(e.Reason(), wrapped, e.fields...) + + return + } + + f(err.Error(), nil) +} diff --git a/vendor/dev.gaijin.team/go/golib/fields/dict.go b/vendor/dev.gaijin.team/go/golib/fields/dict.go new file mode 100644 index 000000000..cd025089f --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/fields/dict.go @@ -0,0 +1,69 @@ +package fields + +import ( + "iter" + "strings" +) + +const CollectionSep = ", " + +// Dict is a map-based collection of unique fields, keyed by string. +// It provides efficient lookup and overwrites duplicate keys. +type Dict map[string]any + +// Add inserts or updates fields in the Dict, overwriting existing keys if present. +// +// Example: +// +// d := fields.Dict{"foo": "bar"} +// d.Add(fields.F("baz", 42), fields.F("foo", "qux")) // d["foo"] == "qux" +func (d Dict) Add(fields ...Field) { + for _, f := range fields { + d[f.K] = f.V + } +} + +// ToList converts the Dict to a List, with order unspecified. +// Each key-value pair becomes a Field in the resulting List. +func (d Dict) ToList() List { + s := make(List, 0, len(d)) + + for k, v := range d { + s = append(s, Field{k, v}) + } + + return s +} + +// All returns an iterator over all key-value pairs in the Dict as iter.Seq2[string, any]. +// +// Example: +// +// for k, v := range d.All() { +// fmt.Println(k, v) +// } +func (d Dict) All() iter.Seq2[string, any] { + return func(yield func(string, any) bool) { + for k, v := range d { + if !yield(k, v) { + return + } + } + } +} + +// WriteTo writes the Dict as a string in the format "(key1=val1, key2=val2)" to the provided builder. +// If the Dict is empty, nothing is written. The order of fields is unspecified. +func (d Dict) WriteTo(b *strings.Builder) { + WriteTo(b, d.All()) +} + +// String returns the Dict as a string in the format "(key1=val1, key2=val2)". +// Returns an empty string if the Dict is empty. The order of fields is unspecified. +func (d Dict) String() string { + b := strings.Builder{} + + d.WriteTo(&b) + + return b.String() +} diff --git a/vendor/dev.gaijin.team/go/golib/fields/doc.go b/vendor/dev.gaijin.team/go/golib/fields/doc.go new file mode 100644 index 000000000..1ef4ee56d --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/fields/doc.go @@ -0,0 +1,32 @@ +// Package fields provides types and functions to work with key-value pairs. +// +// The package offers three primary abstractions: +// +// - Field: A key-value pair where the key is a string and the value can be any type. +// - Dict: A map-based collection of unique fields, providing efficient key-based lookup. +// - List: An ordered collection of fields that preserves insertion order. +// +// Fields can be created using the F constructor, and both Dict and List provide +// conversion methods between the two collection types. All types implement String() +// for consistent string representation. +// +// Example usage: +// +// // Create fields +// f1 := fields.F("status", "success") +// f2 := fields.F("code", 200) +// +// // Working with a List (ordered collection) +// var list fields.List +// list.Add(f1, f2) +// fmt.Println(list) // "(status=success, code=200)" +// +// // Working with a Dict (unique key collection) +// dict := fields.Dict{} +// dict.Add(f1, f2, fields.F("status", "updated")) // overwrites "status" +// fmt.Println(dict) // "(status=updated, code=200)" (order may vary) +// +// // Converting between types +// list2 := dict.ToList() // order unspecified +// dict2 := list.ToDict() // last occurrence of each key wins +package fields diff --git a/vendor/dev.gaijin.team/go/golib/fields/field.go b/vendor/dev.gaijin.team/go/golib/fields/field.go new file mode 100644 index 000000000..324b2970f --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/fields/field.go @@ -0,0 +1,82 @@ +// Package fields provides types and functions for working with key-value fields. +package fields + +import ( + "fmt" + "iter" + "strings" +) + +// Field represents a key-value pair, where the key is a string and the value can be any type. +type Field struct { + // Key of the field + K string + // Value of the field + V any +} + +// F creates a new Field with the given key and value. +// +// Example: +// +// f := fields.F("user", "alice") +func F(key string, value any) Field { + return Field{K: key, V: value} +} + +// writeKVTo writes a key-value pair to the given builder in the format "key=value". +func writeKVTo(b *strings.Builder, key string, value any) { + b.WriteString(key) + b.WriteRune('=') + + switch val := value.(type) { + case string: + b.WriteString(val) + + case fmt.Stringer: + b.WriteString(val.String()) + + case error: + b.WriteString(val.Error()) + + default: + _, _ = fmt.Fprintf(b, "%v", value) + } +} + +// WriteTo writes the Field as a string in the format "key=value" to the provided builder. +func (f Field) WriteTo(b *strings.Builder) { + writeKVTo(b, f.K, f.V) +} + +// String returns the Field as a string in the format "key=value". +func (f Field) String() string { + b := &strings.Builder{} + f.WriteTo(b) + + return b.String() +} + +// WriteTo writes key-value pairs from an iter.Seq2[string, any] to the builder in the format "(key1=val1, key2=val2)". +// If no fields are present, nothing is written. +func WriteTo(b *strings.Builder, seq iter.Seq2[string, any]) { + first := true + + for k, v := range seq { + if first { + first = false + + b.WriteString("(") + } else { + b.WriteString(", ") + } + + writeKVTo(b, k, v) + } + + // means that we've written at least one field, and, therefore, + // can close the parenthesis + if !first { + b.WriteString(")") + } +} diff --git a/vendor/dev.gaijin.team/go/golib/fields/list.go b/vendor/dev.gaijin.team/go/golib/fields/list.go new file mode 100644 index 000000000..5a881f77e --- /dev/null +++ b/vendor/dev.gaijin.team/go/golib/fields/list.go @@ -0,0 +1,69 @@ +package fields + +import ( + "iter" + "strings" +) + +// List is an ordered collection of Field values, preserving insertion order. +// Such collection do not check for duplicate keys. +type List []Field //nolint:recvcheck //we need Add to be a pointer receiver to modify original value. + +// Add one or more fields to the List, modifying it. +// +// Example: +// +// var l fields.List +// l.Add(fields.F("foo", "bar"), fields.F("baz", 42)) +func (l *List) Add(fields ...Field) { + *l = append(*l, fields...) +} + +// ToDict converts the List to a Dict, overwriting duplicate keys with the last occurrence. +// +// Example: +// +// l := fields.List{fields.F("foo", 1), fields.F("foo", 2)} +// d := l.ToDict() // d["foo"] == 2 +func (l List) ToDict() Dict { + d := make(Dict, len(l)) + + for i := range l { + d[l[i].K] = l[i].V + } + + return d +} + +// All returns an iterator over all key-value pairs in the List as iter.Seq2[string, any]. +// +// Example: +// +// for k, v := range l.All() { +// fmt.Println(k, v) +// } +func (l List) All() iter.Seq2[string, any] { + return func(yield func(string, any) bool) { + for i := 0; i < len(l); i++ { + if !yield(l[i].K, l[i].V) { + return + } + } + } +} + +// WriteTo writes the List as a string in the format "(key1=val1, key2=val2)" to the provided builder. +// If the List is empty, nothing is written. +func (l List) WriteTo(b *strings.Builder) { + WriteTo(b, l.All()) +} + +// String returns the List as a string in the format "(key1=val1, key2=val2)". +// Returns an empty string if the List is empty. +func (l List) String() string { + b := strings.Builder{} + + l.WriteTo(&b) + + return b.String() +} diff --git a/vendor/github.com/4meepo/tagalign/tagalign.go b/vendor/github.com/4meepo/tagalign/tagalign.go index 8161a0aa7..612aefb0b 100644 --- a/vendor/github.com/4meepo/tagalign/tagalign.go +++ b/vendor/github.com/4meepo/tagalign/tagalign.go @@ -10,7 +10,7 @@ import ( "strconv" "strings" - "github.com/fatih/structtag" + "github.com/alfatraining/structtag" "golang.org/x/tools/go/analysis" ) diff --git a/vendor/github.com/Abirdcfly/dupword/README.md b/vendor/github.com/Abirdcfly/dupword/README.md index e6c5b919f..a3db4c503 100644 --- a/vendor/github.com/Abirdcfly/dupword/README.md +++ b/vendor/github.com/Abirdcfly/dupword/README.md @@ -101,10 +101,14 @@ Flags: no effect (deprecated) -c int display offending line with this many lines of context (default -1) + -comments-only + check only comments, skip strings -cpuprofile string write CPU profile to this file -debug string debug flags, any subset of "fpstv" + -diff + with -fix, don't update the files, but print a unified diff -fix apply all suggested fixes -flags @@ -130,7 +134,7 @@ Flags: ### 5. my advice -use `--keyword=the,and,a` and `-fix` together. I think that specifying only commonly repeated prepositions can effectively avoid false positives. +use `--keyword=the,and,a` and `-fix` together. I think that specifying only commonly repeated prepositions can effectively avoid false positives. see [dupword#4](https://github.com/Abirdcfly/dupword/issues/4) for real code example. diff --git a/vendor/github.com/Abirdcfly/dupword/dupword.go b/vendor/github.com/Abirdcfly/dupword/dupword.go index 6838d7e75..a3eaced8a 100644 --- a/vendor/github.com/Abirdcfly/dupword/dupword.go +++ b/vendor/github.com/Abirdcfly/dupword/dupword.go @@ -20,8 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// Package dupword defines an Analyzer that checks that duplicate words -// int the source code. +// Package dupword defines an Analyzer that checks those duplicate words in the source code. package dupword import ( @@ -49,54 +48,45 @@ This analyzer checks miswritten duplicate words in comments or package doc or st CommentPrefix = `//` ) -var ( - defaultWord = []string{} - // defaultWord = []string{"the", "and", "a"} - ignoreWord = map[string]bool{} -) - -type analyzer struct { - KeyWord []string -} +type keywords []string -func (a *analyzer) String() string { - return strings.Join(a.KeyWord, ",") +func (a keywords) String() string { + return strings.Join(a, ",") } -func (a *analyzer) Set(w string) error { +func (a *keywords) Set(w string) error { if len(w) != 0 { - a.KeyWord = make([]string, 0) - a.KeyWord = append(a.KeyWord, strings.Split(w, ",")...) + *a = append(*a, strings.Split(w, ",")...) } + return nil } -type ignore struct { -} +type ignore map[string]bool -func (a *ignore) String() string { - t := make([]string, 0, len(ignoreWord)) - for k := range ignoreWord { +func (a ignore) String() string { + var t []string + + for k := range a { t = append(t, k) } + return strings.Join(t, ",") } -func (a *ignore) Set(w string) error { +func (a ignore) Set(w string) error { for _, k := range strings.Split(w, ",") { - ignoreWord[k] = true + a[k] = true } - return nil -} -// for test only -func ClearIgnoreWord() { - ignoreWord = map[string]bool{} + return nil } func NewAnalyzer() *analysis.Analyzer { - ignore := &ignore{} - analyzer := &analyzer{KeyWord: defaultWord} + analyzer := &analyzer{ + ignoreWords: map[string]bool{}, + } + a := &analysis.Analyzer{ Name: Name, Doc: Doc, @@ -104,17 +94,29 @@ func NewAnalyzer() *analysis.Analyzer { Run: analyzer.run, RunDespiteErrors: true, } + a.Flags.Init(Name, flag.ExitOnError) - a.Flags.Var(analyzer, "keyword", "keywords for detecting duplicate words") - a.Flags.Var(ignore, "ignore", "ignore words") + a.Flags.Var(&analyzer.keywords, "keyword", "keywords for detecting duplicate words") + a.Flags.Var(&analyzer.ignoreWords, "ignore", "ignore words") + a.Flags.BoolVar(&analyzer.commentsOnly, "comments-only", false, "check only comments, skip strings") a.Flags.Var(version{}, "V", "print version and exit") + return a } +type analyzer struct { + keywords keywords + ignoreWords ignore + commentsOnly bool +} + func (a *analyzer) run(pass *analysis.Pass) (interface{}, error) { for _, file := range pass.Files { a.fixDuplicateWordInComment(pass, file) } + if a.commentsOnly { + return nil, nil + } inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ (*ast.BasicLit)(nil), @@ -208,8 +210,8 @@ func (a *analyzer) fixDuplicateWordInString(pass *analysis.Pass, lit *ast.BasicL } // CheckOneKey use to check there is a defined duplicate word in a string. -// raw is checked line. key is the keyword to check. empty means just check duplicate word. -func CheckOneKey(raw, key string) (new string, findWord string, find bool) { +// `raw` is the checked line. key is the keyword to check. empty means just check duplicate word. +func (a *analyzer) checkOneKey(raw, key string) (new string, findWord string, find bool) { if key == "" { has := false fields := strings.Fields(raw) @@ -249,7 +251,7 @@ func CheckOneKey(raw, key string) (new string, findWord string, find bool) { */ symbol := raw[spaceStart:i] if ((key != "" && curWord == key) || key == "") && curWord == preWord && curWord != "" { - if !ExcludeWords(curWord) { + if !a.excludeWords(cutTrailingCommas(curWord)) { find = true findWordMap[curWord] = true newLine.WriteString(lastSpace) @@ -270,7 +272,7 @@ func CheckOneKey(raw, key string) (new string, findWord string, find bool) { // last position word := raw[wordStart:] if ((key != "" && word == key) || key == "") && word == preWord { - if !ExcludeWords(word) { + if !a.excludeWords(cutTrailingCommas(word)) { find = true findWordMap[word] = true } @@ -296,8 +298,8 @@ func CheckOneKey(raw, key string) (new string, findWord string, find bool) { } func (a *analyzer) Check(raw string) (update string, keyword string, find bool) { - for _, key := range a.KeyWord { - updateOne, _, findOne := CheckOneKey(raw, key) + for _, key := range a.keywords { + updateOne, _, findOne := a.checkOneKey(raw, key) if findOne { raw = updateOne find = findOne @@ -309,8 +311,8 @@ func (a *analyzer) Check(raw string) (update string, keyword string, find bool) } } } - if len(a.KeyWord) == 0 { - return CheckOneKey(raw, "") + if len(a.keywords) == 0 { + return a.checkOneKey(raw, "") } return } @@ -318,7 +320,7 @@ func (a *analyzer) Check(raw string) (update string, keyword string, find bool) // ExcludeWords determines whether duplicate words should be reported, // // e.g. %s, should not be reported. -func ExcludeWords(word string) (exclude bool) { +func (a *analyzer) excludeWords(word string) (exclude bool) { firstRune, _ := utf8.DecodeRuneInString(word) if unicode.IsDigit(firstRune) { return true @@ -329,7 +331,7 @@ func ExcludeWords(word string) (exclude bool) { if unicode.IsSymbol(firstRune) { return true } - if _, exist := ignoreWord[word]; exist { + if _, exist := a.ignoreWords[word]; exist { return true } return false @@ -341,3 +343,11 @@ func isExampleOutputStart(comment string) bool { strings.HasPrefix(comment, "// Unordered output:") || strings.HasPrefix(comment, "// unordered output:") } + +// cutTrailingCommas is used to remove trailing commas of words. +// The excludeWords are provided as comma-separated list, so it is +// impossible to ignore "[word], [word]," matches otherwise +func cutTrailingCommas(s string) string { + result, _ := strings.CutSuffix(s, ",") + return result +} diff --git a/vendor/github.com/AdminBenni/iota-mixing/LICENSE b/vendor/github.com/AdminBenni/iota-mixing/LICENSE new file mode 100644 index 000000000..06e009ffa --- /dev/null +++ b/vendor/github.com/AdminBenni/iota-mixing/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Benedikt Aron Þjóðbjargarson + +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/vendor/github.com/AdminBenni/iota-mixing/pkg/analyzer/analyzer.go b/vendor/github.com/AdminBenni/iota-mixing/pkg/analyzer/analyzer.go new file mode 100644 index 000000000..4c56ebdde --- /dev/null +++ b/vendor/github.com/AdminBenni/iota-mixing/pkg/analyzer/analyzer.go @@ -0,0 +1,118 @@ +package analyzer + +import ( + "go/ast" + "go/token" + "log" + "strings" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" + + "github.com/AdminBenni/iota-mixing/pkg/analyzer/flags" +) + +func GetIotaMixingAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "iotamixing", + Doc: "checks if iotas are being used in const blocks with other non-iota declarations.", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } +} + +func run(pass *analysis.Pass) (interface{}, error) { + ASTInspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) //nolint:forcetypeassert // will always be correct type + + // we only need to check Generic Declarations + nodeFilter := []ast.Node{ + (*ast.GenDecl)(nil), + } + + ASTInspector.Preorder(nodeFilter, func(node ast.Node) { checkGenericDeclaration(node, pass) }) + + return interface{}(nil), nil +} + +func checkGenericDeclaration(node ast.Node, pass *analysis.Pass) { + decl := node.(*ast.GenDecl) //nolint:forcetypeassert // filtered for this node, will always be this type + + if decl.Tok != token.CONST { + return + } + + checkConstDeclaration(decl, pass) +} + +func checkConstDeclaration(decl *ast.GenDecl, pass *analysis.Pass) { + iotaFound := false + valued := make([]*ast.ValueSpec, 0, len(decl.Specs)) + + // traverse specs inside const block + for _, spec := range decl.Specs { + if specVal, ok := spec.(*ast.ValueSpec); ok { + iotaFound, valued = checkValueSpec(specVal, iotaFound, valued) + } + } + + if !iotaFound { + return + } + + // there was an iota, now depending on the report-individual flag we must either + // report the const block or all regular valued specs that are mixing with the iota + switch flags.ReportIndividualFlag() { + case flags.TrueString: + for _, value := range valued { + pass.Reportf( + value.Pos(), + "%s is a const with r-val in same const block as iota. keep iotas in separate const blocks", + getName(value), + ) + } + default: //nolint:gocritic // default logs error and falls through to "false" case, simplest in this order + log.Printf( + "warning: unsupported value '%s' for flag %s, assuming value 'false'.", + flags.ReportIndividualFlag(), flags.ReportIndividualFlagName, + ) + + fallthrough + case flags.FalseString: + if len(valued) == 0 { + return + } + + pass.Reportf(decl.Pos(), "iota mixing. keep iotas in separate blocks to consts with r-val") + } +} + +func checkValueSpec(spec *ast.ValueSpec, iotaFound bool, valued []*ast.ValueSpec) (bool, []*ast.ValueSpec) { + // traverse through values (r-val) of spec and look for iota + for _, expr := range spec.Values { + if idn, ok := expr.(*ast.Ident); ok && idn.Name == "iota" { + return true, valued + } + } + + // iota wasn't found, add to valued spec list if there is an r-val + if len(spec.Values) > 0 { + return iotaFound, append(valued, spec) + } + + return iotaFound, valued +} + +func getName(spec *ast.ValueSpec) string { + sb := strings.Builder{} + + for i, ident := range spec.Names { + sb.WriteString(ident.Name) + + if i < len(spec.Names)-1 { + sb.WriteString(", ") + } + } + + return sb.String() +} diff --git a/vendor/github.com/AdminBenni/iota-mixing/pkg/analyzer/flags/flags.go b/vendor/github.com/AdminBenni/iota-mixing/pkg/analyzer/flags/flags.go new file mode 100644 index 000000000..8f9b73b64 --- /dev/null +++ b/vendor/github.com/AdminBenni/iota-mixing/pkg/analyzer/flags/flags.go @@ -0,0 +1,23 @@ +package flags + +import "flag" + +const ( + TrueString = "true" + FalseString = "false" + + ReportIndividualFlagName = "report-individual" + reportIndividualFlagUsage = "whether or not to report individual consts rather than just the const block." +) + +var ( + reportIndividualFlag *string //nolint:gochecknoglobals // only used in this file, not too plussed +) + +func SetupFlags(flags *flag.FlagSet) { + reportIndividualFlag = flags.String(ReportIndividualFlagName, FalseString, reportIndividualFlagUsage) +} + +func ReportIndividualFlag() string { + return *reportIndividualFlag +} diff --git a/vendor/github.com/AlwxSin/noinlineerr/.gitignore b/vendor/github.com/AlwxSin/noinlineerr/.gitignore new file mode 100644 index 000000000..15573eff6 --- /dev/null +++ b/vendor/github.com/AlwxSin/noinlineerr/.gitignore @@ -0,0 +1,33 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# 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/ + +# Go workspace file +go.work +go.work.sum + +# env file +.env +.envrc + +# ide +.idea +.vscode + +# OS specific +.DS_Store diff --git a/vendor/github.com/AlwxSin/noinlineerr/.golangci.yml b/vendor/github.com/AlwxSin/noinlineerr/.golangci.yml new file mode 100644 index 000000000..36b315589 --- /dev/null +++ b/vendor/github.com/AlwxSin/noinlineerr/.golangci.yml @@ -0,0 +1,168 @@ +version: "2" + +linters: + default: all + disable: + - decorder + - depguard + - err113 + - exhaustruct + - nlreturn + - nonamedreturns + - paralleltest + - recvcheck + - testpackage + - varnamelen + - wrapcheck + + settings: + cyclop: + max-complexity: 30 + dogsled: + max-blank-identifiers: 2 + dupl: + threshold: 150 + errcheck: + check-type-assertions: false + check-blank: true + exclude-functions: + - fmt.Print + - fmt.Printf + - fmt.Println + - fmt.Fprint(*bytes.Buffer) + - fmt.Fprintf(*bytes.Buffer) + - fmt.Fprintln(*bytes.Buffer) + - fmt.Fprint(*strings.Builder) + - fmt.Fprintf(*strings.Builder) + - fmt.Fprintln(*strings.Builder) + - fmt.Fprint(os.Stderr) + - fmt.Fprintf(os.Stderr) + - fmt.Fprintln(os.Stderr) + - io/ioutil.ReadFile + - io/ioutil.ReadDir + gocognit: + min-complexity: 30 + goconst: + min-len: 3 + min-occurrences: 3 + gocritic: + disabled-checks: + - regexpMust + - rangeValCopy + - importShadow + - docStub + enabled-tags: + - performance + - style + - diagnostic + - experimental + - opinionated + settings: + captLocal: + paramsOnly: true + hugeParam: + sizeThreshold: 1024 + gocyclo: + min-complexity: 30 + godox: + keywords: + - FIXME + govet: + enable: + - atomicalign + disable: + - shadow + enable-all: false + disable-all: false + ireturn: + allow: + - anon + - error + - empty + - stdlib + - generic + lll: + line-length: 160 + misspell: + locale: US + mnd: + ignored-functions: + - ^strings\.SplitN + nakedret: + max-func-lines: 30 + perfsprint: + strconcat: false + prealloc: + simple: true + range-loops: true + for-loops: false + staticcheck: + checks: + - '*' + - -ST1003 + - -QF1008 + unparam: + check-exported: false + unused: + field-writes-are-uses: true + post-statements-are-reads: false + exported-fields-are-used: true + parameters-are-used: true + local-variables-are-used: true + generated-is-used: true + usetesting: + context-background: true + context-todo: true + os-chdir: true + os-mkdir-temp: true + os-setenv: true + os-temp-dir: false + os-create-temp: true + varnamelen: + min-name-length: 2 + whitespace: + multi-if: false + multi-func: false + + exclusions: + presets: + - comments + - common-false-positives + - std-error-handling + rules: + - path: _test\.go + linters: + - bodyclose + - containedctx + - contextcheck + - dogsled + - errcheck + - errchkjson + - errorlint + - forcetypeassert + - funlen + - gosec + - lll + - mnd + - musttag + - nilnil + - unparam + - gosmopolitan + + +formatters: + enable: + - gci + - gofumpt + - goimports + settings: + gci: + sections: + - standard + - default + - localmodule + - blank + - dot + gofumpt: + extra-rules: true + diff --git a/vendor/github.com/AlwxSin/noinlineerr/.goreleaser.yml b/vendor/github.com/AlwxSin/noinlineerr/.goreleaser.yml new file mode 100644 index 000000000..a36e47cdc --- /dev/null +++ b/vendor/github.com/AlwxSin/noinlineerr/.goreleaser.yml @@ -0,0 +1,25 @@ +project_name: noinlineerr +builds: + - main: ./cmd/noinlineerr/main.go + binary: noinlineerr + goos: + - linux + - darwin + - windows + goarch: + - amd64 + - arm64 + +archives: + - formats: [ 'tar.gz' ] + files: + - LICENSE + - README.md + +checksum: + name_template: 'checksums.txt' + +release: + github: + owner: AlwxSin + name: noinlineerr diff --git a/vendor/github.com/olekukonko/tablewriter/LICENSE.md b/vendor/github.com/AlwxSin/noinlineerr/LICENSE similarity index 88% rename from vendor/github.com/olekukonko/tablewriter/LICENSE.md rename to vendor/github.com/AlwxSin/noinlineerr/LICENSE index a0769b5c1..03a52166d 100644 --- a/vendor/github.com/olekukonko/tablewriter/LICENSE.md +++ b/vendor/github.com/AlwxSin/noinlineerr/LICENSE @@ -1,4 +1,6 @@ -Copyright (C) 2014 by Oleku Konko +MIT License + +Copyright (c) 2025 Alwx Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -7,13 +9,13 @@ 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 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. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/AlwxSin/noinlineerr/README.md b/vendor/github.com/AlwxSin/noinlineerr/README.md new file mode 100644 index 000000000..c0a9cb386 --- /dev/null +++ b/vendor/github.com/AlwxSin/noinlineerr/README.md @@ -0,0 +1,54 @@ +# noinlineerr + +A Go linter that forbids inline error handling using `if err := ...; err != nil`. + +--- + +## Why? +Inline error handling in Go can hurt readability by hiding the actual function call behind error plumbing. +We believe errors and functions deserve their own spotlight. + +Instead of: +```go +if err := doSomething(); err != nil { + return err +} +``` +Prefer the more explicit and readable: +```go +err := doSomething() +if err != nil { + return err +} +``` + +--- + +## Install +```bash +go install github.com/AlwxSin/noinlineerr/cmd/noinlineerr@latest +``` + +--- + +## Usage +### As a standalone tool +```bash +noinlineerr ./... +``` + +⚠️ Note: The linter detects inline error assignments only when the error variable is explicitly typed or deducible. It doesn't handle dynamically typed interfaces (e.g., `foo().Err()` where `Err()` returns an error via an interface). + +--- + +## Development +Run tests: +```bash +go test ./... +``` +Test data lives under `testdata/src/...` + +--- + +## Contributing +PRs are welcome. Let's make Go code cleaner, one `err` at a time. diff --git a/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go b/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go new file mode 100644 index 000000000..9bf562320 --- /dev/null +++ b/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go @@ -0,0 +1,154 @@ +package noinlineerr + +import ( + "bytes" + "go/ast" + "go/printer" + "go/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const errMessage = "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" + +func NewAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "noinlineerr", + Doc: "Disallows inline error handling (`if err := ...; err != nil {`)", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } +} + +func run(pass *analysis.Pass) (any, error) { + insp, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + if !ok { + return nil, nil //nolint:nilnil // nothing to return + } + + nodeFilter := []ast.Node{ + (*ast.IfStmt)(nil), + } + + insp.Preorder(nodeFilter, inlineErrorInspector(pass)) + + return nil, nil //nolint:nilnil // nothing to return +} + +func inlineErrorInspector(pass *analysis.Pass) func(n ast.Node) { + return func(n ast.Node) { + ifStmt, ok := n.(*ast.IfStmt) + if !ok || ifStmt.Init == nil { + return + } + + // check if the init clause is an assignment + assignStmt, ok := ifStmt.Init.(*ast.AssignStmt) + if !ok { + return + } + + // iterate over left-hand side variables of the assignment + for _, lhs := range assignStmt.Lhs { + ident, ok := lhs.(*ast.Ident) + if !ok { + continue + } + + // confirm type is error and it is used in condition + obj := pass.TypesInfo.ObjectOf(ident) + if !isError(obj) || ident.Name == "_" || !errorUsedInCondition(ifStmt.Cond, ident.Name) { + continue + } + + // if there are more than 1 assignment + // or there are any variables with same name + // then we can make a shadow conflict with other variables + // so don't do anything beside simple error message + if len(assignStmt.Lhs) != 1 || shadowVarsExists(ident.Name, pass.TypesInfo.Scopes[ifStmt]) { + pass.Reportf(ident.Pos(), errMessage) + return + } + + // else we know there is a simple err assignment like + // if err := func(); err != nil {} + // and we can autofix that + + var buf bytes.Buffer + + _ = printer.Fprint(&buf, pass.Fset, assignStmt) + assignText := buf.String() + + // report usage of inline error assignment + pass.Report(analysis.Diagnostic{ + Pos: ident.Pos(), + End: ident.End(), + Message: errMessage, + SuggestedFixes: []analysis.SuggestedFix{ + { + Message: "move err assignment outside if", + TextEdits: []analysis.TextEdit{ + { + // insert err := ... before if + Pos: ifStmt.Pos(), + End: ifStmt.Pos(), + NewText: []byte(assignText + "\n"), + }, + { + // delete Init part + Pos: assignStmt.Pos(), + End: assignStmt.End() + 1, // +1 for ; + NewText: nil, + }, + }, + }, + }, + }) + } + } +} + +func isError(obj types.Object) bool { + if obj == nil { + return false + } + + errorType := types.Universe.Lookup("error").Type() + + return types.AssignableTo(obj.Type(), errorType) +} + +func shadowVarsExists(name string, scope *types.Scope) bool { + if scope == nil { + return false + } + + parentScope := scope.Parent() + if parentScope == nil { + return false + } + + return parentScope.Lookup(name) != nil +} + +func errorUsedInCondition(cond ast.Expr, errIdentName string) bool { + used := false + + ast.Inspect(cond, func(n ast.Node) bool { + ident, ok := n.(*ast.Ident) + if !ok { + return true + } + + if ident.Name == errIdentName { + used = true + return false + } + + return true + }) + + return used +} diff --git a/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go b/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go index 2b8794dc2..669edcc20 100644 --- a/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go +++ b/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go @@ -21,7 +21,7 @@ func New() *analysis.Analyzer { } } -func run(pass *analysis.Pass) (interface{}, error) { +func run(pass *analysis.Pass) (any, error) { insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) insp.Nodes([]ast.Node{ @@ -72,12 +72,12 @@ func run(pass *analysis.Pass) (interface{}, error) { return true }) - return nil, nil //nolint:nilnil + return nil, nil //nolint:nilnil // Integration interface of analysis.Analyzer. } func reportAboutErrorType(pass *analysis.Pass, typePos token.Pos, typeName string) { var form string - if unicode.IsLower([]rune(typeName)[0]) { + if startsWithLower(typeName) { form = "xxxError" } else { form = "XxxError" @@ -88,7 +88,7 @@ func reportAboutErrorType(pass *analysis.Pass, typePos token.Pos, typeName strin func reportAboutArrayErrorType(pass *analysis.Pass, typePos token.Pos, typeName string) { var forms string - if unicode.IsLower([]rune(typeName)[0]) { + if startsWithLower(typeName) { forms = "`xxxErrors` or `xxxError`" } else { forms = "`XxxErrors` or `XxxError`" @@ -99,10 +99,14 @@ func reportAboutArrayErrorType(pass *analysis.Pass, typePos token.Pos, typeName func reportAboutSentinelError(pass *analysis.Pass, pos token.Pos, varName string) { var form string - if unicode.IsLower([]rune(varName)[0]) { + if startsWithLower(varName) { form = "errXxx" } else { form = "ErrXxx" } pass.Reportf(pos, "the sentinel error name `%s` should conform to the `%s` format", varName, form) } + +func startsWithLower(n string) bool { + return unicode.IsLower([]rune(n)[0]) //nolint:gocritic // Source code is Unicode text encoded in UTF-8. +} diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go index 09ca1a8d9..443d53714 100644 --- a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go +++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go @@ -58,7 +58,7 @@ var funcAndReturns = []ast.Node{ (*ast.ReturnStmt)(nil), } -func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) { +func (n *nilNil) run(pass *analysis.Pass) (any, error) { insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) var fs funcTypeStack @@ -128,7 +128,7 @@ func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) { return true }) - return nil, nil //nolint:nilnil + return nil, nil //nolint:nilnil // Integration interface of analysis.Analyzer. } type zeroValue int diff --git a/vendor/github.com/Antonboom/testifylint/analyzer/analyzer.go b/vendor/github.com/Antonboom/testifylint/analyzer/analyzer.go index a9e41b0a8..711179714 100644 --- a/vendor/github.com/Antonboom/testifylint/analyzer/analyzer.go +++ b/vendor/github.com/Antonboom/testifylint/analyzer/analyzer.go @@ -5,9 +5,9 @@ import ( "go/ast" "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" - "github.com/Antonboom/testifylint/internal/analysisutil" "github.com/Antonboom/testifylint/internal/checkers" "github.com/Antonboom/testifylint/internal/config" "github.com/Antonboom/testifylint/internal/testify" @@ -24,9 +24,10 @@ func New() *analysis.Analyzer { cfg := config.NewDefault() analyzer := &analysis.Analyzer{ - Name: name, - Doc: doc, - URL: url, + Name: name, + Doc: doc, + URL: url, + Requires: []*analysis.Analyzer{inspect.Analyzer}, Run: func(pass *analysis.Pass) (any, error) { regularCheckers, advancedCheckers, err := newCheckers(cfg) if err != nil { @@ -51,16 +52,14 @@ type testifyLint struct { } func (tl *testifyLint) run(pass *analysis.Pass) (any, error) { - filesToAnalysis := make([]*ast.File, 0, len(pass.Files)) - for _, f := range pass.Files { - if !analysisutil.Imports(f, testify.AssertPkgPath, testify.RequirePkgPath, testify.SuitePkgPath) { - continue - } - filesToAnalysis = append(filesToAnalysis, f) + // NOTE(a.telyshev): There are no premature optimizations like "scan only _test.go" or + // "scan only files with testify imports", since it could lead to skip files + // with assertions (etc. test helpers in regular Go files or suite methods). + insp, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + if !ok { + return nil, nil } - insp := inspector.New(filesToAnalysis) - // Regular checkers. insp.Preorder([]ast.Node{(*ast.CallExpr)(nil)}, func(node ast.Node) { tl.regularCheck(pass, node.(*ast.CallExpr)) diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/call_meta.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/call_meta.go index 96b5b19b0..3d9c3428a 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/call_meta.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/call_meta.go @@ -93,7 +93,7 @@ func NewCallMeta(pass *analysis.Pass, ce *ast.CallExpr) *CallMeta { isAssert := analysisutil.IsPkg(initiatorPkg, testify.AssertPkgName, testify.AssertPkgPath) isRequire := analysisutil.IsPkg(initiatorPkg, testify.RequirePkgName, testify.RequirePkgPath) - if !(isAssert || isRequire) { + if !isAssert && !isRequire { return nil } diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/checker.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/checker.go index ac23af6f6..0d8e9d2f4 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/checker.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/checker.go @@ -19,5 +19,5 @@ type RegularChecker interface { // AdvancedChecker implements complex Check logic different from trivial CallMeta check. type AdvancedChecker interface { Checker - Check(pass *analysis.Pass, inspector *inspector.Inspector) []analysis.Diagnostic + Check(pass *analysis.Pass, insp *inspector.Inspector) []analysis.Diagnostic } diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go index a05423dfe..854421e6a 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go @@ -59,7 +59,7 @@ func (checker Empty) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagno return checker.checkNotEmpty(pass, call) } -func (checker Empty) checkEmpty(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic { //nolint:gocognit +func (checker Empty) checkEmpty(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic { //nolint:gocognit // It is ok. newUseEmptyDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic { const proposed = "Empty" return newUseFunctionDiagnostic(checker.Name(), call, proposed, @@ -136,7 +136,7 @@ func (checker Empty) checkEmpty(pass *analysis.Pass, call *CallMeta) *analysis.D return nil } -func (checker Empty) checkNotEmpty(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic { //nolint:gocognit +func (checker Empty) checkNotEmpty(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic { //nolint:gocognit // It is ok. newUseNotEmptyDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic { const proposed = "NotEmpty" return newUseFunctionDiagnostic(checker.Name(), call, proposed, diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/equal_values.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/equal_values.go index df7be5779..c8f305c3e 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/equal_values.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/equal_values.go @@ -43,9 +43,17 @@ func (checker EqualValues) Check(pass *analysis.Pass, call *CallMeta) *analysis. } ft, st := pass.TypesInfo.TypeOf(first), pass.TypesInfo.TypeOf(second) - if types.Identical(ft, st) { - proposed := strings.TrimSuffix(assrn, "Values") - return newUseFunctionDiagnostic(checker.Name(), call, proposed) + if !types.Identical(ft, st) { + return nil } - return nil + + // Type of one of arguments is equivalent to any. + if isEmptyInterfaceType(ft) || isEmptyInterfaceType(st) { + // EqualValues is ok here. + // Equal would check their types and would fail. + return nil + } + + proposed := strings.TrimSuffix(assrn, "Values") + return newUseFunctionDiagnostic(checker.Name(), call, proposed) } diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go index 0e6217875..ac9d968b8 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go @@ -15,6 +15,10 @@ import ( // // assert.Error(t, err, errSentinel) // assert.NoError(t, err, errSentinel) +// assert.IsType(t, err, errSentinel) +// assert.IsType(t, (*http.MaxBytesError)(nil), err) +// assert.IsNotType(t, err, errSentinel) +// assert.IsNotType(t, store.NotFoundError{}, err) // assert.True(t, errors.Is(err, errSentinel)) // assert.False(t, errors.Is(err, errSentinel)) // assert.True(t, errors.As(err, &target)) @@ -50,6 +54,18 @@ func (checker ErrorIsAs) Check(pass *analysis.Pass, call *CallMeta) *analysis.Di return newDiagnostic(checker.Name(), call, msg, newSuggestedFuncReplacement(call, proposed)) } + case "IsType": + if len(call.Args) >= 2 && isError(pass, call.Args[0]) || isError(pass, call.Args[1]) { + msg := fmt.Sprintf("use %[1]s.ErrorIs or %[1]s.ErrorAs depending on the case", call.SelectorXStr) + return newDiagnostic(checker.Name(), call, msg) + } + + case "IsNotType": + if len(call.Args) >= 2 && isError(pass, call.Args[0]) || isError(pass, call.Args[1]) { + msg := fmt.Sprintf("use %[1]s.NotErrorIs or %[1]s.NotErrorAs depending on the case", call.SelectorXStr) + return newDiagnostic(checker.Name(), call, msg) + } + case "True": if len(call.Args) < 1 { return nil diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go index b9f28df21..b7ced9a8d 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go @@ -18,6 +18,7 @@ import ( // assert.EqualValues(t, nil, err) // assert.Exactly(t, nil, err) // assert.ErrorIs(t, err, nil) +// assert.IsType(t, err, nil) // // assert.NotNil(t, err) // assert.NotEmpty(t, err) @@ -25,6 +26,7 @@ import ( // assert.NotEqual(t, nil, err) // assert.NotEqualValues(t, nil, err) // assert.NotErrorIs(t, err, nil) +// assert.IsNotType(t, err, nil) // // and requires // @@ -54,7 +56,7 @@ func (checker ErrorNil) Check(pass *analysis.Pass, call *CallMeta) *analysis.Dia return errorFn, call.Args[0], call.Args[0].End() } - case "Equal", "EqualValues", "Exactly", "ErrorIs": + case "Equal", "EqualValues", "Exactly", "ErrorIs", "IsType": if len(call.Args) < 2 { return "", nil, token.NoPos } @@ -67,7 +69,7 @@ func (checker ErrorNil) Check(pass *analysis.Pass, call *CallMeta) *analysis.Dia return noErrorFn, b, b.End() } - case "NotEqual", "NotEqualValues", "NotErrorIs": + case "NotEqual", "NotEqualValues", "NotErrorIs", "IsNotType": if len(call.Args) < 2 { return "", nil, token.NoPos } diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go index 31ea3ff44..e0467ac70 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go @@ -73,6 +73,7 @@ func (checker ExpectedActual) Check(pass *analysis.Pass, call *CallMeta) *analys "InDeltaSlice", "InEpsilon", "InEpsilonSlice", + "IsNotType", "IsType", "JSONEq", "NotEqual", @@ -120,7 +121,9 @@ func (checker ExpectedActual) isExpectedValueCandidate(pass *analysis.Pass, expr return checker.isExpectedValueCandidate(pass, v.X) case *ast.UnaryExpr: - return (v.Op == token.AND) && checker.isExpectedValueCandidate(pass, v.X) // &value + if v.Op == token.AND || v.Op == token.SUB { // &value, -value + return checker.isExpectedValueCandidate(pass, v.X) + } case *ast.CompositeLit: return true diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go index 8b0d39999..4a0eb294e 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go @@ -57,9 +57,9 @@ func (checker *GoRequire) SetIgnoreHTTPHandlers(v bool) *GoRequire { // Other test functions called in the test function are also analyzed to make a verdict about the current function. // This leads to recursion, which the cache of processed functions (processedFuncs) helps reduce the impact of. // Also, because of this, we have to pre-collect a list of test function declarations (testsDecls). -func (checker GoRequire) Check(pass *analysis.Pass, inspector *inspector.Inspector) (diagnostics []analysis.Diagnostic) { +func (checker GoRequire) Check(pass *analysis.Pass, insp *inspector.Inspector) (diagnostics []analysis.Diagnostic) { testsDecls := make(funcDeclarations) - inspector.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { + insp.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { fd := node.(*ast.FuncDecl) if isTestingFuncOrMethod(pass, fd) { @@ -78,7 +78,7 @@ func (checker GoRequire) Check(pass *analysis.Pass, inspector *inspector.Inspect (*ast.GoStmt)(nil), (*ast.CallExpr)(nil), } - inspector.Nodes(nodesFilter, func(node ast.Node, push bool) bool { + insp.Nodes(nodesFilter, func(node ast.Node, push bool) bool { if fd, ok := node.(*ast.FuncDecl); ok { if !isTestingFuncOrMethod(pass, fd) { return false @@ -171,7 +171,7 @@ func (checker GoRequire) Check(pass *analysis.Pass, inspector *inspector.Inspect }) if !checker.ignoreHTTPHandlers { - diagnostics = append(diagnostics, checker.checkHTTPHandlers(pass, inspector)...) + diagnostics = append(diagnostics, checker.checkHTTPHandlers(pass, insp)...) } return diagnostics diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go index 0e15cc1bf..a716cb0e2 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go @@ -37,7 +37,7 @@ func isTypedUnsignedIntNumber(e ast.Expr, v int) bool { return isTypedIntNumber(e, v, "uint", "uint8", "uint16", "uint32", "uint64") } -func isTypedIntNumber(e ast.Expr, v int, types ...string) bool { +func isTypedIntNumber(e ast.Expr, v int, goTypes ...string) bool { ce, ok := e.(*ast.CallExpr) if !ok || len(ce.Args) != 1 { return false @@ -48,7 +48,7 @@ func isTypedIntNumber(e ast.Expr, v int, types ...string) bool { return false } - for _, t := range types { + for _, t := range goTypes { if fn.Name == t { return isIntNumber(ce.Args[0], v) } @@ -72,6 +72,12 @@ func isEmptyStringLit(e ast.Expr) bool { } func isBasicLit(e ast.Expr) bool { + if un, ok := e.(*ast.UnaryExpr); ok { + if un.Op == token.SUB { + return isBasicLit(un.X) + } + } + _, ok := e.(*ast.BasicLit) return ok } diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_comparison.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_comparison.go index ac11d7399..e62844307 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_comparison.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_comparison.go @@ -55,7 +55,7 @@ func isStrictComparisonWith( lhs predicate, op token.Token, rhs predicate, -) (ast.Expr, ast.Expr, bool) { +) (leftOperand ast.Expr, rightOperand ast.Expr, fact bool) { be, ok := e.(*ast.BinaryExpr) if !ok { return nil, nil, false diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_context.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_context.go index e8505fad0..2ad0ae4a3 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_context.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_context.go @@ -54,7 +54,7 @@ func findSurroundingFunc(pass *analysis.Pass, stack []ast.Node) *funcID { isHTTPHandler = true } - if i >= 2 { //nolint:nestif + if i >= 2 { //nolint:nestif // Already clear code. if ce, ok := stack[i-1].(*ast.CallExpr); ok { if se, ok := ce.Fun.(*ast.SelectorExpr); ok { isTestCleanup = implementsTestingT(pass, se.X) && se.Sel != nil && (se.Sel.Name == "Cleanup") diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go index 9bdd8ff98..51a883b14 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go @@ -22,7 +22,7 @@ import ( // assert.EqualValues(t, value, len(arr)) // assert.Exactly(t, value, len(arr)) // assert.True(t, len(arr) == value) - +// // assert.Equal(t, len(expArr), len(arr)) // assert.EqualValues(t, len(expArr), len(arr)) // assert.Exactly(t, len(expArr), len(arr)) diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go index e4e30aaf4..e96516310 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go @@ -50,12 +50,12 @@ func (checker *RequireError) SetFnPattern(p *regexp.Regexp) *RequireError { return checker } -func (checker RequireError) Check(pass *analysis.Pass, inspector *inspector.Inspector) []analysis.Diagnostic { +func (checker RequireError) Check(pass *analysis.Pass, insp *inspector.Inspector) []analysis.Diagnostic { callsByFunc := make(map[funcID][]*callMeta) // Stage 1. Collect meta information about any calls inside functions. - inspector.WithStack([]ast.Node{(*ast.CallExpr)(nil)}, func(node ast.Node, push bool, stack []ast.Node) bool { + insp.WithStack([]ast.Node{(*ast.CallExpr)(nil)}, func(node ast.Node, push bool, stack []ast.Node) bool { if !push { return false } diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_method_signature.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_method_signature.go index 5293fc7be..9ceba5db7 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_method_signature.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_method_signature.go @@ -20,8 +20,8 @@ type SuiteMethodSignature struct{} func NewSuiteMethodSignature() SuiteMethodSignature { return SuiteMethodSignature{} } func (SuiteMethodSignature) Name() string { return "suite-method-signature" } -func (checker SuiteMethodSignature) Check(pass *analysis.Pass, inspector *inspector.Inspector) (diags []analysis.Diagnostic) { - inspector.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { +func (checker SuiteMethodSignature) Check(pass *analysis.Pass, insp *inspector.Inspector) (diags []analysis.Diagnostic) { + insp.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { fd := node.(*ast.FuncDecl) if !isSuiteMethod(pass, fd) { return diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go index 94f0b4c45..074de4f76 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go @@ -22,8 +22,8 @@ type SuiteTHelper struct{} func NewSuiteTHelper() SuiteTHelper { return SuiteTHelper{} } func (SuiteTHelper) Name() string { return "suite-thelper" } -func (checker SuiteTHelper) Check(pass *analysis.Pass, inspector *inspector.Inspector) (diagnostics []analysis.Diagnostic) { - inspector.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { +func (checker SuiteTHelper) Check(pass *analysis.Pass, insp *inspector.Inspector) (diagnostics []analysis.Diagnostic) { + insp.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { fd := node.(*ast.FuncDecl) if !isSuiteMethod(pass, fd) { return diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go index 70387cca4..15de9c6c5 100644 --- a/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go +++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go @@ -146,6 +146,7 @@ func (checker UselessAssert) checkSameVars(pass *analysis.Pass, call *CallMeta) "InDeltaSlice", "InEpsilon", "InEpsilonSlice", + "IsNotType", "IsType", "JSONEq", "Less", diff --git a/vendor/github.com/Djarvur/go-err113/.travis.yml b/vendor/github.com/Djarvur/go-err113/.travis.yml index 44fe77d53..142be3e8b 100644 --- a/vendor/github.com/Djarvur/go-err113/.travis.yml +++ b/vendor/github.com/Djarvur/go-err113/.travis.yml @@ -1,18 +1,14 @@ language: go go: - - "1.13" - - "1.14" + - "1.23" + - "1.24" + - "1.25" - tip -env: - - GO111MODULE=on - before_install: - - go get github.com/axw/gocov/gocov - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover - - go get golang.org/x/tools/cmd/goimports + - go install github.com/mattn/goveralls@v0.0.12 + - go install golang.org/x/tools/cmd/goimports@v0.36.0 - wget -O - -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh script: @@ -21,4 +17,4 @@ script: - go test -v -race ./... after_success: - - test "$TRAVIS_GO_VERSION" = "1.14" && goveralls -service=travis-ci + - test "$TRAVIS_GO_VERSION" = "1.25" && goveralls -service=travis-ci diff --git a/vendor/github.com/Djarvur/go-err113/comparison.go b/vendor/github.com/Djarvur/go-err113/comparison.go index 8a8555783..a267ebdce 100644 --- a/vendor/github.com/Djarvur/go-err113/comparison.go +++ b/vendor/github.com/Djarvur/go-err113/comparison.go @@ -7,9 +7,10 @@ import ( "go/types" "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/ast/inspector" ) -func inspectComparision(pass *analysis.Pass, n ast.Node) bool { // nolint: unparam +func inspectComparision(file *ast.File, pass *analysis.Pass, n ast.Node) bool { // nolint: unparam // check whether the call expression matches time.Now().Sub() be, ok := n.(*ast.BinaryExpr) if !ok { @@ -25,6 +26,18 @@ func inspectComparision(pass *analysis.Pass, n ast.Node) bool { // nolint: unpar return true } + root := inspector.New([]*ast.File{file}).Root() + c, ok := root.FindNode(n) + if !ok { + panic(fmt.Errorf("could not find node %T in inspector for file %q", n, file.Name.Name)) + } + + for cur := c.Parent(); cur != root; cur = cur.Parent() { + if isMethodNamed(cur, pass, "Is") { + return true + } + } + oldExpr := render(pass.Fset, be) negate := "" @@ -56,6 +69,23 @@ func inspectComparision(pass *analysis.Pass, n ast.Node) bool { // nolint: unpar return true } +var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) + +func isMethodNamed(cur inspector.Cursor, pass *analysis.Pass, name string) bool { + funcNode, ok := cur.Node().(*ast.FuncDecl) + + if !ok || funcNode.Name == nil || funcNode.Name.Name != name { + return false + } + + if funcNode.Recv == nil && len(funcNode.Recv.List) != 1 { + return false + } + + typ := pass.TypesInfo.Types[funcNode.Recv.List[0].Type] + return typ.Type != nil && types.Implements(typ.Type, errorType) +} + func isError(v ast.Expr, info *types.Info) bool { if intf, ok := info.TypeOf(v).Underlying().(*types.Interface); ok { return intf.NumMethods() == 1 && intf.Method(0).FullName() == "(error).Error" diff --git a/vendor/github.com/Djarvur/go-err113/err113.go b/vendor/github.com/Djarvur/go-err113/err113.go index ec4f52ac7..190a7ded9 100644 --- a/vendor/github.com/Djarvur/go-err113/err113.go +++ b/vendor/github.com/Djarvur/go-err113/err113.go @@ -2,10 +2,10 @@ package err113 import ( - "bytes" "go/ast" "go/printer" "go/token" + "strings" "golang.org/x/tools/go/analysis" ) @@ -19,14 +19,14 @@ func NewAnalyzer() *analysis.Analyzer { } } -func run(pass *analysis.Pass) (interface{}, error) { +func run(pass *analysis.Pass) (any, error) { for _, file := range pass.Files { tlds := enumerateFileDecls(file) ast.Inspect( file, func(n ast.Node) bool { - return inspectComparision(pass, n) && + return inspectComparision(file, pass, n) && inspectDefinition(pass, tlds, n) }, ) @@ -36,8 +36,8 @@ func run(pass *analysis.Pass) (interface{}, error) { } // render returns the pretty-print of the given node. -func render(fset *token.FileSet, x interface{}) string { - var buf bytes.Buffer +func render(fset *token.FileSet, x any) string { + var buf strings.Builder if err := printer.Fprint(&buf, fset, x); err != nil { panic(err) } diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/pattern/list.go b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/pattern/list.go deleted file mode 100644 index a16e5058d..000000000 --- a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/internal/pattern/list.go +++ /dev/null @@ -1,82 +0,0 @@ -package pattern - -import ( - "fmt" - "regexp" - "strings" -) - -var ( - ErrEmptyPattern = fmt.Errorf("pattern can't be empty") - ErrCompilationFailed = fmt.Errorf("pattern compilation failed") -) - -// List is a list of regular expressions. -type List []*regexp.Regexp - -// NewList parses slice of strings to a slice of compiled regular expressions. -func NewList(strs ...string) (List, error) { - if len(strs) == 0 { - return nil, nil - } - - l := make(List, 0, len(strs)) - - for _, str := range strs { - re, err := strToRe(str) - if err != nil { - return nil, err - } - - l = append(l, re) - } - - return l, nil -} - -// MatchFullString matches provided string against all regexps in a slice and returns -// true if any of them matches whole string. -func (l List) MatchFullString(str string) bool { - for i := 0; i < len(l); i++ { - if m := l[i].FindStringSubmatch(str); len(m) > 0 && m[0] == str { - return true - } - } - - return false -} - -func (l *List) Set(value string) error { - re, err := strToRe(value) - if err != nil { - return err - } - - *l = append(*l, re) - - return nil -} - -func (l *List) String() string { - res := make([]string, 0, len(*l)) - - for _, re := range *l { - res = append(res, `"`+re.String()+`"`) - } - - return strings.Join(res, ", ") -} - -// strToRe parses string to a compiled regular expression that matches full string. -func strToRe(str string) (*regexp.Regexp, error) { - if str == "" { - return nil, ErrEmptyPattern - } - - re, err := regexp.Compile(str) - if err != nil { - return nil, fmt.Errorf("%w: %s: %w", ErrCompilationFailed, str, err) - } - - return re, nil -} diff --git a/vendor/github.com/MirrexOne/unqueryvet/.gitignore b/vendor/github.com/MirrexOne/unqueryvet/.gitignore new file mode 100644 index 000000000..bd2a78774 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/.gitignore @@ -0,0 +1,43 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +/unqueryvet + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool +*.out +coverage.html + +# Dependency directories +vendor/ + +# Go workspace file +go.work +go.work.sum + +# IDE files +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Temporary files +*.tmp +*.log +go.work +.golangci.local.yml diff --git a/vendor/github.com/MirrexOne/unqueryvet/.golangci.yml b/vendor/github.com/MirrexOne/unqueryvet/.golangci.yml new file mode 100644 index 000000000..d604d323f --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/.golangci.yml @@ -0,0 +1,20 @@ +version: "2" + +formatters: + enable: + - gofumpt + - goimports + settings: + gofumpt: + extra-rules: true + +linters: + exclusions: + warn-unused: true + presets: + - comments + - std-error-handling + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 diff --git a/vendor/github.com/MirrexOne/unqueryvet/LICENSE b/vendor/github.com/MirrexOne/unqueryvet/LICENSE new file mode 100644 index 000000000..278a61152 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 MirrexOne + +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. \ No newline at end of file diff --git a/vendor/github.com/MirrexOne/unqueryvet/Makefile b/vendor/github.com/MirrexOne/unqueryvet/Makefile new file mode 100644 index 000000000..d92d30681 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/Makefile @@ -0,0 +1,93 @@ +.PHONY: all test build fmt fmt-check lint clean install help + +# Default target +all: fmt test build + +# Run tests +test: + @echo "Running tests..." + @go test -v -race -coverprofile=coverage.out ./... + +# Build the binary +build: + @echo "Building unqueryvet..." + @go build -v ./cmd/unqueryvet + +# Format code with gofmt -s +fmt: + @echo "Formatting code..." + @find . -name "*.go" -not -path "./vendor/*" -exec gofmt -s -w {} + + @go fmt ./... + +# Check if code is formatted +fmt-check: + @echo "Checking code formatting..." + @if [ -n "$$(find . -name '*.go' -not -path './vendor/*' -exec gofmt -s -l {} +)" ]; then \ + echo "The following files need formatting:"; \ + find . -name '*.go' -not -path './vendor/*' -exec gofmt -s -l {} +; \ + exit 1; \ + else \ + echo "All files are properly formatted"; \ + fi + +# Run linter +lint: + @echo "Running linter..." + @if command -v golangci-lint > /dev/null 2>&1; then \ + ./lint-local.sh ./...; \ + else \ + echo "golangci-lint not installed. Install it from https://golangci-lint.run/usage/install/"; \ + exit 1; \ + fi + +# Clean build artifacts +clean: + @echo "Cleaning..." + @rm -f unqueryvet + @rm -f coverage.out + @rm -f .golangci.local.yml + @go clean + +# Install the binary +install: + @echo "Installing unqueryvet..." + @go install ./cmd/unqueryvet + +# Run unqueryvet on the project itself +check: + @echo "Running unqueryvet on project..." + @go run ./cmd/unqueryvet ./... + +# Generate coverage report +coverage: test + @echo "Generating coverage report..." + @go tool cover -html=coverage.out -o coverage.html + @echo "Coverage report generated: coverage.html" + +# Run benchmarks +bench: + @echo "Running benchmarks..." + @go test -bench=. -benchmem ./internal/analyzer + +# Update dependencies +deps: + @echo "Updating dependencies..." + @go mod tidy + @go mod verify + +# Help target +help: + @echo "Available targets:" + @echo " make - Format, test, and build" + @echo " make test - Run tests with race detection" + @echo " make build - Build the unqueryvet binary" + @echo " make fmt - Format all Go files with gofmt -s" + @echo " make fmt-check - Check if files are formatted" + @echo " make lint - Run golangci-lint" + @echo " make clean - Remove build artifacts" + @echo " make install - Install unqueryvet binary" + @echo " make check - Run unqueryvet on the project" + @echo " make coverage - Generate coverage report" + @echo " make bench - Run benchmarks" + @echo " make deps - Update and verify dependencies" + @echo " make help - Show this help message" diff --git a/vendor/github.com/MirrexOne/unqueryvet/README.md b/vendor/github.com/MirrexOne/unqueryvet/README.md new file mode 100644 index 000000000..407f9d289 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/README.md @@ -0,0 +1,260 @@ +# unqueryvet + +[![Go Report Card](https://goreportcard.com/badge/github.com/MirrexOne/unqueryvet)](https://goreportcard.com/report/github.com/MirrexOne/unqueryvet) +[![GoDoc](https://godoc.org/github.com/MirrexOne/unqueryvet?status.svg)](https://godoc.org/github.com/MirrexOne/unqueryvet) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +unqueryvet is a Go static analysis tool (linter) that detects `SELECT *` usage in SQL queries and SQL builders, encouraging explicit column selection for better performance, maintainability, and API stability. + +## Features + +- **Detects `SELECT *` in string literals** - Finds problematic queries in your Go code +- **Constants and variables support** - Detects `SELECT *` in const and var declarations +- **SQL Builder support** - Works with popular SQL builders like Squirrel, GORM, etc. +- **Highly configurable** - Extensive configuration options for different use cases +- **Supports `//nolint:unqueryvet`** - Standard Go linting suppression +- **golangci-lint integration** - Works seamlessly with golangci-lint +- **Zero false positives** - Smart pattern recognition for acceptable `SELECT *` usage +- **Fast and lightweight** - Built on golang.org/x/tools/go/analysis + +## Why avoid `SELECT *`? + +- **Performance**: Selecting unnecessary columns wastes network bandwidth and memory +- **Maintainability**: Schema changes can break your application unexpectedly +- **Security**: May expose sensitive data that shouldn't be returned +- **API Stability**: Adding new columns can break clients that depend on column order + +## Informative Error Messages + +Unqueryvet provides context-specific messages that explain WHY you should avoid `SELECT *`: + +```go +// Basic queries +query := "SELECT * FROM users" +// avoid SELECT * - explicitly specify needed columns for better performance, maintainability and stability + +// SQL Builders +query := squirrel.Select("*").From("users") +// avoid SELECT * in SQL builder - explicitly specify columns to prevent unnecessary data transfer and schema change issues + +// Empty Select() +query := squirrel.Select() +// SQL builder Select() without columns defaults to SELECT * - add specific columns with .Columns() method +``` + +## Quick Start + +### As a standalone tool + +```bash +go install github.com/MirrexOne/unqueryvet/cmd/unqueryvet@latest +unqueryvet ./... +``` + +### With golangci-lint (Recommended) + +Add to your `.golangci.yml`: + +```yaml +version: "2" + +linters: + enable: + - unqueryvet + + settings: + unqueryvet: + check-sql-builders: true + # By default, no functions are ignored - minimal configuration + # ignored-functions: + # - "fmt.Printf" + # - "log.Printf" + # allowed-patterns: + # - "SELECT \\* FROM information_schema\\..*" + # - "SELECT \\* FROM pg_catalog\\..*" +``` + +## Examples + +### Problematic code (will trigger warnings) + +```go +// Constants with SELECT * +const QueryUsers = "SELECT * FROM users" + +// Variables with SELECT * +var QueryOrders = "SELECT * FROM orders" + +// String literals with SELECT * +query := "SELECT * FROM users" +rows, err := db.Query("SELECT * FROM orders WHERE status = ?", "active") + +// SQL builders with SELECT * +query := squirrel.Select("*").From("products") +query := builder.Select().Columns("*").From("inventory") +``` + +### Good code (recommended) + +```go +// Constants with explicit columns +const QueryUsers = "SELECT id, name, email FROM users" + +// Variables with explicit columns +var QueryOrders = "SELECT id, status, total FROM orders" + +// String literals with explicit column selection +query := "SELECT id, name, email FROM users" +rows, err := db.Query("SELECT id, total FROM orders WHERE status = ?", "active") + +// SQL builders with explicit columns +query := squirrel.Select("id", "name", "price").From("products") +query := builder.Select().Columns("id", "quantity", "location").From("inventory") +``` + +### Acceptable SELECT * usage (won't trigger warnings) + +```go +// System/meta queries +"SELECT * FROM information_schema.tables" +"SELECT * FROM pg_catalog.pg_tables" + +// Aggregate functions +"SELECT COUNT(*) FROM users" +"SELECT MAX(*) FROM scores" + +// With nolint suppression +query := "SELECT * FROM debug_table" //nolint:unqueryvet +``` + +## Configuration + +Unqueryvet is highly configurable to fit your project's needs: + +```yaml +version: "2" + +linters: + settings: + unqueryvet: + # Enable/disable SQL builder checking (default: true) + check-sql-builders: true + + # Default allowed patterns (automatically included): + # - COUNT(*), MAX(*), MIN(*) functions + # - information_schema, pg_catalog, sys schema queries + # You can add more patterns if needed: + # allowed-patterns: + # - "SELECT \\* FROM temp_.*" +``` + +## Supported SQL Builders + +Unqueryvet supports popular SQL builders out of the box: + +- **Squirrel** - `squirrel.Select("*")`, `Select().Columns("*")` +- **GORM** - Custom query methods +- **SQLBoiler** - Generated query methods +- **Custom builders** - Any builder using `Select()` patterns + +## Integration Examples + +### GitHub Actions + +```yaml +name: Lint +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-go@v6 + - name: golangci-lint + uses: golangci/golangci-lint-action@v8 + with: + version: latest + args: --enable unqueryvet +``` + +## Command Line Options + +When used as a standalone tool: + +```bash +# Check all packages +unqueryvet ./... + +# Check specific packages +unqueryvet ./cmd/... ./internal/... + +# With custom config file +unqueryvet -config=.unqueryvet.yml ./... + +# Verbose output +unqueryvet -v ./... +``` + +## Performance + +Unqueryvet is designed to be fast and lightweight: + +- **Parallel processing**: Analyzes multiple files concurrently +- **Incremental analysis**: Only analyzes changed files when possible +- **Minimal memory footprint**: Efficient AST traversal +- **Smart caching**: Reuses analysis results when appropriate + +## Advanced Usage + +### Custom Patterns + +You can define custom regex patterns for acceptable `SELECT *` usage: + +```yaml +allowed-patterns: + # Allow SELECT * from temporary tables + - "SELECT \\* FROM temp_\\w+" + # Allow SELECT * in migration scripts + - "SELECT \\* FROM.*-- migration" + # Allow SELECT * for specific schemas + - "SELECT \\* FROM audit\\..+" +``` + +### Integration with Custom SQL Builders + +For custom SQL builders, Unqueryvet looks for these patterns: + +```go +// Method chaining +builder.Select("*") // Direct SELECT * +builder.Select().Columns("*") // Chained SELECT * + +// Variable tracking +query := builder.Select() // Empty select +// If no .Columns() call follows, triggers warning +``` + +### Running Tests + +```bash +go test ./... +go test -race ./... +go test -bench=. ./... +``` + +### Development Setup + +```bash +git clone https://github.com/MirrexOne/unqueryvet.git +cd unqueryvet +go mod tidy +go test ./... +``` + +## License + +MIT License - see [LICENSE](LICENSE) file for details. + +## Support + +- **Bug Reports**: [GitHub Issues](https://github.com/MirrexOne/unqueryvet/issues) diff --git a/vendor/github.com/MirrexOne/unqueryvet/analyzer.go b/vendor/github.com/MirrexOne/unqueryvet/analyzer.go new file mode 100644 index 000000000..28c3ba6e8 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/analyzer.go @@ -0,0 +1,27 @@ +// Package unqueryvet provides a Go static analysis tool that detects SELECT * usage +package unqueryvet + +import ( + "golang.org/x/tools/go/analysis" + + "github.com/MirrexOne/unqueryvet/internal/analyzer" + "github.com/MirrexOne/unqueryvet/pkg/config" +) + +// Analyzer is the main unqueryvet analyzer instance +// This is the primary export that golangci-lint will use +var Analyzer = analyzer.NewAnalyzer() + +// New creates a new instance of the unqueryvet analyzer +func New() *analysis.Analyzer { + return Analyzer +} + +// NewWithConfig creates a new analyzer instance with custom configuration +// This is the recommended way to use unqueryvet with custom settings +func NewWithConfig(cfg *config.UnqueryvetSettings) *analysis.Analyzer { + if cfg == nil { + return Analyzer + } + return analyzer.NewAnalyzerWithSettings(*cfg) +} diff --git a/vendor/github.com/MirrexOne/unqueryvet/config.go b/vendor/github.com/MirrexOne/unqueryvet/config.go new file mode 100644 index 000000000..03626ad38 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/config.go @@ -0,0 +1,11 @@ +package unqueryvet + +import "github.com/MirrexOne/unqueryvet/pkg/config" + +// Settings is a type alias for UnqueryvetSettings from the config package. +type Settings = config.UnqueryvetSettings + +// DefaultSettings returns the default configuration for Unqueryvet. +func DefaultSettings() Settings { + return config.DefaultSettings() +} diff --git a/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go b/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go new file mode 100644 index 000000000..ce9b9874c --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go @@ -0,0 +1,465 @@ +// Package analyzer provides the SQL static analysis implementation for detecting SELECT * usage. +package analyzer + +import ( + "go/ast" + "go/token" + "regexp" + "strconv" + "strings" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" + + "github.com/MirrexOne/unqueryvet/pkg/config" +) + +const ( + // selectKeyword is the SQL SELECT method name in builders + selectKeyword = "Select" + // columnKeyword is the SQL Column method name in builders + columnKeyword = "Column" + // columnsKeyword is the SQL Columns method name in builders + columnsKeyword = "Columns" + // defaultWarningMessage is the standard warning for SELECT * usage + defaultWarningMessage = "avoid SELECT * - explicitly specify needed columns for better performance, maintainability and stability" +) + +// NewAnalyzer creates the Unqueryvet analyzer with enhanced logic for production use +func NewAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "unqueryvet", + Doc: "detects SELECT * in SQL queries and SQL builders, preventing performance issues and encouraging explicit column selection", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } +} + +// NewAnalyzerWithSettings creates analyzer with provided settings for golangci-lint integration +func NewAnalyzerWithSettings(s config.UnqueryvetSettings) *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "unqueryvet", + Doc: "detects SELECT * in SQL queries and SQL builders, preventing performance issues and encouraging explicit column selection", + Run: func(pass *analysis.Pass) (any, error) { + return RunWithConfig(pass, &s) + }, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } +} + +// RunWithConfig performs analysis with provided configuration +// This is the main entry point for configured analysis +func RunWithConfig(pass *analysis.Pass, cfg *config.UnqueryvetSettings) (any, error) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + // Use provided configuration or default if nil + if cfg == nil { + defaultSettings := config.DefaultSettings() + cfg = &defaultSettings + } + + // Define AST node types we're interested in + nodeFilter := []ast.Node{ + (*ast.CallExpr)(nil), // Function/method calls + (*ast.File)(nil), // Files (for SQL builder analysis) + (*ast.AssignStmt)(nil), // Assignment statements for standalone literals + (*ast.GenDecl)(nil), // General declarations (const, var, type) + } + + // Walk through all AST nodes and analyze them + insp.Preorder(nodeFilter, func(n ast.Node) { + switch node := n.(type) { + case *ast.File: + // Analyze SQL builders only if enabled in configuration + if cfg.CheckSQLBuilders { + analyzeSQLBuilders(pass, node) + } + case *ast.AssignStmt: + // Check assignment statements for standalone SQL literals + checkAssignStmt(pass, node, cfg) + case *ast.GenDecl: + // Check constant and variable declarations + checkGenDecl(pass, node, cfg) + case *ast.CallExpr: + // Analyze function calls for SQL with SELECT * usage + checkCallExpr(pass, node, cfg) + } + }) + + return nil, nil +} + +// run performs the main analysis of Go code files for SELECT * usage +func run(pass *analysis.Pass) (any, error) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + // Define AST node types we're interested in + nodeFilter := []ast.Node{ + (*ast.CallExpr)(nil), // Function/method calls + (*ast.File)(nil), // Files (for SQL builder analysis) + (*ast.AssignStmt)(nil), // Assignment statements for standalone literals + (*ast.GenDecl)(nil), // General declarations (const, var) + } + + // Always use default settings since passing settings through ResultOf doesn't work reliably + defaultSettings := config.DefaultSettings() + cfg := &defaultSettings + + // Walk through all AST nodes and analyze them + insp.Preorder(nodeFilter, func(n ast.Node) { + switch node := n.(type) { + case *ast.File: + // Analyze SQL builders only if enabled in configuration + if cfg.CheckSQLBuilders { + analyzeSQLBuilders(pass, node) + } + case *ast.AssignStmt: + // Check assignment statements for standalone SQL literals + checkAssignStmt(pass, node, cfg) + case *ast.GenDecl: + // Check constant and variable declarations + checkGenDecl(pass, node, cfg) + case *ast.CallExpr: + // Analyze function calls for SQL with SELECT * usage + checkCallExpr(pass, node, cfg) + } + }) + + return nil, nil +} + +// checkAssignStmt checks assignment statements for standalone SQL literals +func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, cfg *config.UnqueryvetSettings) { + // Check right-hand side expressions for string literals with SELECT * + for _, expr := range stmt.Rhs { + // Only check direct string literals, not function calls + if lit, ok := expr.(*ast.BasicLit); ok && lit.Kind == token.STRING { + content := normalizeSQLQuery(lit.Value) + if isSelectStarQuery(content, cfg) { + pass.Report(analysis.Diagnostic{ + Pos: lit.Pos(), + Message: getWarningMessage(), + }) + } + } + } +} + +// checkGenDecl checks general declarations (const, var) for SELECT * in SQL queries +func checkGenDecl(pass *analysis.Pass, decl *ast.GenDecl, cfg *config.UnqueryvetSettings) { + // Only check const and var declarations + if decl.Tok != token.CONST && decl.Tok != token.VAR { + return + } + + // Iterate through all specifications in the declaration + for _, spec := range decl.Specs { + // Type assert to ValueSpec (const/var specifications) + valueSpec, ok := spec.(*ast.ValueSpec) + if !ok { + continue + } + + // Check all values in the specification + for _, value := range valueSpec.Values { + // Only check direct string literals + if lit, ok := value.(*ast.BasicLit); ok && lit.Kind == token.STRING { + content := normalizeSQLQuery(lit.Value) + if isSelectStarQuery(content, cfg) { + pass.Report(analysis.Diagnostic{ + Pos: lit.Pos(), + Message: getWarningMessage(), + }) + } + } + } + } +} + +// checkCallExpr analyzes function calls for SQL with SELECT * usage +// Includes checking arguments and SQL builders +func checkCallExpr(pass *analysis.Pass, call *ast.CallExpr, cfg *config.UnqueryvetSettings) { + // Check SQL builders for SELECT * in arguments + if cfg.CheckSQLBuilders && isSQLBuilderSelectStar(call) { + pass.Report(analysis.Diagnostic{ + Pos: call.Pos(), + Message: getDetailedWarningMessage("sql_builder"), + }) + return + } + + // Check function call arguments for strings with SELECT * + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + content := normalizeSQLQuery(lit.Value) + if isSelectStarQuery(content, cfg) { + pass.Report(analysis.Diagnostic{ + Pos: lit.Pos(), + Message: getWarningMessage(), + }) + } + } + } +} + +// NormalizeSQLQuery normalizes SQL query for analysis with advanced escape sequence handling. +// Exported for testing purposes. +func NormalizeSQLQuery(query string) string { + return normalizeSQLQuery(query) +} + +func normalizeSQLQuery(query string) string { + if len(query) < 2 { + return query + } + + first, last := query[0], query[len(query)-1] + + // 1. Handle different quote types with escape sequence processing + if first == '"' && last == '"' { + // For regular strings check for escape sequences + if !strings.Contains(query, "\\") { + query = trimQuotes(query) + } else if unquoted, err := strconv.Unquote(query); err == nil { + // Use standard Go unquoting for proper escape sequence handling + query = unquoted + } else { + // Fallback: simple quote removal + query = trimQuotes(query) + } + } else if first == '`' && last == '`' { + // Raw strings - simply remove backticks + query = trimQuotes(query) + } + + // 2. Process comments line by line before normalization + lines := strings.Split(query, "\n") + var processedParts []string + + for _, line := range lines { + // Remove comments from current line + if idx := strings.Index(line, "--"); idx != -1 { + line = line[:idx] + } + + // Add non-empty lines + if trimmed := strings.TrimSpace(line); trimmed != "" { + processedParts = append(processedParts, trimmed) + } + } + + // 3. Reassemble query and normalize + query = strings.Join(processedParts, " ") + query = strings.ToUpper(query) + query = strings.ReplaceAll(query, "\t", " ") + query = regexp.MustCompile(`\s+`).ReplaceAllString(query, " ") + + return strings.TrimSpace(query) +} + +// trimQuotes removes first and last character (quotes) +func trimQuotes(query string) string { + return query[1 : len(query)-1] +} + +// IsSelectStarQuery determines if query contains SELECT * with enhanced allowed patterns support. +// Exported for testing purposes. +func IsSelectStarQuery(query string, cfg *config.UnqueryvetSettings) bool { + return isSelectStarQuery(query, cfg) +} + +func isSelectStarQuery(query string, cfg *config.UnqueryvetSettings) bool { + // Check allowed patterns first - if query matches an allowed pattern, ignore it + for _, pattern := range cfg.AllowedPatterns { + if matched, _ := regexp.MatchString(pattern, query); matched { + return false + } + } + + // Check for SELECT * in query (case-insensitive) + upperQuery := strings.ToUpper(query) + if strings.Contains(upperQuery, "SELECT *") { //nolint:unqueryvet + // Ensure this is actually an SQL query by checking for SQL keywords + sqlKeywords := []string{"FROM", "WHERE", "JOIN", "GROUP", "ORDER", "HAVING", "UNION", "LIMIT"} + for _, keyword := range sqlKeywords { + if strings.Contains(upperQuery, keyword) { + return true + } + } + + // Also check if it's just "SELECT *" without other keywords (still problematic) + trimmed := strings.TrimSpace(upperQuery) + if trimmed == "SELECT *" { + return true + } + } + return false +} + +// getWarningMessage returns informative warning message +func getWarningMessage() string { + return defaultWarningMessage +} + +// getDetailedWarningMessage returns context-specific warning message +func getDetailedWarningMessage(context string) string { + switch context { + case "sql_builder": + return "avoid SELECT * in SQL builder - explicitly specify columns to prevent unnecessary data transfer and schema change issues" + case "nested": + return "avoid SELECT * in subquery - can cause performance issues and unexpected results when schema changes" + case "empty_select": + return "SQL builder Select() without columns defaults to SELECT * - add specific columns with .Columns() method" + default: + return defaultWarningMessage + } +} + +// isSQLBuilderSelectStar checks SQL builder method calls for SELECT * usage +func isSQLBuilderSelectStar(call *ast.CallExpr) bool { + fun, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // Check that this is a Select method call + if fun.Sel == nil || fun.Sel.Name != selectKeyword { + return false + } + + if len(call.Args) == 0 { + return false + } + + // Check Select method arguments for "*" or empty strings + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + // Consider both "*" and empty strings in Select() as problematic + if value == "*" || value == "" { + return true + } + } + } + + return false +} + +// analyzeSQLBuilders performs advanced SQL builder analysis +// Key logic for handling edge-cases like Select().Columns("*") +func analyzeSQLBuilders(pass *analysis.Pass, file *ast.File) { + // Track SQL builder variables and their state + builderVars := make(map[string]*ast.CallExpr) // Variables with empty Select() calls + hasColumns := make(map[string]bool) // Flag: were columns added for variable + + // First pass: find variables created with empty Select() calls + ast.Inspect(file, func(n ast.Node) bool { + switch node := n.(type) { + case *ast.AssignStmt: + // Analyze assignments like: query := builder.Select() + for i, expr := range node.Rhs { + if call, ok := expr.(*ast.CallExpr); ok { + if isEmptySelectCall(call) { + // Found empty Select() call, remember the variable + if i < len(node.Lhs) { + if ident, ok := node.Lhs[i].(*ast.Ident); ok { + builderVars[ident.Name] = call + hasColumns[ident.Name] = false + } + } + } + } + } + } + return true + }) + + // Second pass: check usage of Columns/Column methods + ast.Inspect(file, func(n ast.Node) bool { + switch node := n.(type) { + case *ast.CallExpr: + if sel, ok := node.Fun.(*ast.SelectorExpr); ok { + // Check calls to Columns() or Column() methods + if sel.Sel != nil && (sel.Sel.Name == columnsKeyword || sel.Sel.Name == columnKeyword) { + // Check for "*" in arguments + if hasStarInColumns(node) { + pass.Report(analysis.Diagnostic{ + Pos: node.Pos(), + Message: getDetailedWarningMessage("sql_builder"), + }) + } + + // Update variable state - columns were added + if ident, ok := sel.X.(*ast.Ident); ok { + if _, exists := builderVars[ident.Name]; exists { + if !hasStarInColumns(node) { + hasColumns[ident.Name] = true + } + } + } + } + } + + // Check call chains like builder.Select().Columns("*") + if isSelectWithColumns(node) { + if hasStarInColumns(node) { + if sel, ok := node.Fun.(*ast.SelectorExpr); ok && sel.Sel != nil { + pass.Report(analysis.Diagnostic{ + Pos: node.Pos(), + Message: getDetailedWarningMessage("sql_builder"), + }) + } + } + return true + } + } + return true + }) + + // Final check: warn about builders with empty Select() without subsequent columns + for varName, call := range builderVars { + if !hasColumns[varName] { + pass.Report(analysis.Diagnostic{ + Pos: call.Pos(), + Message: getDetailedWarningMessage("empty_select"), + }) + } + } +} + +// isEmptySelectCall checks if call is an empty Select() +func isEmptySelectCall(call *ast.CallExpr) bool { + if sel, ok := call.Fun.(*ast.SelectorExpr); ok { + if sel.Sel != nil && sel.Sel.Name == selectKeyword && len(call.Args) == 0 { + return true + } + } + return false +} + +// isSelectWithColumns checks call chains like Select().Columns() +func isSelectWithColumns(call *ast.CallExpr) bool { + if sel, ok := call.Fun.(*ast.SelectorExpr); ok { + if sel.Sel != nil && (sel.Sel.Name == columnsKeyword || sel.Sel.Name == columnKeyword) { + // Check that previous call in chain is Select() + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + return isEmptySelectCall(innerCall) + } + } + } + return false +} + +// hasStarInColumns checks if call arguments contain "*" symbol +func hasStarInColumns(call *ast.CallExpr) bool { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + return true + } + } + } + return false +} diff --git a/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go b/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go new file mode 100644 index 000000000..034c324d1 --- /dev/null +++ b/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go @@ -0,0 +1,27 @@ +// Package config provides configuration structures for Unqueryvet analyzer. +package config + +// UnqueryvetSettings holds the configuration for the Unqueryvet analyzer. +type UnqueryvetSettings struct { + // CheckSQLBuilders enables checking SQL builders like Squirrel for SELECT * usage + CheckSQLBuilders bool `mapstructure:"check-sql-builders" json:"check-sql-builders" yaml:"check-sql-builders"` + + // AllowedPatterns is a list of regex patterns that are allowed to use SELECT * + // Example: ["SELECT \\* FROM temp_.*", "SELECT \\* FROM .*_backup"] + AllowedPatterns []string `mapstructure:"allowed-patterns" json:"allowed-patterns" yaml:"allowed-patterns"` +} + +// DefaultSettings returns the default configuration for unqueryvet +func DefaultSettings() UnqueryvetSettings { + return UnqueryvetSettings{ + CheckSQLBuilders: true, + AllowedPatterns: []string{ + `(?i)COUNT\(\s*\*\s*\)`, + `(?i)MAX\(\s*\*\s*\)`, + `(?i)MIN\(\s*\*\s*\)`, + `(?i)SELECT \* FROM information_schema\..*`, + `(?i)SELECT \* FROM pg_catalog\..*`, + `(?i)SELECT \* FROM sys\..*`, + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/v2/.gitignore b/vendor/github.com/alecthomas/chroma/v2/.gitignore index 8cbdd75ea..aedf83d99 100644 --- a/vendor/github.com/alecthomas/chroma/v2/.gitignore +++ b/vendor/github.com/alecthomas/chroma/v2/.gitignore @@ -23,3 +23,6 @@ _models/ _examples/ *.min.* build/ + +cmd/chromad/static/chroma.wasm +cmd/chromad/static/wasm_exec.js diff --git a/vendor/github.com/alecthomas/chroma/v2/Dockerfile b/vendor/github.com/alecthomas/chroma/v2/Dockerfile new file mode 100644 index 000000000..e2a153133 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/Dockerfile @@ -0,0 +1,65 @@ +# Multi-stage Dockerfile for chromad Go application using Hermit-managed tools + +# Build stage +FROM ubuntu:24.04 AS builder + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + curl \ + git \ + make \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Set working directory +WORKDIR /app + +# Copy the entire project (including bin directory with Hermit tools) +COPY . . + +# Make Hermit tools executable and add to PATH +ENV PATH="/app/bin:${PATH}" + +# Set Go environment variables for static compilation +ENV CGO_ENABLED=0 +ENV GOOS=linux +ENV GOARCH=amd64 + +# Build the application using make +RUN make build/chromad + +# Runtime stage +FROM alpine:3.22 AS runtime + +# Install ca-certificates for HTTPS requests +RUN apk --no-cache add ca-certificates curl + +# Create a non-root user +RUN addgroup -g 1001 chromad && \ + adduser -D -s /bin/sh -u 1001 -G chromad chromad + +# Set working directory +WORKDIR /app + +# Copy the binary from build stage +COPY --from=builder /app/build/chromad /app/chromad + +# Change ownership to non-root user +RUN chown chromad:chromad /app/chromad + +# Switch to non-root user +USER chromad + +# Expose port (default is 8080, but can be overridden via PORT env var) +EXPOSE 8080 + +# Set default environment variables +ENV PORT=8080 +ENV CHROMA_CSRF_KEY="testtest" + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -fsSL http://127.0.0.1:8080/ > /dev/null + +# Run the application +CMD ["sh", "-c", "./chromad --csrf-key=$CHROMA_CSRF_KEY --bind=0.0.0.0:$PORT"] diff --git a/vendor/github.com/alecthomas/chroma/v2/Makefile b/vendor/github.com/alecthomas/chroma/v2/Makefile index 50b22ad23..ca89f7cb0 100644 --- a/vendor/github.com/alecthomas/chroma/v2/Makefile +++ b/vendor/github.com/alecthomas/chroma/v2/Makefile @@ -6,21 +6,37 @@ export GOARCH ?= amd64 all: README.md tokentype_string.go -README.md: lexers/*/*.go - ./table.py +README.md: lexers/*.go lexers/embedded/*.xml + GOOS= GOARCH= ./table.py tokentype_string.go: types.go go generate +.PHONY: format-js +format-js: + biome format --write cmd/chromad/static/{index.js,chroma.js} + .PHONY: chromad chromad: build/chromad -build/chromad: $(find . -name '*.go' -o -name '*.html' -o '*.css' -o '*.js') +build/chromad: $(shell find cmd/chromad -name '*.go' -o -name '*.html' -o -name '*.css' -o -name '*.js') \ + cmd/chromad/static/wasm_exec.js \ + cmd/chromad/static/chroma.wasm rm -rf build - esbuild --bundle cmd/chromad/static/index.js --minify --outfile=cmd/chromad/static/index.min.js + esbuild --platform=node --bundle cmd/chromad/static/index.js --minify --outfile=cmd/chromad/static/index.min.js esbuild --bundle cmd/chromad/static/index.css --minify --outfile=cmd/chromad/static/index.min.css (export CGOENABLED=0 ; go build -C cmd/chromad -ldflags="-X 'main.version=$(VERSION)'" -o ../../build/chromad .) +cmd/chromad/static/wasm_exec.js: $(shell tinygo env TINYGOROOT)/targets/wasm_exec.js + install -m644 $< $@ + +cmd/chromad/static/chroma.wasm: $(shell git ls-files | grep '\.go|\.xml') + if type tinygo > /dev/null; then \ + tinygo build -no-debug -target wasm -o $@ cmd/libchromawasm/main.go; \ + else \ + GOOS=js GOARCH=wasm go build -o $@ cmd/libchromawasm/main.go; \ + fi + upload: build/chromad scp build/chromad root@swapoff.org: && \ ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart' diff --git a/vendor/github.com/alecthomas/chroma/v2/README.md b/vendor/github.com/alecthomas/chroma/v2/README.md index 9f966ed06..b65c32523 100644 --- a/vendor/github.com/alecthomas/chroma/v2/README.md +++ b/vendor/github.com/alecthomas/chroma/v2/README.md @@ -2,7 +2,7 @@ # A general purpose syntax highlighter in pure Go -[![Golang Documentation](https://godoc.org/github.com/alecthomas/chroma?status.svg)](https://godoc.org/github.com/alecthomas/chroma) [![CI](https://github.com/alecthomas/chroma/actions/workflows/ci.yml/badge.svg)](https://github.com/alecthomas/chroma/actions/workflows/ci.yml) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://invite.slack.golangbridge.org/) +[![Go Reference](https://pkg.go.dev/badge/github.com/alecthomas/chroma/v2.svg)](https://pkg.go.dev/github.com/alecthomas/chroma/v2) [![CI](https://github.com/alecthomas/chroma/actions/workflows/ci.yml/badge.svg)](https://github.com/alecthomas/chroma/actions/workflows/ci.yml) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://invite.slack.golangbridge.org/) Chroma takes source code and other structured text and converts it into syntax @@ -34,33 +34,34 @@ translators for Pygments lexers and styles. ## Supported languages -| Prefix | Language | -| :----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, AutoHotkey, AutoIt, Awk | -| B | Ballerina, Bash, Bash Session, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck | -| C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython | -| D | D, Dart, Dax, Desktop Entry, Diff, Django/Jinja, dns, Docker, DTD, Dylan | -| E | EBNF, Elixir, Elm, EmacsLisp, Erlang | -| F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp | -| G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML 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, Java, JavaScript, JSON, Jsonnet, Julia, Jungle | -| K | Kotlin | -| L | Lean, Lighttpd configuration file, LLVM, Lua | -| M | Makefile, Mako, markdown, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, MiniZinc, MLIR, Modula-2, Mojo, MonkeyC, MorrowindScript, Myghty, MySQL | -| N | NASM, Natural, Newspeak, Nginx configuration file, Nim, Nix, NSIS | -| O | Objective-C, 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, PromQL, Promela, properties, Protocol Buffer, PRQL, PSL, Puppet, Python, Python 2 | -| Q | QBasic, QML | -| R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, 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 | -| T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData, Typst | -| V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue | -| W | WDTE, WebGPU Shading Language, Whiley | -| X | XML, Xorg | -| Y | YAML, YANG | -| Z | Z80 Assembly, Zed, Zig | +| 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 +| B | Ballerina, Bash, Bash Session, Batchfile, Beef, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck +| C | C, C#, C++, 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 +| 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 | Kotlin +| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua +| M | Makefile, Mako, markdown, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, MiniZinc, MLIR, 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, PRQL, PSL, Puppet, Python, Python 2 +| Q | QBasic, QML +| R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, 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 +| 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 +| W | WDTE, WebGPU Shading Language, WebVTT, Whiley +| X | XML, Xorg +| Y | YAML, YANG +| Z | Z80 Assembly, Zed, Zig _I will attempt to keep this section up to date, but an authoritative list can be displayed with `chroma --list`._ diff --git a/vendor/github.com/alecthomas/chroma/v2/biome.json b/vendor/github.com/alecthomas/chroma/v2/biome.json new file mode 100644 index 000000000..a5bec2e19 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/biome.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.0.5/schema.json", + "formatter": { + "indentStyle": "space" + } +} diff --git a/vendor/github.com/alecthomas/chroma/v2/delegate.go b/vendor/github.com/alecthomas/chroma/v2/delegate.go index f848194f6..298f2dbbd 100644 --- a/vendor/github.com/alecthomas/chroma/v2/delegate.go +++ b/vendor/github.com/alecthomas/chroma/v2/delegate.go @@ -24,6 +24,15 @@ func DelegatingLexer(root Lexer, language Lexer) Lexer { } } +func (d *delegatingLexer) SetTracing(enable bool) { + if l, ok := d.language.(TracingLexer); ok { + l.SetTracing(enable) + } + if l, ok := d.root.(TracingLexer); ok { + l.SetTracing(enable) + } +} + func (d *delegatingLexer) AnalyseText(text string) float32 { return d.root.AnalyseText(text) } diff --git a/vendor/github.com/alecthomas/chroma/v2/emitters.go b/vendor/github.com/alecthomas/chroma/v2/emitters.go index 0788b5b21..1097a7576 100644 --- a/vendor/github.com/alecthomas/chroma/v2/emitters.go +++ b/vendor/github.com/alecthomas/chroma/v2/emitters.go @@ -10,6 +10,12 @@ type Emitter interface { Emit(groups []string, state *LexerState) Iterator } +// ValidatingEmitter is an Emitter that can validate against a compiled rule. +type ValidatingEmitter interface { + Emitter + ValidateEmitter(rule *CompiledRule) error +} + // SerialisableEmitter is an Emitter that can be serialised and deserialised to/from JSON. type SerialisableEmitter interface { Emitter @@ -30,6 +36,8 @@ type byGroupsEmitter struct { Emitters } +var _ ValidatingEmitter = (*byGroupsEmitter)(nil) + // ByGroups emits a token for each matching group in the rule's regex. func ByGroups(emitters ...Emitter) Emitter { return &byGroupsEmitter{Emitters: emitters} @@ -37,6 +45,13 @@ func ByGroups(emitters ...Emitter) Emitter { func (b *byGroupsEmitter) EmitterKind() string { return "bygroups" } +func (b *byGroupsEmitter) ValidateEmitter(rule *CompiledRule) error { + if len(rule.Regexp.GetGroupNumbers())-1 != len(b.Emitters) { + return fmt.Errorf("number of groups %d does not match number of emitters %d", len(rule.Regexp.GetGroupNumbers())-1, len(b.Emitters)) + } + return nil +} + func (b *byGroupsEmitter) Emit(groups []string, state *LexerState) Iterator { iterators := make([]Iterator, 0, len(groups)-1) if len(b.Emitters) != len(groups)-1 { diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go b/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go index 92d784c24..c1c8875b2 100644 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go +++ b/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go @@ -34,6 +34,9 @@ func WithCustomCSS(css map[chroma.TokenType]string) Option { } } +// WithCSSComments adds prefixe comments to the css classes. Defaults to true. +func WithCSSComments(b bool) Option { return func(f *Formatter) { f.writeCSSComments = b } } + // TabWidth sets the number of characters for a tab. Defaults to 8. func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } } @@ -131,8 +134,9 @@ func BaseLineNumber(n int) Option { // New HTML formatter. func New(options ...Option) *Formatter { f := &Formatter{ - baseLineNumber: 1, - preWrapper: defaultPreWrapper, + baseLineNumber: 1, + preWrapper: defaultPreWrapper, + writeCSSComments: true, } f.styleCache = newStyleCache(f) for _, option := range options { @@ -197,6 +201,7 @@ type Formatter struct { Classes bool // Exported field to detect when classes are being used allClasses bool customCSS map[chroma.TokenType]string + writeCSSComments bool preWrapper PreWrapper inlineCode bool preventSurroundingPre bool @@ -416,21 +421,37 @@ func (f *Formatter) tabWidthStyle() string { return "" } +func (f *Formatter) writeCSSRule(w io.Writer, comment string, selector string, styles string) error { + if styles == "" { + return nil + } + if f.writeCSSComments && comment != "" { + if _, err := fmt.Fprintf(w, "/* %s */ ", comment); err != nil { + return err + } + } + if _, err := fmt.Fprintf(w, "%s { %s }\n", selector, styles); err != nil { + return err + } + return nil +} + // WriteCSS writes CSS style definitions (without any surrounding HTML). func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error { css := f.styleCache.get(style, false) + // Special-case background as it is mapped to the outer ".chroma" class. - if _, err := fmt.Fprintf(w, "/* %s */ .%sbg { %s }\n", chroma.Background, f.prefix, css[chroma.Background]); err != nil { + if err := f.writeCSSRule(w, chroma.Background.String(), fmt.Sprintf(".%sbg", f.prefix), css[chroma.Background]); err != nil { return err } // Special-case PreWrapper as it is the ".chroma" class. - if _, err := fmt.Fprintf(w, "/* %s */ .%schroma { %s }\n", chroma.PreWrapper, f.prefix, css[chroma.PreWrapper]); err != nil { + if err := f.writeCSSRule(w, chroma.PreWrapper.String(), fmt.Sprintf(".%schroma", f.prefix), css[chroma.PreWrapper]); err != nil { return err } // Special-case code column of table to expand width. if f.lineNumbers && f.lineNumbersInTable { - if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s:last-child { width: 100%%; }", - chroma.LineTableTD, f.prefix, f.class(chroma.LineTableTD)); err != nil { + selector := fmt.Sprintf(".%schroma .%s:last-child", f.prefix, f.class(chroma.LineTableTD)) + if err := f.writeCSSRule(w, chroma.LineTableTD.String(), selector, "width: 100%;"); err != nil { return err } } @@ -438,7 +459,11 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error { if f.lineNumbers || f.lineNumbersInTable { targetedLineCSS := StyleEntryToCSS(style.Get(chroma.LineHighlight)) for _, tt := range []chroma.TokenType{chroma.LineNumbers, chroma.LineNumbersTable} { - fmt.Fprintf(w, "/* %s targeted by URL anchor */ .%schroma .%s:target { %s }\n", tt, f.prefix, f.class(tt), targetedLineCSS) + comment := fmt.Sprintf("%s targeted by URL anchor", tt) + selector := fmt.Sprintf(".%schroma .%s:target", f.prefix, f.class(tt)) + if err := f.writeCSSRule(w, comment, selector, targetedLineCSS); err != nil { + return err + } } } tts := []int{} @@ -456,8 +481,7 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error { if class == "" { continue } - styles := css[tt] - if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s { %s }\n", tt, f.prefix, class, styles); err != nil { + if err := f.writeCSSRule(w, tt.String(), fmt.Sprintf(".%schroma .%s", f.prefix, class), css[tt]); err != nil { return err } } diff --git a/vendor/github.com/alecthomas/chroma/v2/lexer.go b/vendor/github.com/alecthomas/chroma/v2/lexer.go index eb027bf69..602db1c4f 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexer.go +++ b/vendor/github.com/alecthomas/chroma/v2/lexer.go @@ -130,6 +130,23 @@ type Lexer interface { AnalyseText(text string) float32 } +// Trace is the trace of a tokenisation process. +type Trace struct { + Lexer string `json:"lexer"` + State string `json:"state"` + Rule int `json:"rule"` + Pattern string `json:"pattern"` + Pos int `json:"pos"` + Length int `json:"length"` + Elapsed float64 `json:"elapsedMs"` // Elapsed time spent matching for this rule. +} + +// TracingLexer is a Lexer that can trace its tokenisation process. +type TracingLexer interface { + Lexer + SetTracing(enable bool) +} + // Lexers is a slice of lexers sortable by name. type Lexers []Lexer diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml index 84fe20b34..230ef868c 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml @@ -6,103 +6,104 @@ - - + + - - + + - - + + - + - - + + - + - - - - - - + + + + + + - + - - - - + + + + - - - - + + + + + - + - - - + + + - + - - + + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml index 1de6c67ee..5a6224ac0 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml @@ -8,123 +8,144 @@ - + - + - + - + - - + + - + - - - + + + - + - - + + - + - - + + - - - - - + + - - - + + + - + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - - + + - - + + - + - + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml index 00399c2c8..6a75df5b9 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml @@ -9,301 +9,314 @@ - - + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - - - + + + - + - + - - + + - + - + - - + + - - + + - + - - + - + - - - - - - - + + + + + + + - - + + - + - - + + - + - - - - + + + + - + - + - + - + - + - + - + - + - - + + - - + + - + - - + + - + - - + + - - + + - + - + - - + + - + - - - + + + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - + - + - - + + - + - - - - - + + + + + - + - - - - - + + + + + - + - + - + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml index e5966cf62..340278d37 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml @@ -11,116 +11,116 @@ - + - - + + - - - + + + - + - - + + - + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - - - + + + - + - - + + - - + + - + - + - + - - + + - - + + - - + + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/core.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/core.xml new file mode 100644 index 000000000..c5aa432c9 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/core.xml @@ -0,0 +1,79 @@ + + + Core + core + *.core + text/x-core + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml index 6e370c763..5491fe464 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml @@ -191,7 +191,7 @@ - + @@ -320,4 +320,4 @@ - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml index a73c52cd9..261834f42 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml @@ -3,55 +3,66 @@ Docker docker dockerfile + containerfile Dockerfile Dockerfile.* *.Dockerfile *.docker + Containerfile + Containerfile.* + *.Containerfile text/x-dockerfile-config true - + - - + + - + - - + + - - - + + + - - + + - + - - + + + + + + + - + - + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml index 64e667dd7..9723fd9c2 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml @@ -7,143 +7,125 @@ - - - + - - - + - - - + - - - + - - + + - + - - - - + + - + - + - - + + - + - + - - - - + + - - - + - - - + - - - + - - + + - - - + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml index 09c638a94..ec02c4ef1 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml @@ -3,6 +3,7 @@ Kotlin kotlin *.kt + *.kts text/x-kotlin true diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lox.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lox.xml new file mode 100644 index 000000000..602885a20 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lox.xml @@ -0,0 +1,83 @@ + + + lox + *.lox + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonscript.xml new file mode 100644 index 000000000..293f538cd --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonscript.xml @@ -0,0 +1,83 @@ + + + + MoonScript + moonscript + moon + *.moon + text/x-moonscript + application/x-moonscript + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml new file mode 100644 index 000000000..326558086 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml @@ -0,0 +1,121 @@ + + + Nu + nu + *.nu + text/plain + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml index 12af64b9d..0b7213121 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml @@ -31,12 +31,9 @@ - - - - - - + + + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpgle.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpgle.xml new file mode 100644 index 000000000..a74f3c66f --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpgle.xml @@ -0,0 +1,176 @@ + + + RPGLE + SQLRPGLE + RPG IV + *.RPGLE + *.rpgle + *.SQLRPGLE + *.sqlrpgle + text/x-rpgle + text/x-sqlrpgle + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml index 2209aa77f..fd77d083f 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml @@ -1,3 +1,4 @@ + Sed @@ -10,19 +11,82 @@ - - - - - - - - - - - None - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml index 2a746de34..f8df6be2a 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml @@ -12,131 +12,138 @@ - - + + - + - + - + - - + + - - + + - + - + - - + + - + - + - + - + - + - - - + + - + - + - + - + - - + + - - + + - - + + - + - + - - + + - + - + - + - + - + - + - - - - + + + + - - - + + + - - + + - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml index 9c98ba534..87bd19df4 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml @@ -5,6 +5,7 @@ *.toml Pipfile poetry.lock + uv.lock text/x-toml diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml index 7d541cb6c..a3e3be239 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml @@ -15,280 +15,287 @@ - - + + - - + + - + - - - + + + - - + + - + - - - - + + + + - + - + - + - + - - + + - + - + - - - + + + - + - + - + - - - + + + - + - + - - + + - + - + - - + + - + - + - - + + - - + + - + - + - - + + - + - + - - + + - - + + - - + + - + - - + + - + - + - - + + - - + + - + - + - - + + - + - - + + - - + + - + - - - + + + - - + + - - + + - + - - + + - - - - + + + + - + - + - + - - + + + - + - - + + - - - + + + - + - + - + - + - + - + - - + + - + diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml index 858e9f8e1..6f17bcafc 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml @@ -3,6 +3,7 @@ Zig zig *.zig + *.zon text/zig diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/gemtext.go b/vendor/github.com/alecthomas/chroma/v2/lexers/gemtext.go new file mode 100644 index 000000000..2fed8d62f --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/gemtext.go @@ -0,0 +1,37 @@ +package lexers + +import ( + . "github.com/alecthomas/chroma/v2" // nolint +) + +// Gemtext lexer. +var Gemtext = Register(MustNewLexer( + &Config{ + Name: "Gemtext", + Aliases: []string{"gemtext", "gmi", "gmni", "gemini"}, + Filenames: []string{"*.gmi", "*.gmni", "*.gemini"}, + MimeTypes: []string{"text/gemini"}, + }, + gemtextRules, +)) + +func gemtextRules() Rules { + return Rules{ + "root": { + {`^(#[^#].+\r?\n)`, ByGroups(GenericHeading), nil}, + {`^(#{2,3}.+\r?\n)`, ByGroups(GenericSubheading), nil}, + {`^(\* )(.+\r?\n)`, ByGroups(Keyword, Text), nil}, + {`^(>)(.+\r?\n)`, ByGroups(Keyword, GenericEmph), nil}, + {"^(```\\r?\\n)([\\w\\W]*?)(^```)(.+\\r?\\n)?", ByGroups(String, Text, String, Comment), nil}, + { + "^(```)(\\w+)(\\r?\\n)([\\w\\W]*?)(^```)(.+\\r?\\n)?", + UsingByGroup(2, 4, String, String, String, Text, String, Comment), + nil, + }, + {"^(```)(.+\\r?\\n)([\\w\\W]*?)(^```)(.+\\r?\\n)?", ByGroups(String, String, Text, String, Comment), nil}, + {`^(=>)(\s*)([^\s]+)(\s*)$`, ByGroups(Keyword, Text, NameAttribute, Text), nil}, + {`^(=>)(\s*)([^\s]+)(\s+)(.+)$`, ByGroups(Keyword, Text, NameAttribute, Text, NameTag), nil}, + {`(.|(?:\r?\n))`, ByGroups(Text), nil}, + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/go.go b/vendor/github.com/alecthomas/chroma/v2/lexers/go.go index 60b1f7119..c6123b907 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/go.go +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/go.go @@ -28,10 +28,10 @@ var Go = Register(MustNewLexer( func goRules() Rules { return Rules{ "root": { - {`\n`, Text, nil}, - {`\s+`, Text, nil}, - {`\\\n`, Text, nil}, - {`//[^\n\r]*`, CommentSingle, nil}, + {`\n`, TextWhitespace, nil}, + {`\s+`, TextWhitespace, nil}, + {`//[^\s][^\n\r]*`, CommentPreproc, nil}, + {`//\s+[^\n\r]*`, CommentSingle, nil}, {`/(\\\n)?[*](.|\n)*?[*](\\\n)?/`, CommentMultiline, nil}, {`(import|package)\b`, KeywordNamespace, nil}, {`(var|func|struct|map|chan|type|interface|const)\b`, KeywordDeclaration, nil}, diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go b/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go index db5a89484..bcd5b1784 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go @@ -5,7 +5,7 @@ import ( ) // Markdown lexer. -var Markdown = Register(DelegatingLexer(HTML, MustNewLexer( +var Markdown = Register(MustNewLexer( &Config{ Name: "markdown", Aliases: []string{"md", "mkd"}, @@ -13,7 +13,7 @@ var Markdown = Register(DelegatingLexer(HTML, MustNewLexer( MimeTypes: []string{"text/x-markdown"}, }, markdownRules, -))) +)) func markdownRules() Rules { return Rules{ @@ -40,7 +40,7 @@ func markdownRules() Rules { {"`[^`]+`", LiteralStringBacktick, nil}, {`[@#][\w/:]+`, NameEntity, nil}, {`(!?\[)([^]]+)(\])(\()([^)]+)(\))`, ByGroups(Text, NameTag, Text, Text, NameAttribute, Text), nil}, - {`.|\n`, Other, nil}, + {`.|\n`, Text, nil}, }, } } diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go b/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go index 49e03a4d5..da354dce6 100644 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go +++ b/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go @@ -2,6 +2,7 @@ package lexers import ( "regexp" + "slices" "strings" "unicode/utf8" @@ -1318,16 +1319,6 @@ func indexAt(str []rune, substr []rune, pos int) int { return idx } -// Tells if an array of string contains a string -func contains(s []string, e string) bool { - for _, value := range s { - if value == e { - return true - } - } - return false -} - type rulePosition int const ( @@ -1625,15 +1616,15 @@ func quote(groups []string, state *LexerState) Iterator { var tokenState string switch { - case keyword == "qq" || contains(tokenStates, "qq"): + case keyword == "qq" || slices.Contains(tokenStates, "qq"): tokenState = "qq" - case adverbsStr == "ww" || contains(tokenStates, "ww"): + case adverbsStr == "ww" || slices.Contains(tokenStates, "ww"): tokenState = "ww" - case contains(tokenStates, "Q-closure") && contains(tokenStates, "Q-variable"): + case slices.Contains(tokenStates, "Q-closure") && slices.Contains(tokenStates, "Q-variable"): tokenState = "qq" - case contains(tokenStates, "Q-closure"): + case slices.Contains(tokenStates, "Q-closure"): tokenState = "Q-closure" - case contains(tokenStates, "Q-variable"): + case slices.Contains(tokenStates, "Q-variable"): tokenState = "Q-variable" default: tokenState = "Q" diff --git a/vendor/github.com/alecthomas/chroma/v2/regexp.go b/vendor/github.com/alecthomas/chroma/v2/regexp.go index e1ee4299e..c0e5e1081 100644 --- a/vendor/github.com/alecthomas/chroma/v2/regexp.go +++ b/vendor/github.com/alecthomas/chroma/v2/regexp.go @@ -1,6 +1,7 @@ package chroma import ( + "encoding/json" "fmt" "os" "path/filepath" @@ -135,11 +136,20 @@ func NewLexer(config *Config, rulesFunc func() Rules) (*RegexLexer, error) { } // Trace enables debug tracing. +// +// Deprecated: Use SetTracing instead. func (r *RegexLexer) Trace(trace bool) *RegexLexer { r.trace = trace return r } +// SetTracing enables debug tracing. +// +// This complies with the [TracingLexer] interface. +func (r *RegexLexer) SetTracing(trace bool) { + r.trace = trace +} + // A CompiledRule is a Rule with a pre-compiled regex. // // Note that regular expressions are lazily compiled on first use of the lexer. @@ -185,6 +195,7 @@ func (l *LexerState) Get(key interface{}) interface{} { // Iterator returns the next Token from the lexer. func (l *LexerState) Iterator() Token { // nolint: gocognit + trace := json.NewEncoder(os.Stderr) end := len(l.Text) if l.newlineAdded { end-- @@ -205,14 +216,33 @@ func (l *LexerState) Iterator() Token { // nolint: gocognit } l.State = l.Stack[len(l.Stack)-1] - if l.Lexer.trace { - fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q\n", l.State, l.Pos, string(l.Text[l.Pos:])) - } selectedRule, ok := l.Rules[l.State] if !ok { panic("unknown state " + l.State) } + var start time.Time + if l.Lexer.trace { + start = time.Now() + } ruleIndex, rule, groups, namedGroups := matchRules(l.Text, l.Pos, selectedRule) + if l.Lexer.trace { + var length int + if groups != nil { + length = len(groups[0]) + } else { + length = -1 + } + _ = trace.Encode(Trace{ //nolint + Lexer: l.Lexer.config.Name, + State: l.State, + Rule: ruleIndex, + Pattern: rule.Pattern, + Pos: l.Pos, + Length: length, + Elapsed: float64(time.Since(start)) / float64(time.Millisecond), + }) + // fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q, elapsed=%s\n", l.State, l.Pos, string(l.Text[l.Pos:]), time.Since(start)) + } // No match. if groups == nil { // From Pygments :\ @@ -366,6 +396,17 @@ restart: } } } + // Validate emitters + for state := range r.rules { + for i := range len(r.rules[state]) { + rule := r.rules[state][i] + if validate, ok := rule.Type.(ValidatingEmitter); ok { + if err := validate.ValidateEmitter(rule); err != nil { + return fmt.Errorf("%s: %s: %s: %w", r.config.Name, state, rule.Pattern, err) + } + } + } + } r.compiled = true return nil } diff --git a/vendor/github.com/alecthomas/chroma/v2/renovate.json5 b/vendor/github.com/alecthomas/chroma/v2/renovate.json5 index 77c7b016c..9ade48124 100644 --- a/vendor/github.com/alecthomas/chroma/v2/renovate.json5 +++ b/vendor/github.com/alecthomas/chroma/v2/renovate.json5 @@ -1,18 +1,24 @@ { - $schema: "https://docs.renovatebot.com/renovate-schema.json", - extends: [ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ "config:recommended", ":semanticCommits", ":semanticCommitTypeAll(chore)", ":semanticCommitScope(deps)", "group:allNonMajor", "schedule:earlyMondays", // Run once a week. + 'helpers:pinGitHubActionDigests', ], - packageRules: [ + "packageRules": [ { - matchPackageNames: ["golangci-lint"], - matchManagers: ["hermit"], - enabled: false, + "matchPackageNames": ["golangci-lint"], + "matchManagers": ["hermit"], + "enabled": false }, - ], + { + "matchPackageNames": ["github.com/gorilla/csrf"], + "matchManagers": ["gomod"], + "enabled": false + } + ] } diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml index 0adf1ba9e..66a361fb7 100644 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml +++ b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml @@ -65,12 +65,12 @@ - + - + @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml index 3ea767fd4..c87c8765d 100644 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml +++ b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml @@ -65,12 +65,12 @@ - + - + @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml index 6b5002848..5dba9c647 100644 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml +++ b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml @@ -65,12 +65,12 @@ - + - + @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml index 9a401912f..9f9b9152a 100644 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml +++ b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml @@ -65,12 +65,12 @@ - + - + @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/rpgle.xml b/vendor/github.com/alecthomas/chroma/v2/styles/rpgle.xml new file mode 100644 index 000000000..678fd70fa --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/v2/styles/rpgle.xml @@ -0,0 +1,30 @@ + diff --git a/vendor/github.com/alfatraining/structtag/LICENSE b/vendor/github.com/alfatraining/structtag/LICENSE new file mode 100644 index 000000000..4fd15f9f8 --- /dev/null +++ b/vendor/github.com/alfatraining/structtag/LICENSE @@ -0,0 +1,60 @@ +Copyright (c) 2017, Fatih Arslan +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 structtag 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 HOLDER 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. + +This software includes some portions from Go. Go is used under the terms of the +BSD like license. + +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The Go gopher was designed by Renee French. http://reneefrench.blogspot.com/ The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher diff --git a/vendor/github.com/alfatraining/structtag/README.md b/vendor/github.com/alfatraining/structtag/README.md new file mode 100644 index 000000000..4d0094bec --- /dev/null +++ b/vendor/github.com/alfatraining/structtag/README.md @@ -0,0 +1,92 @@ +# structtag [![](https://github.com/alfatraining/structtag/workflows/build/badge.svg)](https://github.com/alfatraining/structtag/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/alfatraining/structtag)](https://pkg.go.dev/github.com/alfatraining/structtag) + +`structtag` is a library for parsing struct tags in Go during static analysis. +It is designed to provide a simple API for parsing struct field tags in Go code. +This fork focuses exclusively on **reading struct tags** and is not intended for modifying or rewriting them. +It also drops support for accessing the options of a struct tag individually. + +This project is a fork of [`fatih/structtag`](https://github.com/fatih/structtag), originally created by Fatih Arslan. +The primary changes in this fork are: + +- struct tag values are treated as blobs, options are not treated individually, +- the API surface is minimized, just so that the functionality used by [`4meepo/tagalign`](https://github.com/4meepo/tagalign) is provided. + +--- + +## Install + +To install the package: + +```bash +go get github.com/alfatraining/structtag +``` + +--- + +## Example Usage + +The following example demonstrates how to parse and output struct tags using `structtag`: + +```go +package main + +import ( + "fmt" + "reflect" + + "github.com/alfatraining/structtag" +) + +func main() { + type Example struct { + Field string `json:"foo,omitempty" xml:"bar"` + } + + // Get the struct tag from the field + tag := reflect.TypeOf(Example{}).Field(0).Tag + + // Parse the tag using structtag + tags, err := structtag.Parse(string(tag)) + if err != nil { + panic(err) + } + + // Iterate over all tags + for _, t := range tags.Tags() { + fmt.Printf("Key: %s, Value: %v\n", t.Key, t.Value) + } + // Output: + // Key: json, Value: foo,omitempty + // Key: xml, Value: bar +} +``` + +--- + +## API Overview + +### Parsing Struct Tags +Use `Parse` to parse a struct field's tag into a `Tags` object: +```go +tags, err := structtag.Parse(`json:"foo,omitempty" xml:"bar"`) +if err != nil { + panic(err) +} +``` + +### Accessing Tags +- **Retrieve all tags**: + ```go + allTags := tags.Tags() + ``` + +### Inspecting Tags +- **Key**: The key of the tag (e.g., `json` or `xml`). +- **Value**: The value of the tag (e.g., `"foo,omitempty"` for `json:"foo,omitempty"`). + +--- + +## Acknowledgments + +This project is based on [`fatih/structtag`](https://github.com/fatih/structtag), created by Fatih Arslan. +Inspiration for the style of this README was taken from [tylergannon/structtag](https://github.com/tylergannon/structtag), created by Tyler Gannon. diff --git a/vendor/github.com/alfatraining/structtag/tags.go b/vendor/github.com/alfatraining/structtag/tags.go new file mode 100644 index 000000000..227df3c2f --- /dev/null +++ b/vendor/github.com/alfatraining/structtag/tags.go @@ -0,0 +1,138 @@ +package structtag + +import ( + "bytes" + "errors" + "fmt" + "strconv" +) + +var ( + errTagSyntax = errors.New("bad syntax for struct tag pair") + errTagKeySyntax = errors.New("bad syntax for struct tag key") + errTagValueSyntax = errors.New("bad syntax for struct tag value") +) + +// Tags represent a set of tags from a single struct field +type Tags struct { + tags []*Tag +} + +// Tag defines a single struct's string literal tag +type Tag struct { + // Key is the tag key, such as json, xml, etc. + // i.e: `json:"foo,omitempty". Here key is: "json" + Key string + + // Value is the value stored for this tag key. + // i.e.: `json:"foo,omitempty". Here the value is: "foo,omitempty". + Value string +} + +// Parse parses a single struct field tag and returns the set of tags. +func Parse(tag string) (*Tags, error) { + var tags []*Tag + + hasTag := tag != "" + + // NOTE(arslan) following code is from reflect and vet package with some + // modifications to collect all necessary information and extend it with + // usable methods + for tag != "" { + // Skip leading space. + i := 0 + for i < len(tag) && tag[i] == ' ' { + i++ + } + tag = tag[i:] + if tag == "" { + break + } + + // Scan to colon. A space, a quote or a control character is a syntax error. + // Strictly speaking, control chars include the range [0x7f, 0x9f], not just + // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters + // as it is simpler to inspect the tag's bytes than the tag's runes. + i = 0 + for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f { + i++ + } + + if i == 0 { + return nil, errTagKeySyntax + } + if i+1 >= len(tag) || tag[i] != ':' { + return nil, errTagSyntax + } + if tag[i+1] != '"' { + return nil, errTagValueSyntax + } + + key := tag[:i] + tag = tag[i+1:] + + // Scan quoted string to find value. + i = 1 + for i < len(tag) && tag[i] != '"' { + if tag[i] == '\\' { + i++ + } + i++ + } + if i >= len(tag) { + return nil, errTagValueSyntax + } + + qvalue := tag[:i+1] + tag = tag[i+1:] + + value, err := strconv.Unquote(qvalue) + if err != nil { + return nil, errTagValueSyntax + } + + tags = append(tags, &Tag{ + Key: key, + Value: value, + }) + } + + if hasTag && len(tags) == 0 { + return nil, nil + } + + return &Tags{ + tags: tags, + }, nil +} + +// Tags returns a slice of tags. The order is the original tag order. +func (t *Tags) Tags() []*Tag { + return t.tags +} + +// String reassembles the tags into a valid literal tag field representation +func (t *Tags) String() string { + tags := t.Tags() + if len(tags) == 0 { + return "" + } + + var buf bytes.Buffer + for i, tag := range t.Tags() { + buf.WriteString(tag.String()) + if i != len(tags)-1 { + buf.WriteString(" ") + } + } + return buf.String() +} + +// String reassembles the tag into a valid tag field representation +func (t *Tag) String() string { + return fmt.Sprintf(`%s:%q`, t.Key, t.Value) +} + +func (t *Tags) Len() int { + return len(t.tags) +} diff --git a/vendor/github.com/ashanbrown/forbidigo/LICENSE b/vendor/github.com/ashanbrown/forbidigo/v2/LICENSE similarity index 100% rename from vendor/github.com/ashanbrown/forbidigo/LICENSE rename to vendor/github.com/ashanbrown/forbidigo/v2/LICENSE diff --git a/vendor/github.com/ashanbrown/forbidigo/forbidigo/config_options.go b/vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/config_options.go similarity index 100% rename from vendor/github.com/ashanbrown/forbidigo/forbidigo/config_options.go rename to vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/config_options.go diff --git a/vendor/github.com/ashanbrown/forbidigo/forbidigo/forbidigo.go b/vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/forbidigo.go similarity index 94% rename from vendor/github.com/ashanbrown/forbidigo/forbidigo/forbidigo.go rename to vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/forbidigo.go index a7a3ab591..913b45e95 100644 --- a/vendor/github.com/ashanbrown/forbidigo/forbidigo/forbidigo.go +++ b/vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/forbidigo.go @@ -317,13 +317,15 @@ func (v *visitor) expandMatchText(node ast.Node, srcText string) (matchTexts []s // type. We don't care about the value. selectorText := v.textFor(node) if typeAndValue, ok := v.runConfig.TypesInfo.Types[selector]; ok { - m, p, ok := typeNameWithPackage(typeAndValue.Type) - if !ok { - v.runConfig.DebugLog("%s: selector %q with supported type %T", location, selectorText, typeAndValue.Type) + if typeName, pkgPath, ok := typeNameWithPackage(typeAndValue.Type); ok { + v.runConfig.DebugLog("%s: selector %q with supported type %q: %q -> %q, package %q", location, selectorText, typeAndValue.Type.String(), srcText, matchTexts, pkgPath) + matchTexts = []string{typeName + "." + field} + pkgText = pkgPath + } else { + // handle cases such as anonymous structs + v.runConfig.DebugLog("%s: selector %q with unknown type %T", location, selectorText, typeAndValue.Type) + matchTexts = []string{} } - matchTexts = []string{m + "." + field} - pkgText = p - v.runConfig.DebugLog("%s: selector %q with supported type %q: %q -> %q, package %q", location, selectorText, typeAndValue.Type.String(), srcText, matchTexts, pkgText) } // Some expressions need special treatment. switch selector := selector.(type) { @@ -340,7 +342,9 @@ func (v *visitor) expandMatchText(node ast.Node, srcText string) (matchTexts []s pkgText = packageName v.runConfig.DebugLog("%s: selector %q is variable of type %q: %q -> %q, package %q", location, selectorText, object.Type().String(), srcText, matchTexts, pkgText) } else { + // handle cases such as anonymous structs v.runConfig.DebugLog("%s: selector %q is variable with unsupported type %T", location, selectorText, object.Type()) + matchTexts = []string{} } default: // Something else? @@ -370,11 +374,14 @@ func typeNameWithPackage(t types.Type) (typeName, packagePath string, ok bool) { } switch t := t.(type) { + case *types.Alias: + return typeNameWithPackage(t.Rhs()) case *types.Named: obj := t.Obj() pkg := obj.Pkg() + // we either lack a package or the package is the "universe" (i.e. builtin) if pkg == nil { - return "", "", false + return obj.Name(), "", true } return pkg.Name() + "." + obj.Name(), pkg.Path(), true default: diff --git a/vendor/github.com/ashanbrown/forbidigo/forbidigo/patterns.go b/vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/patterns.go similarity index 79% rename from vendor/github.com/ashanbrown/forbidigo/forbidigo/patterns.go rename to vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/patterns.go index 2692dcd24..5f05cec94 100644 --- a/vendor/github.com/ashanbrown/forbidigo/forbidigo/patterns.go +++ b/vendor/github.com/ashanbrown/forbidigo/v2/forbidigo/patterns.go @@ -1,12 +1,14 @@ package forbidigo import ( + "bytes" "fmt" + "io" "regexp" "regexp/syntax" "strings" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) // pattern matches code that is not supposed to be used. @@ -33,15 +35,15 @@ type pattern struct { // patterns). type yamlPattern pattern -func (p *yamlPattern) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (p *yamlPattern) UnmarshalYAML(value *yaml.Node) error { // Try struct first. It's unlikely that a regular expression string // is valid YAML for a struct. var ptrn pattern - if err := unmarshal(&ptrn); err != nil { + if err := unmarshalStrict(&ptrn, value); err != nil && err != io.EOF { errStr := err.Error() // Didn't work, try plain string. var ptrn string - if err := unmarshal(&ptrn); err != nil { + if err := unmarshalStrict(&ptrn, value); err != nil && err != io.EOF { return fmt.Errorf("pattern is neither a regular expression string (%s) nor a Pattern struct (%s)", err.Error(), errStr) } p.Pattern = ptrn @@ -51,6 +53,20 @@ func (p *yamlPattern) UnmarshalYAML(unmarshal func(interface{}) error) error { return ((*pattern)(p)).validate() } +// unmarshalStrict implements missing yaml.UnmarshalStrict in gopkg.in/yaml.v3. +// See https://github.com/go-yaml/yaml/issues/639. +// Inspired by https://github.com/ffenix113/zigbee_home/pull/68 +func unmarshalStrict(to any, node *yaml.Node) error { + buf := &bytes.Buffer{} + if err := yaml.NewEncoder(buf).Encode(node); err != nil { + return err + } + + decoder := yaml.NewDecoder(buf) + decoder.KnownFields(true) + return decoder.Decode(to) +} + var _ yaml.Unmarshaler = &yamlPattern{} // parse accepts a regular expression or, if the string starts with { or contains a line break, a @@ -61,7 +77,9 @@ func parse(ptrn string) (*pattern, error) { if strings.HasPrefix(strings.TrimSpace(ptrn), "{") || strings.Contains(ptrn, "\n") { // Embedded JSON or YAML. We can decode both with the YAML decoder. - if err := yaml.UnmarshalStrict([]byte(ptrn), pattern); err != nil { + decoder := yaml.NewDecoder(strings.NewReader(ptrn)) + decoder.KnownFields(true) + if err := decoder.Decode(pattern); err != nil && err != io.EOF { return nil, fmt.Errorf("parsing as JSON or YAML failed: %v", err) } } else { diff --git a/vendor/github.com/ashanbrown/makezero/LICENSE b/vendor/github.com/ashanbrown/makezero/v2/LICENSE similarity index 100% rename from vendor/github.com/ashanbrown/makezero/LICENSE rename to vendor/github.com/ashanbrown/makezero/v2/LICENSE diff --git a/vendor/github.com/ashanbrown/makezero/makezero/makezero.go b/vendor/github.com/ashanbrown/makezero/v2/makezero/makezero.go similarity index 100% rename from vendor/github.com/ashanbrown/makezero/makezero/makezero.go rename to vendor/github.com/ashanbrown/makezero/v2/makezero/makezero.go diff --git a/vendor/github.com/bombsimon/wsl/v5/.gitignore b/vendor/github.com/bombsimon/wsl/v5/.gitignore new file mode 100644 index 000000000..1c8eba613 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/.gitignore @@ -0,0 +1,70 @@ + +# Created by https://www.gitignore.io/api/go,vim,macos + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +### Go Patch ### +/vendor/ +/Godeps/ + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + + +# End of https://www.gitignore.io/api/go,vim,macos diff --git a/vendor/github.com/bombsimon/wsl/v5/.golangci.yml b/vendor/github.com/bombsimon/wsl/v5/.golangci.yml new file mode 100644 index 000000000..f97571f8e --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/.golangci.yml @@ -0,0 +1,83 @@ +--- +version: "2" + +output: + formats: + text: + path: stdout + print-issued-lines: false + +linters: + default: all + disable: + - cyclop + - depguard + - dupl + - dupword + - err113 + - exhaustruct + - forbidigo + - funlen + - gocognit + - gocyclo + - godot + - godox + - lll + - maintidx + - mnd + - nakedret + - nestif + - nlreturn + - noinlineerr + - paralleltest + - prealloc + - rowserrcheck + - tagliatelle + - testpackage + - tparallel + - varnamelen + - wastedassign + - wsl + + settings: + depguard: + rules: + main: + deny: + - pkg: github.com/davecgh/go-spew/spew + desc: not allowed + gocognit: + min-complexity: 10 + gocritic: + # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` + # to see all tags and checks. Empty list by default. See + # https://github.com/go-critic/go-critic#usage -> section "Tags". + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + misspell: + locale: US + + exclusions: + presets: + - comments + - common-false-positives + - std-error-handling + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 +formatters: + enable: + - gofmt + - gofumpt + - goimports + settings: + gofmt: + rewrite-rules: + - pattern: "interface{}" + replacement: "any" +# vim: set sw=2 ts=2 et: diff --git a/vendor/github.com/bombsimon/wsl/v5/CHECKS.md b/vendor/github.com/bombsimon/wsl/v5/CHECKS.md new file mode 100644 index 000000000..e630a8311 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/CHECKS.md @@ -0,0 +1,1316 @@ +# Checks + +This document describes all the checks done by `wsl` with examples of what's not +allowed and what's allowed. + +## `assign` + +Assign (`foo := bar`) or re-assignments (`foo = bar`) should only be cuddled +with other assignments or increment/decrement. + + + + + + + +
BadGood
+ +```go +if true { + fmt.Println("hello") +} +a := 1 // 1 + +defer func() { + fmt.Println("hello") +}() +a := 1 // 2 +``` + + + +```go +if true { + fmt.Println("hello") +} + +a := 1 + +defer func() { + fmt.Println("hello") +}() + +a := 1 + +a := 1 +b := 2 +c := 3 +``` + +
+ +1 Not an assign statement above + +2 Not an assign statement above + + + +
+ +## `branch` + +> Configurable via `branch-max-lines` + +Branch statement (`break`, `continue`, `fallthrough`, `goto`) should only be +cuddled if the block is less than `n` lines where `n` is the value of +`branch-max-statements`. + + + + + + + +
BadGood
+ +```go +for { + a, err : = SomeFn() + if err != nil { + return err + } + + fmt.Println(a) + break // 1 +} +``` + + + +```go +for { + a, err : = SomeFn() + if err != nil { + return err + } + + fmt.Println(a) + + break +} + +for { + fmt.Println("hello") + break +} +``` + +
+ +1 Block is more than 2 lines so should be a blank line above + + + +
+ +## `decl` + +Declarations should never be cuddled. When grouping multiple declarations +together they should be declared in the same group with parenthesis into a +single statement. The benefit of this is that it also aligns the declaration or +assignment increasing readability. + +> **NOTE** The fixer can't do smart adjustments if there are comments on the +> same line as the declaration. + + + + + + + +
BadGood
+ +```go +var a string +var b int // 1 + +const a = 1 +const b = 2 // 2 + +a := 1 +var b string // 3 + +fmt.Println("hello") +var a string // 4 +``` + + + +```go +var ( + a string + b int +) + +const ( + a = 1 + b = 2 +) + +a := 1 + +var b string + +fmt.Println("hello") + +var a string +``` + +
+ +1 Multiple declarations should be grouped to one + +2 Multiple declarations should be grouped to one + +3 Declaration should always have a whitespace above + +4 Declaration should always have a whitespace above + + + +
+ +## `defer` + +Deferring execution should only be used directly in the context of what's being +deferred and there should only be one statement above. + + + + + + + +
BadGood
+ +```go +val, closeFn := SomeFn() +val2 := fmt.Sprintf("v-%s", val) +fmt.Println(val) +defer closeFn() // 1 + +defer fn1() +a := 1 +defer fn3() // 2 + +f, err := os.Open("/path/to/f.txt") +if err != nil { + return err +} + +lines := ReadFile(f) +trimLines(lines) +defer f.Close() // 3 +``` + + + +```go +val, closeFn := SomeFn() +defer closeFn() + +defer fn1() +defer fn2() +defer fn3() + +f, err := os.Open("/path/to/f.txt") +if err != nil { + return err +} +defer f.Close() + +m.Lock() +defer m.Unlock() +``` + +
+ +1 More than a single statement between `defer` and `closeFn` + +2 `a` is not used in expression + +3 More than a single statement between `defer` and `f.Close` + + + +
+ +## `expr` + +Expressions can be multiple things and a big part of them are not handled by +`wsl`. However all function calls are expressions which can be verified. + + + + + + + +
BadGood
+ +```go +a := 1 +b := 2 +fmt.Println("not b") // 1 +``` + + + +```go +a := 1 +b := 2 + +fmt.Println("not b") + +a := 1 +fmt.Println(a) +``` + +
+ +1 `b` is not used in expression + + + +
+ +## `for` + +> Configurable via `allow-first-in-block` to allow cuddling if the variable is +> used _first_ in the block (enabled by default). +> +> Configurable via `allow-whole-block` to allow cuddling if the variable is used +> _anywhere_ in the following block (disabled by default). +> +> See [Configuration](#configuration) for details. + + + + + + + +
BadGood
+ +```go +i := 0 +for j := 0; j < 3; j++ { // 1 + fmt.Println(j) +} + +a := 0 +i := 3 +for j := 0; j < i; j++ { // 2 + fmt.Println(j) +} + +x := 1 +for { // 3 + fmt.Println("hello") + break +} +``` + + + +```go +i := 0 +for j := 0; j < i; j++ { + fmt.Println(j) +} + +a := 0 + +i := 3 +for j := 0; j < i; j++ { + fmt.Println(j) +} + +// Allowed with `allow-first-in-block` +x := 1 +for { + x++ + break +} + +// Allowed with `allow-whole-block` +x := 1 +for { + fmt.Println("hello") + + if shouldIncrement() { + x++ + } +} +``` + +
+ +1 `i` is not used in expression + +2 More than one variable above statement + +3 No variable in expression + + + +
+ +## `go` + + + + + + + +
BadGood
+ +```go +someFunc := func() {} +go anotherFunc() // 1 + +x := 1 +go func () // 2 + fmt.Println(y) +}() + +someArg := 1 +go Fn(notArg) // 3 +``` + + + +```go +someFunc := func() {} +go someFunc() + +x := 1 +go func (s string) { + fmt.Println(s) +}(x) + +someArg := 1 +go Fn(someArg) +``` + +
+ +1 `someFunc` is not used in expression + +2 `x` is not used in expression + +3 `someArg` is not used in expression + + + +
+ +## `if` + +> Configurable via `allow-first-in-block` to allow cuddling if the variable is +> used _first_ in the block (enabled by default). +> +> Configurable via `allow-whole-block` to allow cuddling if the variable is used +> _anywhere_ in the following block (disabled by default). +> +> See [Configuration](#configuration) for details. + +`if` statements are one of several block statements (a statement with a block) +that can have some form of expression or condition. To make block context more +readable, only one variable is allowed immediately above the `if` statement and +the variable must be used in the condition (unless configured otherwise). + + + + + + + +
BadGood
+ +```go +x := 1 +if y > 1 { // 1 + fmt.Println("y > 1") +} + +a := 1 +b := 2 +if b > 1 { // 2 + fmt.Println("a > 1") +} + +a := 1 +b := 2 +if a > 1 { // 3 + fmt.Println("a > 1") +} + +a := 1 +b := 2 +if notEvenAOrB() { // 4 + fmt.Println("not a or b") +} + +a := 1 +x, err := SomeFn() // 5 +if err != nil { + return err +} +``` + + + +```go +x := 1 + +if y > 1 { + fmt.Println("y > 1") +} + +a := 1 + +b := 2 +if b > 1 { + fmt.Println("a > 1") +} + +b := 2 + +a := 1 +if a > 1 { + fmt.Println("a > b") +} + +a := 1 +b := 2 + +if notEvenAOrB() { + fmt.Println("not a or b") +} + +a := 1 + +x, err := SomeFn() +if err != nil { + return err +} + +// Allowed with `allow-first-in-block` +x := 1 +if xUsedFirstInBlock() { + x = 2 +} + +// Allowed with `allow-whole-block` +x := 1 +if xUsedLaterInBlock() { + fmt.Println("will use x later") + + if orEvenNestedWouldWork() { + x = 3 + } +} +``` + +
+ +1 `x` is not used in expression + +2 More than one variable above statement + +3 `b` is not used in expression and too many statements + +4 No variable in expression + +5 More than one variable above statement + + + +
+ +## `inc-dec` + + + + + + + +
BadGood
+ +```go +i := 1 + +if true { + fmt.Println("hello") +} +i++ // 1 + +defer func() { + fmt.Println("hello") +}() +i++ // 2 +``` + + + +```go +i := 1 +i++ + +i-- +j := i +j++ +``` + +
+ +1 Not an assign or inc/dec statement above + +2 Not an assign or inc/dec statement above + + + +
+ +## `label` + +Labels should never be cuddled. Labels in itself is often a symptom of big scope +and split context and because of that should always have an empty line above. + + + + + + + +
BadGood
+ +```go +L1: + if true { + _ = 1 + } +L2: // 1 + if true { + _ = 1 + } +``` + + + +```go +L1: + if true { + _ = 1 + } + +L2: + if true { + _ = 1 + } +``` + +
+ +1 Labels should always have a whitespabe above + + + +
+ +## `range` + +> Configurable via `allow-first-in-block` to allow cuddling if the variable is +> used _first_ in the block (enabled by default). +> +> Configurable via `allow-whole-block` to allow cuddling if the variable is used +> _anywhere_ in the following block (disabled by default). +> +> See [Configuration](#configuration) for details. + + + + + + + +
BadGood
+ +```go +someRange := []int{1, 2, 3} +for _, i := range thisIsNotSomeRange { // 1 + fmt.Println(i) +} + +x := 1 +for i := range make([]int, 3) { // 2 + fmt.Println("hello") + break +} + +s1 := []int{1, 2, 3} +s2 := []int{3, 2, 1} +for _, v := range s2 { // 3 + fmt.Println(v) +} +``` + + + +```go +someRange := []int{1, 2, 3} + +for _, i := range thisIsNotSomeRange { + fmt.Println(i) +} + +someRange := []int{1, 2, 3} +for _, i := range someRange { + fmt.Println(i) +} + +notARange := 1 +for i := range returnsRange(notARange) { + fmt.Println(i) +} + +s1 := []int{1, 2, 3} + +s2 := []int{3, 2, 1} +for _, v := range s2 { + fmt.Println(v) +} +``` + +
+ +1 `someRange` is not used in expression + +2 `x` is not used in expression + +3 More than one variable above statement + + + +
+ +## `return` + +> Configurable via `branch-max-lines` + +Return statements is an important statement that is easiy to miss in larger code +blocks. To better visualize the `return` statement and that the method is +returning it should always be followed by a blank line unless the scope is as +small as `branch-max-lines`. + + + + + + + +
BadGood
+ +```go +func Fn() int { + x, err := someFn() + if err != nil { + panic(err) + } + + fmt.Println(x) + return // 1 +} +``` + + + +```go +func Fn() int { + x, err := someFn() + if err != nil { + panic(err) + } + + fmt.Println(x) + + return +} +``` + +
+ +1 Block is more than 2 lines so should be a blank line above + + + +
+ +## `select` + +Identifiers used in case arms of select statements are allowed to be cuddled. + +> Configurable via `allow-first-in-block` to allow cuddling if the variable is +> used _first_ in the block (enabled by default). +> +> Configurable via `allow-whole-block` to allow cuddling if the variable is used +> _anywhere_ in the following block (disabled by default). +> +> See [Configuration](#configuration) for details. + + + + + + + +
BadGood
+ +```go +x := 0 +select { // 1 +case <-time.After(time.Second): + // ... +case <-stop: + // ... +} +``` + + + +```go +stop := make(chan struct{}) +select { +case <-time.After(time.Second): + // ... +case <-stop: + // ... +} + +x := 0 + +select { +case <-time.After(time.Second): + // ... +case <-stop: + // ... +} + +// Allowed with `allow-whole-block` +x := 1 +select { +case <-time.After(time.Second): + // ... +case <-stop: + Fn(x) +} +``` + +
+ +1 `x` is not used in expression + + + +
+ +## `send` + +Send statements should only be cuddled with a single variable that is used on +the line above. + + + + + + + +
BadGood
+ +```go +a := 1 +ch <- 1 // 1 + +b := 2 +<-ch // 2 +``` + + + +```go +a := 1 +ch <- a + +b := 1 + +<-ch +``` + +
+ +1 `a` is not used in expression + +2 `b` is not used in expression + + + +
+ +## `switch` + +In addition to checking the switch condition, switch statements also checks +identifiers in all case arms. If a variable is used in one or more of the case +arms it's allowed to be cuddled. + +> Configurable via `allow-first-in-block` to allow cuddling if the variable is +> used _first_ in the block (enabled by default). +> +> Configurable via `allow-whole-block` to allow cuddling if the variable is used +> _anywhere_ in the following block (disabled by default). +> +> See [Configuration](#configuration) for details. + + + + + + + +
BadGood
+ +```go +x := 0 +switch y { // 1 +case 1: + // ... +case 2: + // ... +} + + +x := 0 +y := 1 +switch y { // 2 +case 1: + // ... +case 2: + // ... +} +``` + + + +```go +n := 1 +switch n { +case 1: + // ... +case 2: + // ... +} + +n := 1 +switch { +case n < 1: + // ... +case n > 1: + // ... +} + +x := 0 + +switch y { +case 1: + // ... +case 2: + // ... +} + + +x := 0 + +y := 1 +switch y { +case 1: + // ... +case 2: + // ... +} + +// Allowed with `allow-whole-block` +x := 1 +switch y { +case 1: + // ... +case 2: + fmt.Println(x) +} +``` + +
+ +1 `x` is not used in expression + +2 More than one variable above statement + + + +
+ +## `type-switch` + +> Configurable via `allow-first-in-block` to allow cuddling if the variable is +> used _first_ in the block (enabled by default). +> +> Configurable via `allow-whole-block` to allow cuddling if the variable is used +> _anywhere_ in the following block (disabled by default). +> +> See [Configuration](#configuration) for details. + + + + + + + +
BadGood
+ +```go +x := someType() +switch y.(type) { // 1 +case int32: + // ... +case int64: + // ... +} + + +x := 0 +y := someType() +switch y.(type) { +case int32: + // ... +case int64: + // ... +} +``` + + + +```go +x := someType() + +switch y.(type) { +case int32: + // ... +case int64: + // ... +} + + +x := 0 + +y := someType() +switch y.(type) { +case int32: + // ... +case int64: + // ... +} + +// Allowed with `allow-whole-block` +x := 1 +switch y.(type) { +case int32: + // ... +case int64: + fmt.Println(x) +} +``` + +
+ +1 `x` is not used in expression + + + +
+ +## `append` + +Append enables strict `append` checking where assignments that are +re-assignments with `append` (e.g. `x = append(x, y)`) is only allowed to be +cuddled with other assignments if the `append` uses the variable on the line +above. + + + + + + + +
BadGood
+ +```go +s := []string{} + +a := 1 +s = append(s, 2) // 1 +b := 3 +s = append(s, a) // 2 +``` + + + +```go +s := []string{} + +a := 1 +s = append(s, a) + +b := 3 + +s = append(s, 2) +``` + +
+ +1 `a` is not used in append + +2 `b` is not used in append + + + +
+ +## `assign-exclusive` + +Assign exclusive does not allow mixing new assignments (`:=`) with +re-assignments (`=`). + + + + + + + +
BadGood
+ +```go +a := 1 +b = 2 // 1 +c := 3 // 2 +d = 4 // 3 +``` + + + +```go +a := 1 +c := 3 + +b = 2 +d = 4 +``` + +
+ +1 `a` is not a re-assignment + +2 `b` is not a new assignment + +3 `c` is not a re-assignment + + + +
+ +## `assign-expr` + +Assignments are allowed to be cuddled with expressions, primarily to support +mixing assignments and function calls which can often make sense in shorter +flows. By enabling this check `wsl` will ensure assignments are not cuddled with +expressions. + + + + + + + +
BadGood
+ +```go +t1.Fn1() +x := t1.Fn2() // 1 +t1.Fn3() +``` + + + +```go +t1.Fn1() + +x := t1.Fn2() +t1.Fn3() +``` + +
+ +1 Line above is not an assignment + + + +
+ +## `err` + + + + + + + +
BadGood
+ +```go +_, err := SomeFn() + +if err != nil { // 1 + return fmt.Errorf("failed to fn: %w", err) +} +``` + + + +```go +_, err := SomeFn() +if err != nil { + return fmt.Errorf("failed to fn: %w", err) +} +``` + +
+ +1 Whitespace between error assignment and error checking + + + +
+ +## `leading-whitespace` + + + + + + +
BadGood
+ +```go +if true { + + fmt.Println("hello") +} +``` + + + +```go +if true { + fmt.Println("hello") +} +``` + +
+ +## `trailing-whitespace` + + + + + + +
BadGood
+ +```go +if true { + fmt.Println("hello") + +} +``` + + + +```go +if true { + fmt.Println("hello") +} +``` + +
+ +## Configuration + +One shared logic across different checks is the logic around statements +containing a block, i.e. a statement with a following `{}` (e.g. `if`, `for`, +`switch` etc). + +`wsl` only allows one statement immediately above and that statement must also +be referenced in the expression in the statement with the block. E.g. + +```go +someVariable := true +if someVariable { + // Here `someVariable` used in the `if` expression is the only variable + // immediately above the statement. +} +``` + +This can be configured to be more "laxed" by also allowing a single statement +immediately above if it's used either first in the following block or anywhere +inside the following block. + +### `allow-first-in-block` + +By setting this to true (default), the variable doesn't have to be used in the +expression itself but is also allowed if it's the first statement in the block +body. + +```go +someVariable := 1 +if anotherVariable { + someVariable++ +} +``` + +### `allow-whole-block` + +This is similar to `allow-first-in-block` but now allows the lack of whitespace +if it's used anywhere in the following block. + +```go +someVariable := 1 +if anotherVariable { + someFn(yetAnotherVariable) + + if stillNotSomeVariable { + someVariable++ + } +} +``` diff --git a/vendor/github.com/bombsimon/wsl/v5/LICENSE b/vendor/github.com/bombsimon/wsl/v5/LICENSE new file mode 100644 index 000000000..f881b648e --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 - 2025 Simon Sawert + +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/vendor/github.com/bombsimon/wsl/v5/README.md b/vendor/github.com/bombsimon/wsl/v5/README.md new file mode 100644 index 000000000..449e88710 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/README.md @@ -0,0 +1,183 @@ +# wsl - whitespace linter + +[![GitHub Actions](https://github.com/bombsimon/wsl/actions/workflows/go.yml/badge.svg)](https://github.com/bombsimon/wsl/actions/workflows/go.yml) +[![Coverage Status](https://coveralls.io/repos/github/bombsimon/wsl/badge.svg?branch=main)](https://coveralls.io/github/bombsimon/wsl?branch=main) + +`wsl` (**w**hite**s**pace **l**inter) is a linter that wants you to use empty +lines to separate grouping of different types to increase readability. There are +also a few places where it encourages you to _remove_ whitespaces which is at +the start and the end of blocks or between assigning and error checking. + +## Checks and configuration + +Each check can be disabled or enabled individually to the point where no checks +can be run. The idea with this is to attract more users. Some checks have +configuration that affect how they work but most of them can only be turned on +or off. + +### Checks + +This is an exhaustive list of all the checks that can be enabled or disabled and +their default value. The names are the same as the Go +[AST](https://pkg.go.dev/go/ast) type name for built-ins. + +The base rule is that statements that has a block (e.g. `for`, `range`, +`switch`, `if` etc) should always only be directly adjacent with a single +variable and only if it's used in the expression in the block itself. + +For more details and examples, see [CHECKS](CHECKS.md). + +✅ = enabled by default, ❌ = disabled by default + +#### Built-ins and keywords + +- ✅ **assign** - Assignments should only be cuddled with other assignments, + or increment/decrement +- ✅ **branch** - Branch statement (`break`, `continue`, `fallthrough`, `goto`) + should only be cuddled if the block is less than `n` lines where `n` is the + value of [`branch-max-lines`](#configuration) +- ✅ **decl** - Declarations should never be cuddled +- ✅ **defer** - Defer should only be cuddled with other `defer`, after error + checking or with a single variable used on the line above +- ✅ **expr** - Expressions are e.g. function calls or index expressions, they + should only be cuddled with variables used on the line above +- ✅ **for** - For loops should only be cuddled with a single variable used on + the line above +- ✅ **go** - Go should only be cuddled with other `go` or a single variable + used on the line above +- ✅ **if** - If should only be cuddled with a single variable used on the line + above +- ✅ **inc-dec** - Increment/decrement (`++/--`) has the same rules as `assign` +- ✅ **label** - Labels should never be cuddled +- ✅ **range** - Range should only be cuddled with a single variable used on the + line above +- ✅ **return** - Return should only be cuddled if the block is less than `n` + lines where `n` is the value of [`branch-max-lines`](#configuration) +- ✅ **select** - Select should only be cuddled with a single variable used on + the line above +- ✅ **send** - Send should only be cuddled with a single variable used on the + line above +- ✅ **switch** - Switch should only be cuddled with a single variable used on + the line above +- ✅ **type-switch** - Type switch should only be cuddled with a single variable + used on the line above + +#### Specific `wsl` cases + +- ✅ **append** - Only allow re-assigning with `append` if the value being + appended exist on the line above +- ❌ **assign-exclusive** - Only allow cuddling either new variables or + re-assigning of existing ones +- ❌ **assign-expr** - Don't allow assignments to be cuddled with expressions, + e.g. function calls +- ✅ **err** - Error checking must follow immediately after the error variable + is assigned +- ✅ **leading-whitespace** - Disallow leading empty lines in blocks +- ✅ **trailing-whitespace** - Disallow trailing empty lines in blocks + +### Configuration + +Other than enabling or disabling specific checks some checks can be configured +in more details. + +- ✅ **allow-first-in-block** - Allow cuddling a variable if it's used first in + the immediate following block, even if the statement with the block doesn't + use the variable (see [Configuration](CHECKS.md#allow-first-in-block) for + details) +- ❌ **allow-whole-block** - Same as above, but allows cuddling if the variable + is used _anywhere_ in the following (or nested) block (see + [Configuration](CHECKS.md#allow-whole-block) for details) +- **branch-max-lines** - If a block contains more than this number of lines the + branch statement (e.g. `return`, `break`, `continue`) need to be separated by + a whitespace (default 2) +- **case-max-lines** - If set to a non negative number, `case` blocks needs to + end with a whitespace if exceeding this number (default 0, 0 = off, 1 = + always) +- ❌ **include-generated** - Include generated files when checking + +## Installation + +```sh +# Latest release +go install github.com/bombsimon/wsl/v5/cmd/wsl@latest + +# Main branch +go install github.com/bombsimon/wsl/v5/cmd/wsl@main +``` + +## Usage + +> **Note**: This linter provides a fixer that can fix most issues with the +> `--fix` flag. + +`wsl` uses the [analysis] package meaning it will operate on package level with +the default analysis flags and way of working. + +```sh +wsl --help +wsl [flags] + +wsl --default none --enable branch,return --fix ./... +``` + +`wsl` is also integrated in [`golangci-lint`][golangci-lint] but since v5 which +had a bunch of breaking changes it's renamed to `wsl_v5`. The previous version +of `wsl` is deprecated and will be removed from `golangci-lint` eventually. + +```sh +golangci-lint run --no-config --enable-only wsl_v5 --fix +``` + +This is an exhaustive, default, configuration for `wsl_v5` in `golangci-lint`. + +```yaml +linters: + default: none + enable: + - wsl_v5 + + settings: + wsl_v5: + allow-first-in-block: true + allow-whole-block: false + branch-max-lines: 2 + case-max-lines: 0 + default: ~ # Can be `all`, `none`, `default` or empty + enable: + - append + - assign + - branch + - decl + - defer + - err + - expr + - for + - go + - if + - inc-dec + - label + - range + - return + - select + - send + - switch + - type-switch + - leading-whitespace + - trailing-whitespace + disable: + - assign-exclusive + - assign-expr +``` + +## See also + +- [`nlreturn`][nlreturn] - Use empty lines before `return` +- [`whitespace`][whitespace] - Don't use a blank newline at the start or end of + a block. +- [`gofumpt`][gofumpt] - Stricter formatter than `gofmt`. + + [analysis]: https://pkg.go.dev/golang.org/x/tools/go/analysis + [gofumpt]: https://github.com/mvdan/gofumpt + [golangci-lint]: https://golangci-lint.run + [nlreturn]: https://github.com/ssgreg/nlreturn + [whitespace]: https://github.com/ultraware/whitespace diff --git a/vendor/github.com/bombsimon/wsl/v5/analyzer.go b/vendor/github.com/bombsimon/wsl/v5/analyzer.go new file mode 100644 index 000000000..38a84973f --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/analyzer.go @@ -0,0 +1,198 @@ +package wsl + +import ( + "flag" + "fmt" + "go/ast" + "go/token" + "os" + "strings" + "sync" + + "golang.org/x/tools/go/analysis" +) + +const version = "wsl version v5.3.0" + +func NewAnalyzer(config *Configuration) *analysis.Analyzer { + wa := &wslAnalyzer{config: config} + + return &analysis.Analyzer{ + Name: "wsl", + Doc: "add or remove empty lines", + Flags: wa.flags(), + Run: wa.run, + RunDespiteErrors: true, + } +} + +// wslAnalyzer is a wrapper around the configuration which is used to be able to +// set the configuration when creating the analyzer and later be able to update +// flags and running method. +type wslAnalyzer struct { + config *Configuration + + // When we use flags, we need to parse the ones used for checks into + // temporary variables so we can create the check set once the flag is being + // parsed by the analyzer and we run our analyzer. + defaultChecks string + enable []string + disable []string + + // To only validate and convert the parsed flags once we use a `sync.Once` + // to only create a check set once and store the set and potential error. We + // also store if we actually had a configuration to ensure we don't + // overwrite the checks if the analyzer was created with a proper wsl + // config. + cfgOnce sync.Once + didHaveConfig bool + checkSetErr error +} + +func (wa *wslAnalyzer) flags() flag.FlagSet { + flags := flag.NewFlagSet("wsl", flag.ExitOnError) + + if wa.config != nil { + wa.didHaveConfig = true + return *flags + } + + wa.config = NewConfig() + + flags.BoolVar(&wa.config.IncludeGenerated, "include-generated", false, "Include generated files") + flags.BoolVar(&wa.config.AllowFirstInBlock, "allow-first-in-block", true, "Allow cuddling if variable is used in the first statement in the block") + flags.BoolVar(&wa.config.AllowWholeBlock, "allow-whole-block", false, "Allow cuddling if variable is used anywhere in the block") + flags.IntVar(&wa.config.BranchMaxLines, "branch-max-lines", 2, "Max lines before requiring newline before branching, e.g. `return`, `break`, `continue` (0 = never)") + flags.IntVar(&wa.config.CaseMaxLines, "case-max-lines", 0, "Max lines before requiring a newline at the end of case (0 = never)") + + flags.StringVar(&wa.defaultChecks, "default", "", "Can be 'all' for all checks or 'none' for no checks or empty for default checks") + flags.Var(&multiStringValue{slicePtr: &wa.enable}, "enable", "Comma separated list of checks to enable") + flags.Var(&multiStringValue{slicePtr: &wa.disable}, "disable", "Comma separated list of checks to disable") + flags.Var(new(versionFlag), "V", "print version and exit") + + return *flags +} + +func (wa *wslAnalyzer) run(pass *analysis.Pass) (any, error) { + wa.cfgOnce.Do(func() { + // No need to update checks if config was passed when creating the + // analyzer. + if wa.didHaveConfig { + return + } + + // Parse the check params once if we set our config from flags. + wa.config.Checks, wa.checkSetErr = NewCheckSet(wa.defaultChecks, wa.enable, wa.disable) + }) + + if wa.checkSetErr != nil { + return nil, wa.checkSetErr + } + + for _, file := range pass.Files { + filename := getFilename(pass.Fset, file) + if !strings.HasSuffix(filename, ".go") { + continue + } + + // if the file is related to cgo the filename of the unadjusted position + // is a not a '.go' file. + unadjustedFilename := pass.Fset.PositionFor(file.Pos(), false).Filename + + // if the file is related to cgo the filename of the unadjusted position + // is a not a '.go' file. + if !strings.HasSuffix(unadjustedFilename, ".go") { + continue + } + + // The file is skipped if the "unadjusted" file is a Go file, and it's a + // generated file (ex: "_test.go" file). The other non-Go files are + // skipped by the first 'if' with the adjusted position. + if !wa.config.IncludeGenerated && ast.IsGenerated(file) { + continue + } + + wsl := New(file, pass, wa.config) + wsl.Run() + + for pos, fix := range wsl.issues { + textEdits := []analysis.TextEdit{} + + for _, f := range fix.fixRanges { + textEdits = append(textEdits, analysis.TextEdit{ + Pos: f.fixRangeStart, + End: f.fixRangeEnd, + NewText: f.fix, + }) + } + + pass.Report(analysis.Diagnostic{ + Pos: pos, + Category: "whitespace", + Message: fix.message, + SuggestedFixes: []analysis.SuggestedFix{ + { + TextEdits: textEdits, + }, + }, + }) + } + } + + //nolint:nilnil // A pass don't need to return anything. + return nil, nil +} + +// multiStringValue is a flag that supports multiple values. It's implemented to +// contain a pointer to a string slice that will be overwritten when the flag's +// `Set` method is called. +type multiStringValue struct { + slicePtr *[]string +} + +// Set implements the flag.Value interface and will overwrite the pointer to +// the +// slice with a new pointer after splitting the flag by comma. +func (m *multiStringValue) Set(value string) error { + var s []string + + for _, v := range strings.Split(value, ",") { + s = append(s, strings.TrimSpace(v)) + } + + *m.slicePtr = s + + return nil +} + +// String implements the flag.Value interface. +func (m *multiStringValue) String() string { + if m.slicePtr == nil { + return "" + } + + return strings.Join(*m.slicePtr, ", ") +} + +// https://cs.opensource.google/go/x/tools/+/refs/tags/v0.35.0:go/analysis/internal/analysisflags/flags.go;l=188-237;drc=99337ebe7b90918701a41932abf121600b972e34 +type versionFlag string + +func (*versionFlag) IsBoolFlag() bool { return true } +func (*versionFlag) Get() any { return nil } +func (*versionFlag) String() string { return "" } + +func (*versionFlag) Set(_ string) error { + fmt.Println(version) + os.Exit(0) + + return nil +} + +func getFilename(fset *token.FileSet, file *ast.File) string { + filename := fset.PositionFor(file.Pos(), true).Filename + if !strings.HasSuffix(filename, ".go") { + return fset.PositionFor(file.Pos(), false).Filename + } + + return filename +} diff --git a/vendor/github.com/bombsimon/wsl/v5/config.go b/vendor/github.com/bombsimon/wsl/v5/config.go new file mode 100644 index 000000000..7bed5ef42 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/config.go @@ -0,0 +1,279 @@ +package wsl + +import ( + "fmt" + "strings" +) + +// CheckSet is a set of checks to run. +type CheckSet map[CheckType]struct{} + +// CheckType is a type that represents a checker to run. +type CheckType int + +// Each checker is represented by a CheckType that is used to enable or disable +// the check. +// A check can either be of a specific built-in keyword or custom checks. +const ( + CheckInvalid CheckType = iota + CheckAssign + CheckBranch + CheckDecl + CheckDefer + CheckExpr + CheckFor + CheckGo + CheckIf + CheckIncDec + CheckLabel + CheckRange + CheckReturn + CheckSelect + CheckSend + CheckSwitch + CheckTypeSwitch + + // Check append only allows assignments of `append` to be cuddled with other + // assignments if it's a variable used in the append statement, e.g. + // + // a := 1 + // x = append(x, a) + // . + CheckAppend + // Assign exclusive only allows assignments of either new variables or + // re-assignment of existing ones, e.g. + // + // a := 1 + // b := 2 + // + // a = 1 + // b = 2 + // . + CheckAssignExclusive + // CheckAssignExpr will check so assignments are not cuddled with expression + // nodes, e.g. + // + // t1.Fn1() + // + // x := t1.Fn2() + // t1.Fn3() + // . + CheckAssignExpr + // Force error checking to follow immediately after an error variable is + // assigned, e.g. + // + // _, err := someFn() + // if err != nil { + // panic(err) + // } + // . + CheckErr + CheckLeadingWhitespace + CheckTrailingWhitespace + + // CheckTypes only used for reporting. + CheckCaseTrailingNewline +) + +func (c CheckType) String() string { + return [...]string{ + "invalid", + "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", + // + "case-trailing-newline", + }[c] +} + +type Configuration struct { + IncludeGenerated bool + AllowFirstInBlock bool + AllowWholeBlock bool + BranchMaxLines int + CaseMaxLines int + Checks CheckSet +} + +func NewConfig() *Configuration { + return &Configuration{ + IncludeGenerated: false, + AllowFirstInBlock: true, + AllowWholeBlock: false, + CaseMaxLines: 0, + BranchMaxLines: 2, + Checks: DefaultChecks(), + } +} + +func NewWithChecks( + defaultChecks string, + enable []string, + disable []string, +) (*Configuration, error) { + checks, err := NewCheckSet(defaultChecks, enable, disable) + if err != nil { + return nil, fmt.Errorf("failed to create config: %w", err) + } + + cfg := NewConfig() + cfg.Checks = checks + + return cfg, nil +} + +func NewCheckSet( + defaultChecks string, + enable []string, + disable []string, +) (CheckSet, error) { + var cs CheckSet + + switch strings.ToLower(defaultChecks) { + case "", "default": + cs = DefaultChecks() + case "all": + cs = AllChecks() + case "none": + cs = NoChecks() + default: + return nil, fmt.Errorf("invalid preset '%s', must be `all`, `none` or `` (empty)", defaultChecks) + } + + for _, s := range enable { + check, err := CheckFromString(s) + if err != nil { + return nil, fmt.Errorf("invalid check '%s'", s) + } + + cs.Add(check) + } + + for _, s := range disable { + check, err := CheckFromString(s) + if err != nil { + return nil, fmt.Errorf("invalid check '%s'", s) + } + + cs.Remove(check) + } + + return cs, nil +} + +func DefaultChecks() CheckSet { + return CheckSet{ + CheckAppend: {}, + CheckAssign: {}, + CheckBranch: {}, + CheckDecl: {}, + CheckDefer: {}, + CheckErr: {}, + CheckExpr: {}, + CheckFor: {}, + CheckGo: {}, + CheckIf: {}, + CheckIncDec: {}, + CheckLabel: {}, + CheckLeadingWhitespace: {}, + CheckTrailingWhitespace: {}, + CheckRange: {}, + CheckReturn: {}, + CheckSelect: {}, + CheckSend: {}, + CheckSwitch: {}, + CheckTypeSwitch: {}, + } +} + +func AllChecks() CheckSet { + c := DefaultChecks() + c.Add(CheckAssignExclusive) + c.Add(CheckAssignExpr) + + return c +} + +func NoChecks() CheckSet { + return CheckSet{} +} + +func (c CheckSet) Add(check CheckType) { + c[check] = struct{}{} +} + +func (c CheckSet) Remove(check CheckType) { + delete(c, check) +} + +func CheckFromString(s string) (CheckType, error) { + switch strings.ToLower(s) { + case "assign": + return CheckAssign, nil + case "branch": + return CheckBranch, nil + case "decl": + return CheckDecl, nil + case "defer": + return CheckDefer, nil + case "expr": + return CheckExpr, nil + case "for": + return CheckFor, nil + case "go": + return CheckGo, nil + case "if": + return CheckIf, nil + case "inc-dec": + return CheckIncDec, nil + case "label": + return CheckLabel, nil + case "range": + return CheckRange, nil + case "return": + return CheckReturn, nil + case "select": + return CheckSelect, nil + case "send": + return CheckSend, nil + case "switch": + return CheckSwitch, nil + case "type-switch": + return CheckTypeSwitch, nil + + case "append": + return CheckAppend, nil + case "assign-exclusive": + return CheckAssignExclusive, nil + case "assign-expr": + return CheckAssignExpr, nil + case "err": + return CheckErr, nil + case "leading-whitespace": + return CheckLeadingWhitespace, nil + case "trailing-whitespace": + return CheckTrailingWhitespace, nil + default: + return CheckInvalid, fmt.Errorf("invalid check '%s'", s) + } +} diff --git a/vendor/github.com/bombsimon/wsl/v5/cursor.go b/vendor/github.com/bombsimon/wsl/v5/cursor.go new file mode 100644 index 000000000..0d275829f --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/cursor.go @@ -0,0 +1,88 @@ +package wsl + +import ( + "go/ast" +) + +// Cursor holds a list of statements and a pointer to where in the list we are. +// Each block gets a new cursor and can be used to check previous or coming +// statements. +type Cursor struct { + currentIdx int + statements []ast.Stmt + checkType CheckType +} + +// NewCursor creates a new cursor with a given list of statements. +func NewCursor(statements []ast.Stmt) *Cursor { + return &Cursor{ + currentIdx: -1, + statements: statements, + } +} + +func (c *Cursor) SetChecker(ct CheckType) { + c.checkType = ct +} + +func (c *Cursor) NextNode() ast.Node { + defer c.Save()() + + var nextNode ast.Node + if c.Next() { + nextNode = c.Stmt() + } + + return nextNode +} + +func (c *Cursor) Next() bool { + if c.currentIdx >= len(c.statements)-1 { + return false + } + + c.currentIdx++ + + return true +} + +func (c *Cursor) Previous() bool { + if c.currentIdx <= 0 { + return false + } + + c.currentIdx-- + + return true +} + +func (c *Cursor) PreviousNode() ast.Node { + defer c.Save()() + + var previousNode ast.Node + if c.Previous() { + previousNode = c.Stmt() + } + + return previousNode +} + +func (c *Cursor) Stmt() ast.Stmt { + return c.statements[c.currentIdx] +} + +func (c *Cursor) Save() func() { + idx := c.currentIdx + + return func() { + c.currentIdx = idx + } +} + +func (c *Cursor) Len() int { + return len(c.statements) +} + +func (c *Cursor) Nth(n int) ast.Stmt { + return c.statements[n] +} diff --git a/vendor/github.com/bombsimon/wsl/v5/wsl.go b/vendor/github.com/bombsimon/wsl/v5/wsl.go new file mode 100644 index 000000000..9bf62c2ae --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v5/wsl.go @@ -0,0 +1,1464 @@ +package wsl + +import ( + "bytes" + "fmt" + "go/ast" + "go/format" + "go/token" + "go/types" + + "golang.org/x/tools/go/analysis" +) + +const ( + messageMissingWhitespaceAbove = "missing whitespace above this line" + messageMissingWhitespaceBelow = "missing whitespace below this line" + messageRemoveWhitespace = "unnecessary whitespace" +) + +type fixRange struct { + fixRangeStart token.Pos + fixRangeEnd token.Pos + fix []byte +} + +type issue struct { + message string + // We can report multiple fixes at the same position. This happens e.g. when + // we force error cuddling but the error assignment is already cuddled. + // See `checkError` for examples. + fixRanges []fixRange +} + +type WSL struct { + file *ast.File + fset *token.FileSet + typeInfo *types.Info + issues map[token.Pos]issue + config *Configuration + groupedDecls map[token.Pos]struct{} +} + +func New(file *ast.File, pass *analysis.Pass, cfg *Configuration) *WSL { + return &WSL{ + fset: pass.Fset, + file: file, + typeInfo: pass.TypesInfo, + issues: make(map[token.Pos]issue), + config: cfg, + groupedDecls: make(map[token.Pos]struct{}), + } +} + +// Run will run analysis on the file and pass passed to the constructor. It's +// typically only supposed to be used by [analysis.Analyzer]. +func (w *WSL) Run() { + for _, decl := range w.file.Decls { + if funcDecl, ok := decl.(*ast.FuncDecl); ok { + w.checkFunc(funcDecl) + } + } +} + +func (w *WSL) checkStmt(stmt ast.Stmt, cursor *Cursor) { + //nolint:gocritic // This is not commented out code, it's examples + switch s := stmt.(type) { + // if a {} else if b {} else {} + case *ast.IfStmt: + w.checkIf(s, cursor, false) + // for {} / for a; b; c {} + case *ast.ForStmt: + w.checkFor(s, cursor) + // for _, _ = range a {} + case *ast.RangeStmt: + w.checkRange(s, cursor) + // switch {} // switch a {} + case *ast.SwitchStmt: + w.checkSwitch(s, cursor) + // switch a.(type) {} + case *ast.TypeSwitchStmt: + w.checkTypeSwitch(s, cursor) + // return a + case *ast.ReturnStmt: + w.checkReturn(s, cursor) + // continue / break + case *ast.BranchStmt: + w.checkBranch(s, cursor) + // var a + case *ast.DeclStmt: + w.checkDeclStmt(s, cursor) + // a := a + case *ast.AssignStmt: + w.checkAssign(s, cursor) + // a++ / a-- + case *ast.IncDecStmt: + w.checkIncDec(s, cursor) + // defer func() {} + case *ast.DeferStmt: + w.checkDefer(s, cursor) + // go func() {} + case *ast.GoStmt: + w.checkGo(s, cursor) + // e.g. someFn() + case *ast.ExprStmt: + w.checkExprStmt(s, cursor) + // case: + case *ast.CaseClause: + w.checkCaseClause(s, cursor) + // case: + case *ast.CommClause: + w.checkCommClause(s, cursor) + // { } + case *ast.BlockStmt: + w.checkBlock(s) + // select { } + case *ast.SelectStmt: + w.checkSelect(s, cursor) + // ch <- ... + case *ast.SendStmt: + w.checkSend(s, cursor) + // LABEL: + case *ast.LabeledStmt: + w.checkLabel(s, cursor) + case *ast.EmptyStmt: + default: + } +} + +//nolint:unparam // False positive on `cursor` +func (w *WSL) checkExpr(expr ast.Expr, cursor *Cursor) { + // This switch traverses all possible subexpressions in search + // of anonymous functions, no matter how unlikely or perhaps even + // semantically impossible it is. + switch s := expr.(type) { + case *ast.FuncLit: + w.checkBlock(s.Body) + case *ast.CallExpr: + w.checkExpr(s.Fun, cursor) + + for _, e := range s.Args { + w.checkExpr(e, cursor) + } + case *ast.StarExpr: + w.checkExpr(s.X, cursor) + case *ast.CompositeLit: + w.checkExpr(s.Type, cursor) + + for _, e := range s.Elts { + w.checkExpr(e, cursor) + } + case *ast.KeyValueExpr: + w.checkExpr(s.Key, cursor) + w.checkExpr(s.Value, cursor) + case *ast.ArrayType: + w.checkExpr(s.Elt, cursor) + w.checkExpr(s.Len, cursor) + case *ast.BasicLit: + case *ast.BinaryExpr: + w.checkExpr(s.X, cursor) + w.checkExpr(s.Y, cursor) + case *ast.ChanType: + w.checkExpr(s.Value, cursor) + case *ast.Ellipsis: + w.checkExpr(s.Elt, cursor) + case *ast.FuncType: + if params := s.TypeParams; params != nil { + for _, f := range params.List { + w.checkExpr(f.Type, cursor) + } + } + + if params := s.Params; params != nil { + for _, f := range params.List { + w.checkExpr(f.Type, cursor) + } + } + + if results := s.Results; results != nil { + for _, f := range results.List { + w.checkExpr(f.Type, cursor) + } + } + case *ast.Ident: + case *ast.IndexExpr: + w.checkExpr(s.Index, cursor) + w.checkExpr(s.X, cursor) + case *ast.IndexListExpr: + w.checkExpr(s.X, cursor) + + for _, e := range s.Indices { + w.checkExpr(e, cursor) + } + case *ast.InterfaceType: + for _, f := range s.Methods.List { + w.checkExpr(f.Type, cursor) + } + case *ast.MapType: + w.checkExpr(s.Key, cursor) + w.checkExpr(s.Value, cursor) + case *ast.ParenExpr: + w.checkExpr(s.X, cursor) + case *ast.SelectorExpr: + w.checkExpr(s.X, cursor) + case *ast.SliceExpr: + w.checkExpr(s.X, cursor) + w.checkExpr(s.Low, cursor) + w.checkExpr(s.High, cursor) + w.checkExpr(s.Max, cursor) + case *ast.StructType: + for _, f := range s.Fields.List { + w.checkExpr(f.Type, cursor) + } + case *ast.TypeAssertExpr: + w.checkExpr(s.X, cursor) + w.checkExpr(s.Type, cursor) + case *ast.UnaryExpr: + w.checkExpr(s.X, cursor) + case nil: + default: + } +} + +func (w *WSL) checkDecl(decl ast.Decl, cursor *Cursor) { + switch d := decl.(type) { + case *ast.GenDecl: + for _, spec := range d.Specs { + w.checkSpec(spec, cursor) + } + case *ast.FuncDecl: + w.checkStmt(d.Body, cursor) + case *ast.BadDecl: + default: + } +} + +func (w *WSL) checkSpec(spec ast.Spec, cursor *Cursor) { + switch s := spec.(type) { + case *ast.ValueSpec: + for _, expr := range s.Values { + w.checkExpr(expr, cursor) + } + case *ast.ImportSpec, *ast.TypeSpec: + default: + } +} + +func (w *WSL) checkBody(body []ast.Stmt) { + cursor := NewCursor(body) + + for cursor.Next() { + w.checkStmt(cursor.Stmt(), cursor) + } +} + +func (w *WSL) checkCuddlingBlock( + stmt ast.Node, + blockList []ast.Stmt, + allowedIdents []*ast.Ident, + cursor *Cursor, + maxAllowedStatements int, +) { + var firstBlockStmt ast.Node + if len(blockList) > 0 { + firstBlockStmt = blockList[0] + } + + w.checkCuddlingMaxAllowed(stmt, firstBlockStmt, allowedIdents, cursor, maxAllowedStatements) +} + +func (w *WSL) checkCuddling(stmt ast.Node, cursor *Cursor, maxAllowedStatements int) { + w.checkCuddlingMaxAllowed(stmt, nil, []*ast.Ident{}, cursor, maxAllowedStatements) +} + +func (w *WSL) checkCuddlingMaxAllowed( + stmt ast.Node, + firstBlockStmt ast.Node, + allowedIdents []*ast.Ident, + cursor *Cursor, + maxAllowedStatements int, +) { + if _, ok := cursor.Stmt().(*ast.LabeledStmt); ok { + return + } + + previousNode := cursor.PreviousNode() + + if previousNode != nil { + if _, ok := w.groupedDecls[previousNode.End()]; ok { + w.addErrorTooManyStatements(cursor.Stmt().Pos(), cursor.checkType) + return + } + } + + numStmtsAbove := w.numberOfStatementsAbove(cursor) + previousIdents := w.identsFromNode(previousNode, true) + + // If we don't have any statements above, we only care about potential error + // cuddling (for if statements) so check that. + if numStmtsAbove == 0 { + w.checkError(numStmtsAbove, stmt, previousNode, cursor) + return + } + + nodeIsAssignDeclOrIncDec := func(n ast.Node) bool { + _, a := n.(*ast.AssignStmt) + _, d := n.(*ast.DeclStmt) + _, i := n.(*ast.IncDecStmt) + + return a || d || i + } + + _, currIsDefer := stmt.(*ast.DeferStmt) + + // We're cuddled but not with an assign, declare or defer statement which is + // never allowed. + if !nodeIsAssignDeclOrIncDec(previousNode) && !currIsDefer { + w.addErrorInvalidTypeCuddle(cursor.Stmt().Pos(), cursor.checkType) + return + } + + checkIntersection := func(other []*ast.Ident) bool { + anyIntersects := identIntersection(previousIdents, other) + if len(anyIntersects) > 0 { + // We have matches, but too many statements above. + if maxAllowedStatements != -1 && numStmtsAbove > maxAllowedStatements { + w.addErrorTooManyStatements(previousNode.Pos(), cursor.checkType) + } + + return true + } + + return false + } + + // FEATURE(AllowWholeBlock): Allow identifier used anywhere in block + // (including recursive blocks). + if w.config.AllowWholeBlock { + allIdentsInBlock := w.identsFromNode(stmt, false) + if checkIntersection(allIdentsInBlock) { + return + } + } + + // FEATURE(AllowFirstInBlock): Allow identifiers used first in block. + if !w.config.AllowWholeBlock && w.config.AllowFirstInBlock { + firstStmtIdents := w.identsFromNode(firstBlockStmt, true) + if checkIntersection(firstStmtIdents) { + return + } + } + + currentIdents := w.identsFromNode(stmt, true) + if checkIntersection(currentIdents) { + return + } + + if checkIntersection(allowedIdents) { + return + } + + intersects := identIntersection(currentIdents, previousIdents) + if len(intersects) > 0 { + return + } + + // We're cuddled but the line immediately above doesn't contain any + // variables used in this statement. + w.addErrorNoIntersection(stmt.Pos(), cursor.checkType) +} + +func (w *WSL) checkCuddlingWithoutIntersection(stmt ast.Node, cursor *Cursor) { + if w.numberOfStatementsAbove(cursor) == 0 { + return + } + + if _, ok := cursor.Stmt().(*ast.LabeledStmt); ok { + return + } + + previousNode := cursor.PreviousNode() + + currAssign, currIsAssign := stmt.(*ast.AssignStmt) + previousAssign, prevIsAssign := previousNode.(*ast.AssignStmt) + _, prevIsDecl := previousNode.(*ast.DeclStmt) + _, prevIsIncDec := previousNode.(*ast.IncDecStmt) + + // Cuddling without intersection is allowed for assignments and inc/dec + // statements. If however the check for declarations is disabled, we also + // allow cuddling with them as well. + // + // var x string + // x := "" + // y++ + if _, ok := w.config.Checks[CheckDecl]; ok { + prevIsDecl = false + } + + // If we enable exclusive assign checks we only allow new declarations or + // new assignments together but not mix and match. + // + // When this is enabled we also implicitly disable support to cuddle with + // anything else. + if _, ok := w.config.Checks[CheckAssignExclusive]; ok { + prevIsDecl = false + prevIsIncDec = false + + if prevIsAssign && currIsAssign { + prevIsAssign = previousAssign.Tok == currAssign.Tok + } + } + + prevIsValidType := previousNode == nil || prevIsAssign || prevIsDecl || prevIsIncDec + + if _, ok := w.config.Checks[CheckAssignExpr]; !ok { + if _, ok := previousNode.(*ast.ExprStmt); ok && w.hasIntersection(stmt, previousNode) { + prevIsValidType = prevIsValidType || ok + } + } + + if prevIsValidType { + return + } + + w.addErrorInvalidTypeCuddle(stmt.Pos(), cursor.checkType) +} + +func (w *WSL) checkBlock(block *ast.BlockStmt) { + w.checkBlockLeadingNewline(block) + w.checkTrailingNewline(block) + + w.checkBody(block.List) +} + +func (w *WSL) checkCaseClause(stmt *ast.CaseClause, cursor *Cursor) { + w.checkCaseLeadingNewline(stmt) + + if w.config.CaseMaxLines != 0 { + w.checkCaseTrailingNewline(stmt.Body, cursor) + } + + w.checkBody(stmt.Body) +} + +func (w *WSL) checkCommClause(stmt *ast.CommClause, cursor *Cursor) { + w.checkCommLeadingNewline(stmt) + + if w.config.CaseMaxLines != 0 { + w.checkCaseTrailingNewline(stmt.Body, cursor) + } + + w.checkBody(stmt.Body) +} + +func (w *WSL) checkFunc(funcDecl *ast.FuncDecl) { + if funcDecl.Body == nil { + return + } + + w.checkBlock(funcDecl.Body) +} + +func (w *WSL) checkAssign(stmt *ast.AssignStmt, cursor *Cursor) { + defer func() { + for _, expr := range stmt.Rhs { + w.checkExpr(expr, cursor) + } + + w.checkAppend(stmt, cursor) + }() + + if _, ok := w.config.Checks[CheckAssign]; !ok { + return + } + + cursor.SetChecker(CheckAssign) + + w.checkCuddlingWithoutIntersection(stmt, cursor) +} + +func (w *WSL) checkAppend(stmt *ast.AssignStmt, cursor *Cursor) { + if _, ok := w.config.Checks[CheckAppend]; !ok { + return + } + + if w.numberOfStatementsAbove(cursor) == 0 { + return + } + + previousNode := cursor.PreviousNode() + + var appendNode *ast.CallExpr + + for _, expr := range stmt.Rhs { + e, ok := expr.(*ast.CallExpr) + if !ok { + continue + } + + if f, ok := e.Fun.(*ast.Ident); ok && f.Name == "append" { + appendNode = e + break + } + } + + if appendNode == nil { + return + } + + if !w.hasIntersection(appendNode, previousNode) { + w.addErrorNoIntersection(stmt.Pos(), CheckAppend) + } +} + +func (w *WSL) checkBranch(stmt *ast.BranchStmt, cursor *Cursor) { + if _, ok := w.config.Checks[CheckBranch]; !ok { + return + } + + cursor.SetChecker(CheckBranch) + + if w.numberOfStatementsAbove(cursor) == 0 { + return + } + + lastStmtInBlock := cursor.statements[len(cursor.statements)-1] + firstStmts := cursor.Nth(0) + + if w.lineFor(lastStmtInBlock.End())-w.lineFor(firstStmts.Pos()) < w.config.BranchMaxLines { + return + } + + w.addErrorTooManyLines(stmt.Pos(), cursor.checkType) +} + +func (w *WSL) checkDeclStmt(stmt *ast.DeclStmt, cursor *Cursor) { + w.checkDecl(stmt.Decl, cursor) + + if _, ok := w.config.Checks[CheckDecl]; !ok { + return + } + + cursor.SetChecker(CheckDecl) + + if w.numberOfStatementsAbove(cursor) == 0 { + return + } + + // Try to do smart grouping and if we succeed return, otherwise do + // line-by-line fixing. + if w.maybeGroupDecl(stmt, cursor) { + return + } + + w.addErrorNeverAllow(stmt.Pos(), cursor.checkType) +} + +func (w *WSL) checkDefer(stmt *ast.DeferStmt, cursor *Cursor) { + w.maybeCheckExpr( + stmt, + stmt.Call, + cursor, + func(n ast.Node) (int, bool) { + _, previousIsDefer := n.(*ast.DeferStmt) + _, previousIsIf := n.(*ast.IfStmt) + + // We allow defer as a third node only if we have an if statement + // between, e.g. + // + // f, err := os.Open(file) + // if err != nil { + // return err + // } + // defer f.Close() + if previousIsIf && w.numberOfStatementsAbove(cursor) >= 2 { + defer cursor.Save()() + + cursor.Previous() + cursor.Previous() + + if w.hasIntersection(cursor.Stmt(), stmt) { + return 1, false + } + } + + // Only check cuddling if previous statement isn't also a defer. + return 1, !previousIsDefer + }, + CheckDefer, + ) +} + +func (w *WSL) checkError( + stmtsAbove int, + ifStmt ast.Node, + previousNode ast.Node, + cursor *Cursor, +) { + if _, ok := w.config.Checks[CheckErr]; !ok { + return + } + + if _, ok := cursor.Stmt().(*ast.LabeledStmt); ok { + return + } + + defer cursor.Save()() + + // It must be an if statement + stmt, ok := ifStmt.(*ast.IfStmt) + if !ok { + return + } + + // If we actually have statements above we can't possibly need to remove any + // empty lines. + if stmtsAbove > 0 { + return + } + + // If the error checking has an init condition (e.g. if err := f();) we + // don't want to check cuddling since the error is now assigned on this row. + if stmt.Init != nil { + return + } + + // The condition must be a binary expression (X OP Y) + binaryExpr, ok := stmt.Cond.(*ast.BinaryExpr) + if !ok { + return + } + + // We must do not equal or equal comparison (!= or ==) + if binaryExpr.Op != token.NEQ && binaryExpr.Op != token.EQL { + return + } + + xIdent, ok := binaryExpr.X.(*ast.Ident) + if !ok { + return + } + + // X is not an error so it's not error checking + if !w.implementsErr(xIdent) { + return + } + + yIdent, ok := binaryExpr.Y.(*ast.Ident) + if !ok { + return + } + + // Y is not compared with `nil` + if yIdent.Name != "nil" { + return + } + + previousIdents := []*ast.Ident{} + + if assign, ok := previousNode.(*ast.AssignStmt); ok { + for _, lhs := range assign.Lhs { + previousIdents = append(previousIdents, w.identsFromNode(lhs, true)...) + } + } + + if decl, ok := previousNode.(*ast.DeclStmt); ok { + if genDecl, ok := decl.Decl.(*ast.GenDecl); ok { + for _, spec := range genDecl.Specs { + if vs, ok := spec.(*ast.ValueSpec); ok { + previousIdents = append(previousIdents, vs.Names...) + } + } + } + } + + // Ensure that the error checked on this line was assigned or declared in + // the previous statement. + if len(identIntersection([]*ast.Ident{xIdent}, previousIdents)) == 0 { + return + } + + cursor.SetChecker(CheckErr) + + previousNodeEnd := previousNode.End() + + comments := ast.NewCommentMap(w.fset, previousNode, w.file.Comments) + for _, cg := range comments { + for _, c := range cg { + if c.Pos() < previousNodeEnd || c.End() > ifStmt.Pos() { + continue + } + + if c.End() > previousNodeEnd { + // There's a comment between the error variable and the + // if-statement, we can't do much about this. Most likely, the + // comment has a meaning, but even if not we would end up with + // something like + // + // err := fn() + // // Some Comment + // if err != nil {} + // + // Which just feels marginally better than leaving the space + // anyway. + if w.lineFor(c.End()) != w.lineFor(previousNodeEnd) { + return + } + + // If they are on the same line though, we can just extend where + // the line ends. + previousNodeEnd = c.End() + } + } + } + + w.addError(previousNodeEnd+1, previousNodeEnd, ifStmt.Pos(), messageRemoveWhitespace, cursor.checkType) + + // If we add the error at the same position but with a different fix + // range, only the fix range will be updated. + // + // a := 1 + // err := fn() + // + // if err != nil {} + // + // Should become + // + // a := 1 + // + // err := fn() + // if err != nil {} + cursor.Previous() + + // We report this fix on the same pos as the previous diagnostic, but the + // fix is different. The reason is to just stack more fixes for the same + // diagnostic, the issue isn't present until the first fix so this message + // will never be shown to the user. + if w.numberOfStatementsAbove(cursor) > 0 { + w.addError(previousNodeEnd+1, previousNode.Pos(), previousNode.Pos(), messageMissingWhitespaceAbove, cursor.checkType) + } +} + +func (w *WSL) checkExprStmt(stmt *ast.ExprStmt, cursor *Cursor) { + w.maybeCheckExpr( + stmt, + stmt.X, + cursor, + func(n ast.Node) (int, bool) { + _, ok := n.(*ast.ExprStmt) + return -1, !ok + }, + CheckExpr, + ) +} + +func (w *WSL) checkFor(stmt *ast.ForStmt, cursor *Cursor) { + w.maybeCheckBlock(stmt, stmt.Body, cursor, CheckFor) +} + +func (w *WSL) checkGo(stmt *ast.GoStmt, cursor *Cursor) { + w.maybeCheckExpr( + stmt, + stmt.Call, + cursor, + // We can cuddle any amount `go` statements so only check cuddling if + // the previous one isn't a `go` call. + func(n ast.Node) (int, bool) { + _, ok := n.(*ast.GoStmt) + return 1, !ok + }, + CheckGo, + ) +} + +func (w *WSL) checkIf(stmt *ast.IfStmt, cursor *Cursor, isElse bool) { + // if + w.checkBlock(stmt.Body) + + switch v := stmt.Else.(type) { + // else-if + case *ast.IfStmt: + w.checkIf(v, cursor, true) + + // else + case *ast.BlockStmt: + w.checkBlock(v) + } + + if _, ok := w.config.Checks[CheckIf]; !isElse && ok { + cursor.SetChecker(CheckIf) + w.checkCuddlingBlock(stmt, stmt.Body.List, []*ast.Ident{}, cursor, 1) + } else if _, ok := w.config.Checks[CheckErr]; !isElse && ok { + previousNode := cursor.PreviousNode() + + w.checkError( + w.numberOfStatementsAbove(cursor), + stmt, + previousNode, + cursor, + ) + } +} + +func (w *WSL) checkIncDec(stmt *ast.IncDecStmt, cursor *Cursor) { + defer w.checkExpr(stmt.X, cursor) + + if _, ok := w.config.Checks[CheckIncDec]; !ok { + return + } + + cursor.SetChecker(CheckIncDec) + + w.checkCuddlingWithoutIntersection(stmt, cursor) +} + +func (w *WSL) checkLabel(stmt *ast.LabeledStmt, cursor *Cursor) { + // We check the statement last because the statement is the same node as the + // label (it's a labeled statement). This means that we _first_ want to + // check any violations of cuddling the label (never cuddle label) before we + // actually check the inner statement. + // + // It's a subtle difference, but it makes the diagnostic make more sense. + // We do this by deferring the statmenet check so it happens last no matter + // if we have label checking enabled or not. + defer w.checkStmt(stmt.Stmt, cursor) + + if _, ok := w.config.Checks[CheckLabel]; !ok { + return + } + + cursor.SetChecker(CheckLabel) + + if w.numberOfStatementsAbove(cursor) == 0 { + return + } + + w.addErrorNeverAllow(stmt.Pos(), cursor.checkType) +} + +func (w *WSL) checkRange(stmt *ast.RangeStmt, cursor *Cursor) { + w.maybeCheckBlock(stmt, stmt.Body, cursor, CheckRange) +} + +func (w *WSL) checkReturn(stmt *ast.ReturnStmt, cursor *Cursor) { + for _, expr := range stmt.Results { + w.checkExpr(expr, cursor) + } + + if _, ok := w.config.Checks[CheckReturn]; !ok { + return + } + + cursor.SetChecker(CheckReturn) + + // There's only a return statement. + if cursor.Len() <= 1 { + return + } + + if w.numberOfStatementsAbove(cursor) == 0 { + return + } + + // If the distance between the first statement and the return statement is + // less than `n` LOC we're allowed to cuddle. + firstStmts := cursor.Nth(0) + if w.lineFor(stmt.End())-w.lineFor(firstStmts.Pos()) < w.config.BranchMaxLines { + return + } + + w.addErrorTooManyLines(stmt.Pos(), cursor.checkType) +} + +func (w *WSL) checkSelect(stmt *ast.SelectStmt, cursor *Cursor) { + w.maybeCheckBlock(stmt, stmt.Body, cursor, CheckSelect) +} + +func (w *WSL) checkSend(stmt *ast.SendStmt, cursor *Cursor) { + defer w.checkExpr(stmt.Value, cursor) + + if _, ok := w.config.Checks[CheckSend]; !ok { + return + } + + cursor.SetChecker(CheckSend) + + var stmts []ast.Stmt + + ast.Inspect(stmt.Value, func(n ast.Node) bool { + if b, ok := n.(*ast.BlockStmt); ok { + stmts = b.List + return false + } + + return true + }) + + w.checkCuddlingBlock(stmt, stmts, []*ast.Ident{}, cursor, 1) +} + +func (w *WSL) checkSwitch(stmt *ast.SwitchStmt, cursor *Cursor) { + w.maybeCheckBlock(stmt, stmt.Body, cursor, CheckSwitch) +} + +func (w *WSL) checkTypeSwitch(stmt *ast.TypeSwitchStmt, cursor *Cursor) { + w.maybeCheckBlock(stmt, stmt.Body, cursor, CheckTypeSwitch) +} + +func (w *WSL) checkCaseTrailingNewline(body []ast.Stmt, cursor *Cursor) { + if len(body) == 0 { + return + } + + defer cursor.Save()() + + if !cursor.Next() { + return + } + + var nextCase ast.Node + + switch n := cursor.Stmt().(type) { + case *ast.CaseClause: + nextCase = n + case *ast.CommClause: + nextCase = n + default: + return + } + + firstStmt := body[0] + lastStmt := body[len(body)-1] + totalLines := w.lineFor(lastStmt.End()) - w.lineFor(firstStmt.Pos()) + 1 + + if totalLines < w.config.CaseMaxLines { + return + } + + // Next case is not immediately after the last statement so must be newline + // already. + if w.lineFor(nextCase.Pos()) > w.lineFor(lastStmt.End())+1 { + return + } + + w.addError(lastStmt.End(), nextCase.Pos(), nextCase.Pos(), messageMissingWhitespaceBelow, CheckCaseTrailingNewline) +} + +func (w *WSL) checkBlockLeadingNewline(body *ast.BlockStmt) { + comments := ast.NewCommentMap(w.fset, body, w.file.Comments) + w.checkLeadingNewline(body.Lbrace, body.List, comments) +} + +func (w *WSL) checkCaseLeadingNewline(caseClause *ast.CaseClause) { + comments := ast.NewCommentMap(w.fset, caseClause, w.file.Comments) + w.checkLeadingNewline(caseClause.Colon, caseClause.Body, comments) +} + +func (w *WSL) checkCommLeadingNewline(commClause *ast.CommClause) { + comments := ast.NewCommentMap(w.fset, commClause, w.file.Comments) + w.checkLeadingNewline(commClause.Colon, commClause.Body, comments) +} + +func (w *WSL) checkLeadingNewline(startPos token.Pos, body []ast.Stmt, comments ast.CommentMap) { + if _, ok := w.config.Checks[CheckLeadingWhitespace]; !ok { + return + } + + // No statements in the block, let's leave it as is. + if len(body) == 0 { + return + } + + openLine := w.lineFor(startPos) + openingPos := startPos + 1 + firstStmt := body[0].Pos() + + for _, commentGroup := range comments { + for _, comment := range commentGroup { + // The comment starts after the current opening position (originally + // the LBrace) and ends before the current first statement + // (originally first body.List item). + if comment.Pos() > openingPos && comment.End() < firstStmt { + openingPosLine := w.lineFor(openingPos) + commentStartLine := w.lineFor(comment.Pos()) + + // If comment starts at the same line as the opening position it + // should just extend the position for the fixer if needed. + // func fn() { // This comment starts at the same line as LBrace + switch { + // The comment is on the same line as current opening position. + // E.g. func fn() { // A comment + case commentStartLine == openingPosLine: + openingPos = comment.End() + // Opening position is the same as `{` and the comment is + // directly on the line after (no empty line) + case openingPosLine == openLine && + commentStartLine == openLine+1: + openingPos = comment.End() + // The opening position has been updated, it's another comment. + case openingPosLine != openLine: + openingPos = comment.End() + // The opening position is still { and the comment is not + // directly above - it must be an empty line which shouldn't be + // there. + default: + firstStmt = comment.Pos() + } + } + } + } + + openingPosLine := w.lineFor(openingPos) + firstStmtLine := w.lineFor(firstStmt) + + if firstStmtLine > openingPosLine+1 { + w.addError(openingPos+1, openingPos, firstStmt, messageRemoveWhitespace, CheckLeadingWhitespace) + } +} + +func (w *WSL) checkTrailingNewline(body *ast.BlockStmt) { + if _, ok := w.config.Checks[CheckTrailingWhitespace]; !ok { + return + } + + // No statements in the block, let's leave it as is. + if len(body.List) == 0 { + return + } + + lastStmt := body.List[len(body.List)-1] + + // We don't want to force removal of the empty line for the last case since + // it can be use for consistency and readability. + if _, ok := lastStmt.(*ast.CaseClause); ok { + return + } + + closingPos := body.Rbrace + lastStmtOrComment := lastStmt.End() + + // Empty label statements needs positional adjustment. #92 + if l, ok := lastStmt.(*ast.LabeledStmt); ok { + if _, ok := l.Stmt.(*ast.EmptyStmt); ok { + lastStmtOrComment = lastStmt.Pos() + } + } + + comments := ast.NewCommentMap(w.fset, body, w.file.Comments) + for _, commentGroup := range comments { + for _, comment := range commentGroup { + if comment.End() < closingPos && comment.Pos() > lastStmtOrComment { + lastStmtOrComment = comment.End() + } + } + } + + closingPosLine := w.lineFor(closingPos) + lastStmtLine := w.lineFor(lastStmtOrComment) + + if closingPosLine > lastStmtLine+1 { + w.addError(lastStmtOrComment+1, lastStmtOrComment, closingPos, messageRemoveWhitespace, CheckTrailingWhitespace) + } +} + +func (w *WSL) maybeGroupDecl(stmt *ast.DeclStmt, cursor *Cursor) bool { + firstNode := asGenDeclWithValueSpecs(cursor.PreviousNode()) + if firstNode == nil { + return false + } + + currentNode := asGenDeclWithValueSpecs(stmt) + if currentNode == nil { + return false + } + + // Both are not same type, e.g. `const` or `var` + if firstNode.Tok != currentNode.Tok { + return false + } + + group := &ast.GenDecl{ + Tok: firstNode.Tok, + Lparen: 1, + Specs: firstNode.Specs, + } + + group.Specs = append(group.Specs, currentNode.Specs...) + + reportNodes := []ast.Node{currentNode} + lastNode := currentNode + + for { + nextPeeked := cursor.NextNode() + if nextPeeked == nil { + break + } + + if w.lineFor(lastNode.End()) < w.lineFor(nextPeeked.Pos())-1 { + break + } + + nextNode := asGenDeclWithValueSpecs(nextPeeked) + if nextNode == nil { + break + } + + if nextNode.Tok != firstNode.Tok { + break + } + + cursor.Next() + + group.Specs = append(group.Specs, nextNode.Specs...) + reportNodes = append(reportNodes, nextNode) + lastNode = nextNode + } + + var buf bytes.Buffer + if err := format.Node(&buf, token.NewFileSet(), group); err != nil { + return false + } + + // We add a diagnostic to every subsequent statement to properly represent + // the violations. Duplicate fixes for the same range is fine. + for _, n := range reportNodes { + w.groupedDecls[n.End()] = struct{}{} + + w.addErrorWithMessageAndFix( + n.Pos(), + firstNode.Pos(), + lastNode.End(), + fmt.Sprintf("%s (never cuddle %s)", messageMissingWhitespaceAbove, CheckDecl), + buf.Bytes(), + ) + } + + return true +} + +func (w *WSL) maybeCheckBlock( + node ast.Node, + blockStmt *ast.BlockStmt, + cursor *Cursor, + check CheckType, +) { + w.checkBlock(blockStmt) + + if _, ok := w.config.Checks[check]; ok { + cursor.SetChecker(check) + + var ( + blockList []ast.Stmt + allowedIdents []*ast.Ident + ) + + if check != CheckSwitch && check != CheckTypeSwitch && check != CheckSelect { + blockList = blockStmt.List + } else { + allowedIdents = w.identsFromCaseArms(node) + } + + w.checkCuddlingBlock(node, blockList, allowedIdents, cursor, 1) + } +} + +func (w *WSL) maybeCheckExpr( + node ast.Node, + expr ast.Expr, + cursor *Cursor, + predicate func(ast.Node) (int, bool), + check CheckType, +) { + w.checkExpr(expr, cursor) + + if _, ok := w.config.Checks[check]; ok { + cursor.SetChecker(check) + previousNode := cursor.PreviousNode() + + if n, ok := predicate(previousNode); ok { + w.checkCuddling(node, cursor, n) + } + } +} + +// numberOfStatementsAbove will find out how many lines above the cursor's +// current statement there is without any newlines between. +func (w *WSL) numberOfStatementsAbove(cursor *Cursor) int { + defer cursor.Save()() + + statementsWithoutNewlines := 0 + currentStmtStartLine := w.lineFor(cursor.Stmt().Pos()) + + for cursor.Previous() { + previousStmtEndLine := w.lineFor(cursor.Stmt().End()) + if previousStmtEndLine != currentStmtStartLine-1 { + break + } + + currentStmtStartLine = w.lineFor(cursor.Stmt().Pos()) + statementsWithoutNewlines++ + } + + return statementsWithoutNewlines +} + +func (w *WSL) lineFor(pos token.Pos) int { + return w.fset.PositionFor(pos, false).Line +} + +func (w *WSL) implementsErr(node *ast.Ident) bool { + typeInfo := w.typeInfo.TypeOf(node) + if typeInfo == nil { + return false + } + + errorType, ok := types.Universe.Lookup("error").Type().Underlying().(*types.Interface) + if !ok { + return false + } + + return types.Implements(typeInfo, errorType) +} + +func (w *WSL) addErrorInvalidTypeCuddle(pos token.Pos, ct CheckType) { + reportMessage := fmt.Sprintf("%s (invalid statement above %s)", messageMissingWhitespaceAbove, ct) + w.addErrorWithMessage(pos, pos, pos, reportMessage) +} + +func (w *WSL) addErrorTooManyStatements(pos token.Pos, ct CheckType) { + reportMessage := fmt.Sprintf("%s (too many statements above %s)", messageMissingWhitespaceAbove, ct) + w.addErrorWithMessage(pos, pos, pos, reportMessage) +} + +func (w *WSL) addErrorNoIntersection(pos token.Pos, ct CheckType) { + reportMessage := fmt.Sprintf("%s (no shared variables above %s)", messageMissingWhitespaceAbove, ct) + w.addErrorWithMessage(pos, pos, pos, reportMessage) +} + +func (w *WSL) addErrorTooManyLines(pos token.Pos, ct CheckType) { + reportMessage := fmt.Sprintf("%s (too many lines above %s)", messageMissingWhitespaceAbove, ct) + w.addErrorWithMessage(pos, pos, pos, reportMessage) +} + +func (w *WSL) addErrorNeverAllow(pos token.Pos, ct CheckType) { + reportMessage := fmt.Sprintf("%s (never cuddle %s)", messageMissingWhitespaceAbove, ct) + w.addErrorWithMessage(pos, pos, pos, reportMessage) +} + +func (w *WSL) addError(report, start, end token.Pos, message string, ct CheckType) { + reportMessage := fmt.Sprintf("%s (%s)", message, ct) + w.addErrorWithMessage(report, start, end, reportMessage) +} + +func (w *WSL) addErrorWithMessage(report, start, end token.Pos, message string) { + w.addErrorWithMessageAndFix(report, start, end, message, []byte("\n")) +} + +func (w *WSL) addErrorWithMessageAndFix(report, start, end token.Pos, message string, fix []byte) { + iss, ok := w.issues[report] + if !ok { + iss = issue{ + message: message, + fixRanges: []fixRange{}, + } + } + + iss.fixRanges = append(iss.fixRanges, fixRange{ + fixRangeStart: start, + fixRangeEnd: end, + fix: fix, + }) + + w.issues[report] = iss +} + +func asGenDeclWithValueSpecs(n ast.Node) *ast.GenDecl { + decl, ok := n.(*ast.DeclStmt) + if !ok { + return nil + } + + genDecl, ok := decl.Decl.(*ast.GenDecl) + if !ok { + return nil + } + + for _, spec := range genDecl.Specs { + // We only care about value specs and not type specs or import + // specs. We will never see any import specs but type specs we just + // separate with an empty line as usual. + valueSpec, ok := spec.(*ast.ValueSpec) + if !ok { + return nil + } + + // It's very hard to get comments right in the ast and with the current + // way the ast package works we simply don't support grouping at all if + // there are any comments related to the node. + if valueSpec.Doc != nil || valueSpec.Comment != nil { + return nil + } + } + + return genDecl +} + +func (w *WSL) hasIntersection(a, b ast.Node) bool { + return len(w.nodeIdentIntersection(a, b)) > 0 +} + +func (w *WSL) nodeIdentIntersection(a, b ast.Node) []*ast.Ident { + aI := w.identsFromNode(a, true) + bI := w.identsFromNode(b, true) + + return identIntersection(aI, bI) +} + +func identIntersection(a, b []*ast.Ident) []*ast.Ident { + intersects := []*ast.Ident{} + + for _, as := range a { + for _, bs := range b { + if as.Name == bs.Name { + intersects = append(intersects, as) + } + } + } + + return intersects +} + +func isTypeOrPredeclConst(obj types.Object) bool { + switch o := obj.(type) { + case *types.TypeName: + // Covers predeclared types ("string", "int", ...) and user types. + return true + case *types.Const: + // true/false/iota are universe consts. + return o.Parent() == types.Universe + case *types.Nil: + return true + case *types.PkgName: + // Skip package qualifiers like "fmt" in fmt.Println + return true + default: + return false + } +} + +// identsFromNode returns all *ast.Ident in a node except: +// - type names (types.TypeName) +// - builtin constants from the universe (true, false, iota) +// - nil (*types.Nil) +// - package names (types.PkgName) +// - the blank identifier "_" +func (w *WSL) identsFromNode(node ast.Node, skipBlock bool) []*ast.Ident { + var ( + idents []*ast.Ident + seen = map[string]struct{}{} + ) + + if node == nil { + return idents + } + + addIdent := func(ident *ast.Ident) { + if ident == nil { + return + } + + name := ident.Name + if name == "" || name == "_" { + return + } + + if _, ok := seen[name]; ok { + return + } + + idents = append(idents, ident) + seen[name] = struct{}{} + } + + ast.Inspect(node, func(n ast.Node) bool { + if skipBlock { + if _, ok := n.(*ast.BlockStmt); ok { + return false + } + } + + ident, ok := n.(*ast.Ident) + if !ok { + return true + } + + // Prefer Uses over Defs; fall back to Defs if not a use site. + var typesObject types.Object + if obj := w.typeInfo.Uses[ident]; obj != nil { + typesObject = obj + } else if obj := w.typeInfo.Defs[ident]; obj != nil { + typesObject = obj + } + + // Unresolved (could be a build-tag or syntax artifact). Keep it. + if typesObject == nil { + addIdent(ident) + return true + } + + if isTypeOrPredeclConst(typesObject) { + return true + } + + addIdent(ident) + + return true + }) + + return idents +} + +func (w *WSL) identsFromCaseArms(node ast.Node) []*ast.Ident { + var ( + idents []*ast.Ident + nodes []ast.Stmt + seen = map[string]struct{}{} + + addUnseen = func(node ast.Node) { + for _, ident := range w.identsFromNode(node, true) { + if _, ok := seen[ident.Name]; ok { + continue + } + + seen[ident.Name] = struct{}{} + idents = append(idents, ident) + } + } + ) + + switch v := node.(type) { + case *ast.SwitchStmt: + nodes = v.Body.List + case *ast.TypeSwitchStmt: + nodes = v.Body.List + case *ast.SelectStmt: + nodes = v.Body.List + default: + return idents + } + + for _, node := range nodes { + switch n := node.(type) { + case *ast.CommClause: + addUnseen(n.Comm) + case *ast.CaseClause: + for _, n := range n.List { + addUnseen(n) + } + default: + continue + } + } + + return idents +} diff --git a/vendor/github.com/catenacyber/perfsprint/analyzer/analyzer.go b/vendor/github.com/catenacyber/perfsprint/analyzer/analyzer.go index c40e84d41..c44104f5f 100644 --- a/vendor/github.com/catenacyber/perfsprint/analyzer/analyzer.go +++ b/vendor/github.com/catenacyber/perfsprint/analyzer/analyzer.go @@ -1,7 +1,9 @@ +// Package analyzer provides a static analysis tool that checks that fmt.Sprintf can be replaced with a faster alternative. package analyzer import ( "bytes" + "fmt" "go/ast" "go/format" "go/token" @@ -33,13 +35,20 @@ type optionStr struct { strconcat bool } +type optionConcatLoop struct { + enabled bool + otherOps bool +} + type perfSprint struct { - intFormat optionInt - errFormat optionErr - strFormat optionStr + intFormat optionInt + errFormat optionErr + strFormat optionStr + concatLoop optionConcatLoop boolFormat bool hexFormat bool + fiximports bool } @@ -48,6 +57,7 @@ func newPerfSprint() *perfSprint { intFormat: optionInt{enabled: true, intConv: true}, errFormat: optionErr{enabled: true, errError: false, errorf: true}, strFormat: optionStr{enabled: true, sprintf1: true, strconcat: true}, + concatLoop: optionConcatLoop{enabled: true, otherOps: false}, boolFormat: true, hexFormat: true, fiximports: true, @@ -65,6 +75,8 @@ const ( checkerBoolFormat = "bool-format" // checkerHexFormat checks for hexadecimal formatting. checkerHexFormat = "hex-format" + // checkerConcatLoop checks for concatenation in loop. + checkerConcatLoop = "concat-loop" // checkerFixImports fix needed imports from other fixes. checkerFixImports = "fiximports" ) @@ -87,6 +99,8 @@ func New() *analysis.Analyzer { r.Flags.BoolVar(&n.boolFormat, checkerBoolFormat, n.boolFormat, "enable/disable optimization of bool formatting") r.Flags.BoolVar(&n.hexFormat, checkerHexFormat, n.hexFormat, "enable/disable optimization of hex formatting") + r.Flags.BoolVar(&n.concatLoop.enabled, checkerConcatLoop, n.concatLoop.enabled, "enable/disable optimization of concat loop") + r.Flags.BoolVar(&n.concatLoop.otherOps, "loop-other-ops", n.concatLoop.otherOps, "optimization of concat loop even with other operations") r.Flags.BoolVar(&n.strFormat.enabled, checkerStringFormat, n.strFormat.enabled, "enable/disable optimization of string formatting") r.Flags.BoolVar(&n.strFormat.sprintf1, "sprintf1", n.strFormat.sprintf1, "optimizes fmt.Sprintf with only one argument") r.Flags.BoolVar(&n.strFormat.strconcat, "strconcat", n.strFormat.strconcat, "optimizes into strings concatenation") @@ -105,7 +119,347 @@ func isConcatable(verb string) bool { if strings.Count(verb, "%[1]s") > 1 { return false } - return (hasPrefix || hasSuffix) && !(hasPrefix && hasSuffix) + // TODO handle case hasPrefix and hasSuffix + return (hasPrefix || hasSuffix) && !(hasPrefix && hasSuffix) //nolint:staticcheck +} + +func isStringAdd(st *ast.AssignStmt, idname string) ast.Expr { + // right is one + if len(st.Rhs) == 1 { + // right is addition + add, ok := st.Rhs[0].(*ast.BinaryExpr) + if ok && add.Op == token.ADD { + // right is addition to same ident name + x, ok := add.X.(*ast.Ident) + if ok && x.Name == idname { + return add.Y + } + } + } + return nil +} + +func (n *perfSprint) reportConcatLoop(pass *analysis.Pass, neededPackages map[string]map[string]struct{}, node ast.Node, adds map[string][]*ast.AssignStmt) *analysis.Diagnostic { + fname := pass.Fset.File(node.Pos()).Name() + if _, ok := neededPackages[fname]; !ok { + neededPackages[fname] = make(map[string]struct{}) + } + // note that we will need strings package + neededPackages[fname]["strings"] = struct{}{} + + // sort for reproducibility + keys := make([]string, 0, len(adds)) + for k := range adds { + keys = append(keys, k) + } + sort.Strings(keys) + + // use line number to define a unique variable name for the strings Builder + loopStartLine := pass.Fset.Position(node.Pos()).Line + + // If the loop does more with the string than concatenations + // add a TODO/FIXME comment that the fix is likely incomplete/incorrect + addTODO := "" + ast.Inspect(node, func(n ast.Node) bool { + if len(addTODO) > 0 { + // already found one, stop recursing + return false + } + switch x := n.(type) { + case *ast.AssignStmt: + // skip if this is one string concatenation that we are fixing + if (x.Tok == token.ASSIGN || x.Tok == token.ADD_ASSIGN) && len(x.Lhs) == 1 { + id, ok := x.Lhs[0].(*ast.Ident) + if ok { + _, ok = adds[id.Name] + if ok { + if x.Tok == token.ASSIGN && isStringAdd(x, id.Name) == nil { + addTODO = id.Name + } + return false + } + } + } + case *ast.Ident: + _, ok := adds[x.Name] + if ok { + // The variable name is used in some place else + addTODO = x.Name + return false + } + } + return true + }) + + prefix := "" + suffix := "" + if len(addTODO) > 0 { + if !n.concatLoop.otherOps { + return nil + } + prefix = fmt.Sprintf("// FIXME check usages of string identifier %s (and mayber others) in loop\n", addTODO) + } + // The fix contains 3 parts + // before the loop: declare the strings Builders + // during the loop: replace concatenation with Builder.WriteString + // after the loop: use the Builder.String to append to the pre-existing string + var prefixSb203 strings.Builder + var suffixSb203 strings.Builder + for _, k := range keys { + // lol + prefixSb203.WriteString(fmt.Sprintf("var %sSb%d strings.Builder\n", k, loopStartLine)) + suffixSb203.WriteString(fmt.Sprintf("\n%s += %sSb%d.String()", k, k, loopStartLine)) + } + prefix += prefixSb203.String() + suffix += suffixSb203.String() + te := []analysis.TextEdit{ + { + Pos: node.Pos(), + End: node.Pos(), + NewText: []byte(prefix), + }, + } + for _, k := range keys { + v := adds[k] + for _, st := range v { + // s += "x" -> use "x" + added := st.Rhs[0] + if st.Tok == token.ASSIGN { + // s = s + "x" -> use just "x", not `s + "x"` + added = isStringAdd(st, k) + } + te = append(te, analysis.TextEdit{ + Pos: st.Pos(), + End: added.Pos(), + NewText: []byte(fmt.Sprintf("%sSb%d.WriteString(", k, loopStartLine)), + }) + te = append(te, analysis.TextEdit{ + Pos: added.End(), + End: added.End(), + NewText: []byte(")"), + }) + } + } + te = append(te, analysis.TextEdit{ + Pos: node.End(), + End: node.End(), + NewText: []byte(suffix), + }) + + return newAnalysisDiagnostic( + checkerConcatLoop, + adds[keys[0]][0], + "string concatenation in a loop", + []analysis.SuggestedFix{ + { + Message: "Use a strings.Builder", + TextEdits: te, + }, + }, + ) +} + +func (n *perfSprint) runConcatLoop(pass *analysis.Pass, neededPackages map[string]map[string]struct{}) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + // 2 different kinds of loops in go + nodeFilter := []ast.Node{ + (*ast.RangeStmt)(nil), + (*ast.ForStmt)(nil), + } + insp.Preorder(nodeFilter, func(node ast.Node) { + // set of variable names declared insied the loop + declInLoop := make(map[string]bool) + var bl []ast.Stmt + // just take the list of instruction of the loop + switch ra := node.(type) { + case *ast.RangeStmt: + bl = ra.Body.List + case *ast.ForStmt: + bl = ra.Body.List + } + // set of results : mapping a variable name to a list of statements like `s +=` + // one loop may be bad for multiple string variables, + // each being concatenated in multiple statements + adds := make(map[string][]*ast.AssignStmt) + for bs := 0; bs < len(bl); bs++ { + switch st := bl[bs].(type) { + case *ast.IfStmt: + // explore breadth first, but go inside the if/else blocks + if st.Body != nil { + bl = append(bl, st.Body.List...) + } + el, ok := st.Else.(*ast.BlockStmt) + if ok && el != nil { + bl = append(bl, el.List...) + } + case *ast.DeclStmt: + // identifiers defined within loop do not count + de, ok := st.Decl.(*ast.GenDecl) + if !ok { + break + } + if len(de.Specs) != 1 { + break + } + // is it possible to have len(de.Specs) > 1 for ValueSpec ? + vs, ok := de.Specs[0].(*ast.ValueSpec) + if !ok { + break + } + for n := range vs.Names { + declInLoop[vs.Names[n].Name] = true + } + case *ast.AssignStmt: + for n := range st.Lhs { + id, ok := st.Lhs[n].(*ast.Ident) + if !ok { + break + } + switch st.Tok { + case token.DEFINE: + declInLoop[id.Name] = true + case token.ASSIGN, token.ADD_ASSIGN: + if n > 0 { + // do not search bugs for multi-assign + break + } + _, local := declInLoop[id.Name] + if local { + break + } + ti, ok := pass.TypesInfo.Types[id] + if !ok || ti.Type.String() != "string" { + break + } + if st.Tok == token.ASSIGN { + if isStringAdd(st, id.Name) == nil { + break + } + } + // found a bad string concat in the loop + adds[id.Name] = append(adds[id.Name], st) + } + } + } + } + if len(adds) > 0 { + d := n.reportConcatLoop(pass, neededPackages, node, adds) + if d != nil { + pass.Report(*d) + } + } + }) +} + +func (n *perfSprint) fixImports(pass *analysis.Pass, neededPackages map[string]map[string]struct{}, removedFmtUsages map[string]int) { + if !n.fiximports { + return + } + for _, pkg := range pass.Pkg.Imports() { + if pkg.Path() == "fmt" { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + nodeFilter := []ast.Node{ + (*ast.SelectorExpr)(nil), + } + insp.Preorder(nodeFilter, func(node ast.Node) { + selec := node.(*ast.SelectorExpr) + selecok, ok := selec.X.(*ast.Ident) + if ok { + pkgname, ok := pass.TypesInfo.ObjectOf(selecok).(*types.PkgName) + if ok && pkgname.Name() == pkg.Name() { + fname := pass.Fset.File(pkgname.Pos()).Name() + removedFmtUsages[fname]-- + } + } + }) + } else if pkg.Path() == "errors" || pkg.Path() == "strconv" || pkg.Path() == "encoding/hex" || pkg.Path() == "strings" { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + nodeFilter := []ast.Node{ + (*ast.ImportSpec)(nil), + } + insp.Preorder(nodeFilter, func(node ast.Node) { + gd := node.(*ast.ImportSpec) + if gd.Path.Value == strconv.Quote(pkg.Path()) { + fname := pass.Fset.File(gd.Pos()).Name() + if _, ok := neededPackages[fname]; ok { + delete(neededPackages[fname], pkg.Path()) + } + } + }) + } + } + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + nodeFilter := []ast.Node{ + (*ast.File)(nil), + } + insp.Preorder(nodeFilter, func(node ast.Node) { + gd := node.(*ast.File) + fname := pass.Fset.File(gd.Pos()).Name() + removed, hasFmt := removedFmtUsages[fname] + if (!hasFmt || removed < 0) && len(neededPackages[fname]) == 0 { + return + } + fix := "" + var ar analysis.Range + ar = gd.Decls[0] + start := gd.Decls[0].Pos() + end := gd.Decls[0].Pos() + if len(gd.Imports) == 0 { + fix += "import (\n" + } else { + id := gd.Decls[0].(*ast.GenDecl) + start = id.Specs[0].Pos() + end = id.Specs[0].Pos() + if removedFmtUsages[fname] >= 0 { + for sp := range id.Specs { + is := id.Specs[sp].(*ast.ImportSpec) + if is.Path.Value == strconv.Quote("fmt") { + ar = is + start = is.Pos() + end = is.End() + break + } + } + } + } + keys := make([]string, 0, len(neededPackages[fname])) + for k := range neededPackages[fname] { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + already := false + knames := strings.Split(k, "/") + kname := knames[len(knames)-1] + for i := range gd.Imports { // quadratic + if (gd.Imports[i].Name != nil && gd.Imports[i].Name.Name == kname) || (gd.Imports[i].Name == nil && strings.HasSuffix(gd.Imports[i].Path.Value, "/"+kname+`"`)) { + already = true + } + } + if already { + fix = fix + "\t\"" + k + "\" //TODO FIXME\n" + } else { + fix = fix + "\t\"" + k + "\"\n" + } + } + if len(gd.Imports) == 0 { + fix += ")\n" + } + pass.Report(*newAnalysisDiagnostic( + checkerFixImports, + ar, + "Fix imports", + []analysis.SuggestedFix{ + { + Message: "Fix imports", + TextEdits: []analysis.TextEdit{{ + Pos: start, + End: end, + NewText: []byte(fix), + }}, + }, + })) + }) } func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { @@ -121,6 +475,11 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { n.strFormat.strconcat = false } + neededPackages := make(map[string]map[string]struct{}) + if n.concatLoop.enabled { + n.runConcatLoop(pass, neededPackages) + } + removedFmtUsages := make(map[string]int) var fmtSprintObj, fmtSprintfObj, fmtErrorfObj types.Object for _, pkg := range pass.Pkg.Imports() { if pkg.Path() == "fmt" { @@ -130,10 +489,11 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { } } if fmtSprintfObj == nil && fmtSprintObj == nil && fmtErrorfObj == nil { + if len(neededPackages) > 0 { + n.fixImports(pass, neededPackages, removedFmtUsages) + } return nil, nil } - removedFmtUsages := make(map[string]int) - neededPackages := make(map[string]map[string]struct{}) insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ @@ -530,79 +890,8 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { } }) - if len(removedFmtUsages) > 0 && n.fiximports { - for _, pkg := range pass.Pkg.Imports() { - if pkg.Path() == "fmt" { - insp = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) - nodeFilter = []ast.Node{ - (*ast.SelectorExpr)(nil), - } - insp.Preorder(nodeFilter, func(node ast.Node) { - selec := node.(*ast.SelectorExpr) - selecok, ok := selec.X.(*ast.Ident) - if ok { - pkgname, ok := pass.TypesInfo.ObjectOf(selecok).(*types.PkgName) - if ok && pkgname.Name() == pkg.Name() { - fname := pass.Fset.File(pkgname.Pos()).Name() - removedFmtUsages[fname]-- - } - } - }) - } else if pkg.Path() == "errors" || pkg.Path() == "strconv" || pkg.Path() == "encoding/hex" { - insp = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) - nodeFilter = []ast.Node{ - (*ast.ImportSpec)(nil), - } - insp.Preorder(nodeFilter, func(node ast.Node) { - gd := node.(*ast.ImportSpec) - if gd.Path.Value == strconv.Quote(pkg.Path()) { - fname := pass.Fset.File(gd.Pos()).Name() - if _, ok := neededPackages[fname]; ok { - delete(neededPackages[fname], pkg.Path()) - } - } - }) - } - } - insp = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) - nodeFilter = []ast.Node{ - (*ast.ImportSpec)(nil), - } - insp.Preorder(nodeFilter, func(node ast.Node) { - gd := node.(*ast.ImportSpec) - if gd.Path.Value == `"fmt"` { - fix := "" - fname := pass.Fset.File(gd.Pos()).Name() - if removedFmtUsages[fname] < 0 { - fix += `"fmt"` - if len(neededPackages[fname]) == 0 { - return - } - } - keys := make([]string, 0, len(neededPackages[fname])) - for k := range neededPackages[fname] { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - fix = fix + "\n\t\"" + k + `"` - } - pass.Report(*newAnalysisDiagnostic( - checkerFixImports, - gd, - "Fix imports", - []analysis.SuggestedFix{ - { - Message: "Fix imports", - TextEdits: []analysis.TextEdit{{ - Pos: gd.Pos(), - End: gd.End(), - NewText: []byte(fix), - }}, - }, - })) - } - }) + if len(removedFmtUsages) > 0 || len(neededPackages) > 0 { + n.fixImports(pass, neededPackages, removedFmtUsages) } return nil, nil diff --git a/vendor/github.com/ccojocar/zxcvbn-go/.golangci.yml b/vendor/github.com/ccojocar/zxcvbn-go/.golangci.yml index b54f70092..765d3b5ea 100644 --- a/vendor/github.com/ccojocar/zxcvbn-go/.golangci.yml +++ b/vendor/github.com/ccojocar/zxcvbn-go/.golangci.yml @@ -1,39 +1,46 @@ +version: "2" linters: enable: - asciicheck - bodyclose - dogsled - durationcheck - - errcheck - errorlint - - exportloopref - - gci - ginkgolinter - - gofmt - - gofumpt - - goimports - - gosimple - - govet - importas - - ineffassign - - megacheck - misspell - nakedret - nolintlint - revive - - staticcheck - - typecheck - unconvert - unparam - - unused - wastedassign - -linters-settings: - gci: - sections: - - standard - - default - - prefix(github.com/ccojocar) - -run: - timeout: 5m + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: + gci: + sections: + - standard + - default + - prefix(github.com/ccojocar) + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/vendor/github.com/ccojocar/zxcvbn-go/.goreleaser.yml b/vendor/github.com/ccojocar/zxcvbn-go/.goreleaser.yml index 2386aeee5..2b786c5d8 100644 --- a/vendor/github.com/ccojocar/zxcvbn-go/.goreleaser.yml +++ b/vendor/github.com/ccojocar/zxcvbn-go/.goreleaser.yml @@ -1,4 +1,4 @@ ---- +version: 2 project_name: zxcvbn-go release: diff --git a/vendor/github.com/ccojocar/zxcvbn-go/matching/dateMatchers.go b/vendor/github.com/ccojocar/zxcvbn-go/matching/dateMatchers.go index fd7f38332..c3829c925 100644 --- a/vendor/github.com/ccojocar/zxcvbn-go/matching/dateMatchers.go +++ b/vendor/github.com/ccojocar/zxcvbn-go/matching/dateMatchers.go @@ -39,7 +39,8 @@ func checkDate(day, month, year int64) (bool, int64, int64, int64) { return false, 0, 0, 0 } - if !((1900 <= year && year <= 2019) || (0 <= year && year <= 99)) { + //nolint:staticcheck // Ignore De Morgan's law optimization + if !((1900 <= year && year <= 2025) || (0 <= year && year <= 99)) { return false, 0, 0, 0 } diff --git a/vendor/github.com/ccojocar/zxcvbn-go/matching/leet.go b/vendor/github.com/ccojocar/zxcvbn-go/matching/leet.go index 1f303aa6e..f7fd30420 100644 --- a/vendor/github.com/ccojocar/zxcvbn-go/matching/leet.go +++ b/vendor/github.com/ccojocar/zxcvbn-go/matching/leet.go @@ -191,7 +191,7 @@ func createSubstitutionsMapsFromTable(table map[string][]string) []map[string]st func createWordForSubstitutionMap(word string, substitutionMap map[string]string) string { result := word for key, value := range substitutionMap { - result = strings.Replace(result, value, key, -1) + result = strings.ReplaceAll(result, value, key) } return result @@ -224,7 +224,7 @@ func copyMapRemovingSameValueFromOtherKeys(table map[string][]string, keyToFix s for key, values := range table { for _, value := range values { - if !(value == valueToFix && key != keyToFix) { + if value != valueToFix || key == keyToFix { result[key] = append(result[key], value) } } diff --git a/vendor/github.com/ccojocar/zxcvbn-go/scoring/scoring.go b/vendor/github.com/ccojocar/zxcvbn-go/scoring/scoring.go index f25606a8d..7154025a9 100644 --- a/vendor/github.com/ccojocar/zxcvbn-go/scoring/scoring.go +++ b/vendor/github.com/ccojocar/zxcvbn-go/scoring/scoring.go @@ -166,7 +166,7 @@ func displayTime(seconds float64) string { } func crackTimeToScore(seconds float64) int { - if seconds < math.Pow(10, 2) { + if seconds < 100 { return 0 } else if seconds < math.Pow(10, 4) { return 1 diff --git a/vendor/github.com/charithe/durationcheck/README.md b/vendor/github.com/charithe/durationcheck/README.md index 6f4279bd3..4aa9558f2 100644 --- a/vendor/github.com/charithe/durationcheck/README.md +++ b/vendor/github.com/charithe/durationcheck/README.md @@ -33,7 +33,7 @@ See the [test cases](testdata/src/a/a.go) for more examples of the types of erro Installation ------------- -Requires Go 1.11 or above. +Requires Go 1.14 or above. ``` go get -u github.com/charithe/durationcheck/cmd/durationcheck diff --git a/vendor/github.com/charithe/durationcheck/durationcheck.go b/vendor/github.com/charithe/durationcheck/durationcheck.go index c47b3a761..5fcb98a89 100644 --- a/vendor/github.com/charithe/durationcheck/durationcheck.go +++ b/vendor/github.com/charithe/durationcheck/durationcheck.go @@ -32,6 +32,7 @@ func run(pass *analysis.Pass) (interface{}, error) { nodeTypes := []ast.Node{ (*ast.BinaryExpr)(nil), + (*ast.AssignStmt)(nil), } inspect.Preorder(nodeTypes, check(pass)) @@ -52,25 +53,45 @@ func hasImport(pkg *types.Package, importPath string) bool { // check contains the logic for checking that time.Duration is used correctly in the code being analysed func check(pass *analysis.Pass) func(ast.Node) { return func(node ast.Node) { - expr := node.(*ast.BinaryExpr) - // we are only interested in multiplication - if expr.Op != token.MUL { - return + switch expr := node.(type) { + case *ast.BinaryExpr: + checkBinaryExpr(pass, expr) + case *ast.AssignStmt: + if expr.Tok != token.MUL_ASSIGN { + return + } + // '*=' assignment requires single-valued expressions + if len(expr.Lhs) != 1 || len(expr.Rhs) != 1 { + return + } + checkBinaryExpr(pass, &ast.BinaryExpr{ + X: expr.Lhs[0], + OpPos: expr.TokPos, + Op: expr.Tok, + Y: expr.Rhs[0], + }) } + } +} - // get the types of the two operands - x, xOK := pass.TypesInfo.Types[expr.X] - y, yOK := pass.TypesInfo.Types[expr.Y] +func checkBinaryExpr(pass *analysis.Pass, expr *ast.BinaryExpr) { + // we are only interested in multiplication + if expr.Op != token.MUL && expr.Op != token.MUL_ASSIGN { + return + } - if !xOK || !yOK { - return - } + // get the types of the two operands + x, xOK := pass.TypesInfo.Types[expr.X] + y, yOK := pass.TypesInfo.Types[expr.Y] - if isDuration(x.Type) && isDuration(y.Type) { - // check that both sides are acceptable expressions - if isUnacceptableExpr(pass, expr.X) && isUnacceptableExpr(pass, expr.Y) { - pass.Reportf(expr.Pos(), "Multiplication of durations: `%s`", formatNode(expr)) - } + if !xOK || !yOK { + return + } + + if isDuration(x.Type) && isDuration(y.Type) { + // check that both sides are acceptable expressions + if isUnacceptableExpr(pass, expr.X) && isUnacceptableExpr(pass, expr.Y) { + pass.Reportf(expr.Pos(), "Multiplication of durations: `%s`", formatNode(expr)) } } } diff --git a/vendor/github.com/daixiang0/gci/pkg/config/config.go b/vendor/github.com/daixiang0/gci/pkg/config/config.go index 814201a00..643a313f0 100644 --- a/vendor/github.com/daixiang0/gci/pkg/config/config.go +++ b/vendor/github.com/daixiang0/gci/pkg/config/config.go @@ -2,7 +2,6 @@ package config import ( "sort" - "strings" "gopkg.in/yaml.v3" @@ -64,11 +63,11 @@ func (g YamlConfig) Parse() (*Config, error) { sort.Slice(sections, func(i, j int) bool { sectionI, sectionJ := sections[i].Type(), sections[j].Type() - if g.Cfg.NoLexOrder || strings.Compare(sectionI, sectionJ) != 0 { + if g.Cfg.NoLexOrder || sectionI != sectionJ { return defaultOrder[sectionI] < defaultOrder[sectionJ] } - return strings.Compare(sections[i].String(), sections[j].String()) < 0 + return sections[i].String() < sections[j].String() }) } diff --git a/vendor/github.com/daixiang0/gci/pkg/section/standard_list.go b/vendor/github.com/daixiang0/gci/pkg/section/standard_list.go index 2fddded70..34cf38cec 100644 --- a/vendor/github.com/daixiang0/gci/pkg/section/standard_list.go +++ b/vendor/github.com/daixiang0/gci/pkg/section/standard_list.go @@ -1,182 +1,185 @@ package section -// Code generated based on go1.24.0 X:boringcrypto,arenas,synctest. DO NOT EDIT. +// Code generated based on go1.25rc1 X:boringcrypto,arenas,synctest,jsonv2. DO NOT EDIT. var standardPackages = map[string]struct{}{ - "archive/tar": {}, - "archive/zip": {}, - "arena": {}, - "bufio": {}, - "bytes": {}, - "cmp": {}, - "compress/bzip2": {}, - "compress/flate": {}, - "compress/gzip": {}, - "compress/lzw": {}, - "compress/zlib": {}, - "container/heap": {}, - "container/list": {}, - "container/ring": {}, - "context": {}, - "crypto": {}, - "crypto/aes": {}, - "crypto/boring": {}, - "crypto/cipher": {}, - "crypto/des": {}, - "crypto/dsa": {}, - "crypto/ecdh": {}, - "crypto/ecdsa": {}, - "crypto/ed25519": {}, - "crypto/elliptic": {}, - "crypto/fips140": {}, - "crypto/hkdf": {}, - "crypto/hmac": {}, - "crypto/md5": {}, - "crypto/mlkem": {}, - "crypto/pbkdf2": {}, - "crypto/rand": {}, - "crypto/rc4": {}, - "crypto/rsa": {}, - "crypto/sha1": {}, - "crypto/sha256": {}, - "crypto/sha3": {}, - "crypto/sha512": {}, - "crypto/subtle": {}, - "crypto/tls": {}, - "crypto/tls/fipsonly": {}, - "crypto/x509": {}, - "crypto/x509/pkix": {}, - "database/sql": {}, - "database/sql/driver": {}, - "debug/buildinfo": {}, - "debug/dwarf": {}, - "debug/elf": {}, - "debug/gosym": {}, - "debug/macho": {}, - "debug/pe": {}, - "debug/plan9obj": {}, - "embed": {}, - "encoding": {}, - "encoding/ascii85": {}, - "encoding/asn1": {}, - "encoding/base32": {}, - "encoding/base64": {}, - "encoding/binary": {}, - "encoding/csv": {}, - "encoding/gob": {}, - "encoding/hex": {}, - "encoding/json": {}, - "encoding/pem": {}, - "encoding/xml": {}, - "errors": {}, - "expvar": {}, - "flag": {}, - "fmt": {}, - "go/ast": {}, - "go/build": {}, - "go/build/constraint": {}, - "go/constant": {}, - "go/doc": {}, - "go/doc/comment": {}, - "go/format": {}, - "go/importer": {}, - "go/parser": {}, - "go/printer": {}, - "go/scanner": {}, - "go/token": {}, - "go/types": {}, - "go/version": {}, - "hash": {}, - "hash/adler32": {}, - "hash/crc32": {}, - "hash/crc64": {}, - "hash/fnv": {}, - "hash/maphash": {}, - "html": {}, - "html/template": {}, - "image": {}, - "image/color": {}, - "image/color/palette": {}, - "image/draw": {}, - "image/gif": {}, - "image/jpeg": {}, - "image/png": {}, - "index/suffixarray": {}, - "io": {}, - "io/fs": {}, - "io/ioutil": {}, - "iter": {}, - "log": {}, - "log/slog": {}, - "log/syslog": {}, - "maps": {}, - "math": {}, - "math/big": {}, - "math/bits": {}, - "math/cmplx": {}, - "math/rand": {}, - "math/rand/v2": {}, - "mime": {}, - "mime/multipart": {}, - "mime/quotedprintable": {}, - "net": {}, - "net/http": {}, - "net/http/cgi": {}, - "net/http/cookiejar": {}, - "net/http/fcgi": {}, - "net/http/httptest": {}, - "net/http/httptrace": {}, - "net/http/httputil": {}, - "net/http/pprof": {}, - "net/mail": {}, - "net/netip": {}, - "net/rpc": {}, - "net/rpc/jsonrpc": {}, - "net/smtp": {}, - "net/textproto": {}, - "net/url": {}, - "os": {}, - "os/exec": {}, - "os/signal": {}, - "os/user": {}, - "path": {}, - "path/filepath": {}, - "plugin": {}, - "reflect": {}, - "regexp": {}, - "regexp/syntax": {}, - "runtime": {}, - "runtime/cgo": {}, - "runtime/coverage": {}, - "runtime/debug": {}, - "runtime/metrics": {}, - "runtime/pprof": {}, - "runtime/race": {}, - "runtime/trace": {}, - "slices": {}, - "sort": {}, - "strconv": {}, - "strings": {}, - "structs": {}, - "sync": {}, - "sync/atomic": {}, - "syscall": {}, - "testing": {}, - "testing/fstest": {}, - "testing/iotest": {}, - "testing/quick": {}, - "testing/slogtest": {}, - "testing/synctest": {}, - "text/scanner": {}, - "text/tabwriter": {}, - "text/template": {}, - "text/template/parse": {}, - "time": {}, - "time/tzdata": {}, - "unicode": {}, - "unicode/utf16": {}, - "unicode/utf8": {}, - "unique": {}, - "unsafe": {}, - "weak": {}, + "archive/tar": {}, + "archive/zip": {}, + "arena": {}, + "bufio": {}, + "bytes": {}, + "cmp": {}, + "compress/bzip2": {}, + "compress/flate": {}, + "compress/gzip": {}, + "compress/lzw": {}, + "compress/zlib": {}, + "container/heap": {}, + "container/list": {}, + "container/ring": {}, + "context": {}, + "crypto": {}, + "crypto/aes": {}, + "crypto/boring": {}, + "crypto/cipher": {}, + "crypto/des": {}, + "crypto/dsa": {}, + "crypto/ecdh": {}, + "crypto/ecdsa": {}, + "crypto/ed25519": {}, + "crypto/elliptic": {}, + "crypto/fips140": {}, + "crypto/hkdf": {}, + "crypto/hmac": {}, + "crypto/md5": {}, + "crypto/mlkem": {}, + "crypto/pbkdf2": {}, + "crypto/rand": {}, + "crypto/rc4": {}, + "crypto/rsa": {}, + "crypto/sha1": {}, + "crypto/sha256": {}, + "crypto/sha3": {}, + "crypto/sha512": {}, + "crypto/subtle": {}, + "crypto/tls": {}, + "crypto/tls/fipsonly": {}, + "crypto/x509": {}, + "crypto/x509/pkix": {}, + "database/sql": {}, + "database/sql/driver": {}, + "debug/buildinfo": {}, + "debug/dwarf": {}, + "debug/elf": {}, + "debug/gosym": {}, + "debug/macho": {}, + "debug/pe": {}, + "debug/plan9obj": {}, + "embed": {}, + "encoding": {}, + "encoding/ascii85": {}, + "encoding/asn1": {}, + "encoding/base32": {}, + "encoding/base64": {}, + "encoding/binary": {}, + "encoding/csv": {}, + "encoding/gob": {}, + "encoding/hex": {}, + "encoding/json": {}, + "encoding/json/jsontext": {}, + "encoding/json/v2": {}, + "encoding/pem": {}, + "encoding/xml": {}, + "errors": {}, + "expvar": {}, + "flag": {}, + "fmt": {}, + "go/ast": {}, + "go/build": {}, + "go/build/constraint": {}, + "go/constant": {}, + "go/doc": {}, + "go/doc/comment": {}, + "go/format": {}, + "go/importer": {}, + "go/parser": {}, + "go/printer": {}, + "go/scanner": {}, + "go/token": {}, + "go/types": {}, + "go/version": {}, + "hash": {}, + "hash/adler32": {}, + "hash/crc32": {}, + "hash/crc64": {}, + "hash/fnv": {}, + "hash/maphash": {}, + "html": {}, + "html/template": {}, + "image": {}, + "image/color": {}, + "image/color/palette": {}, + "image/draw": {}, + "image/gif": {}, + "image/jpeg": {}, + "image/png": {}, + "index/suffixarray": {}, + "io": {}, + "io/fs": {}, + "io/ioutil": {}, + "iter": {}, + "log": {}, + "log/slog": {}, + "log/syslog": {}, + "maps": {}, + "math": {}, + "math/big": {}, + "math/bits": {}, + "math/cmplx": {}, + "math/rand": {}, + "math/rand/v2": {}, + "mime": {}, + "mime/multipart": {}, + "mime/quotedprintable": {}, + "net": {}, + "net/http": {}, + "net/http/cgi": {}, + "net/http/cookiejar": {}, + "net/http/fcgi": {}, + "net/http/httptest": {}, + "net/http/httptrace": {}, + "net/http/httputil": {}, + "net/http/pprof": {}, + "net/mail": {}, + "net/netip": {}, + "net/rpc": {}, + "net/rpc/jsonrpc": {}, + "net/smtp": {}, + "net/textproto": {}, + "net/url": {}, + "os": {}, + "os/exec": {}, + "os/signal": {}, + "os/user": {}, + "path": {}, + "path/filepath": {}, + "plugin": {}, + "reflect": {}, + "regexp": {}, + "regexp/syntax": {}, + "runtime": {}, + "runtime/cgo": {}, + "runtime/coverage": {}, + "runtime/debug": {}, + "runtime/metrics": {}, + "runtime/pprof": {}, + "runtime/race": {}, + "runtime/trace": {}, + "slices": {}, + "sort": {}, + "strconv": {}, + "strings": {}, + "structs": {}, + "sync": {}, + "sync/atomic": {}, + "syscall": {}, + "syscall/js": {}, + "testing": {}, + "testing/fstest": {}, + "testing/iotest": {}, + "testing/quick": {}, + "testing/slogtest": {}, + "testing/synctest": {}, + "text/scanner": {}, + "text/tabwriter": {}, + "text/template": {}, + "text/template/parse": {}, + "time": {}, + "time/tzdata": {}, + "unicode": {}, + "unicode/utf16": {}, + "unicode/utf8": {}, + "unique": {}, + "unsafe": {}, + "weak": {}, } diff --git a/vendor/github.com/ghostiam/protogetter/flake.lock b/vendor/github.com/ghostiam/protogetter/flake.lock index 46930d254..664ccdaa6 100644 --- a/vendor/github.com/ghostiam/protogetter/flake.lock +++ b/vendor/github.com/ghostiam/protogetter/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1741513245, - "narHash": "sha256-7rTAMNTY1xoBwz0h7ZMtEcd8LELk9R5TzBPoHuhNSCk=", + "lastModified": 1759381078, + "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e3e32b642a31e6714ec1b712de8c91a3352ce7e1", + "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "type": "github" }, "original": { diff --git a/vendor/github.com/ghostiam/protogetter/flake.nix b/vendor/github.com/ghostiam/protogetter/flake.nix index 3e2a6ce66..4bbe48500 100644 --- a/vendor/github.com/ghostiam/protogetter/flake.nix +++ b/vendor/github.com/ghostiam/protogetter/flake.nix @@ -16,6 +16,7 @@ system: let pkgs = import nixpkgs { inherit system; }; + go = pkgs.go_1_24; buildInputs = with pkgs; [ go coreutils @@ -35,7 +36,7 @@ export FLAKE_ROOT="$(nix flake metadata | grep 'Resolved URL' | awk '{print $3}' | sed 's/^path://' | sed 's/^git+file:\/\///')" export HISTFILE="$FLAKE_ROOT/.nix_bash_history" - export GOROOT="${pkgs.go}/share/go" + export GOROOT="${go}/share/go" ''; in { @@ -57,7 +58,7 @@ cd "$FLAKE_ROOT" echo "Replace GOPATH" - xmlstarlet ed -L -u '//project/component[@name="GOROOT"]/@url' -v 'file://${pkgs.go}/share/go' .idea/workspace.xml + xmlstarlet ed -L -u '//project/component[@name="GOROOT"]/@url' -v 'file://${go}/share/go' .idea/workspace.xml exit 0 '' diff --git a/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go index 9be45ccc7..22a6267fd 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go @@ -87,7 +87,8 @@ func (c *badCondChecker) checkExpr(expr ast.Expr) { func (c *badCondChecker) equalToBoth(lhs, rhs *ast.BinaryExpr) bool { return lhs.Op == token.EQL && rhs.Op == token.EQL && - astequal.Expr(lhs.X, rhs.X) + astequal.Expr(lhs.X, rhs.X) && + typep.SideEffectFree(c.ctx.TypesInfo, lhs.Y) && typep.SideEffectFree(c.ctx.TypesInfo, rhs.Y) } func (c *badCondChecker) lessAndGreater(lhs, rhs *ast.BinaryExpr) bool { diff --git a/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go index 6c6845053..8f5cf97f6 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go @@ -148,7 +148,7 @@ func (c *badRegexpChecker) walk(e syntax.Expr) { case syntax.OpCaret: if !c.isGoodAnchor(e) { - c.warn("dangling or redundant ^, maybe \\^ is intended?") + c.warnf("dangling or redundant ^, maybe \\^ is intended?") } default: @@ -176,11 +176,11 @@ func (c *badRegexpChecker) updateFlagState(state *regexpFlagState, e syntax.Expr if clearing { if !state[ch] { - c.warn("clearing unset flag %c in %s", ch, e.Value) + c.warnf("clearing unset flag %c in %s", ch, e.Value) } } else { if state[ch] { - c.warn("redundant flag %c in %s", ch, e.Value) + c.warnf("redundant flag %c in %s", ch, e.Value) } } state[ch] = !clearing @@ -198,7 +198,7 @@ func (c *badRegexpChecker) checkNestedQuantifier(e syntax.Expr) { switch x.Op { case syntax.OpPlus, syntax.OpStar: - c.warn("repeated greedy quantifier in %s", e.Value) + c.warnf("repeated greedy quantifier in %s", e.Value) } } @@ -208,7 +208,7 @@ func (c *badRegexpChecker) checkAltDups(alt syntax.Expr) { set := make(map[string]struct{}, len(alt.Args)) for _, a := range alt.Args { if _, ok := set[a.Value]; ok { - c.warn("`%s` is duplicated in %s", a.Value, alt.Value) + c.warnf("`%s` is duplicated in %s", a.Value, alt.Value) } set[a.Value] = struct{}{} } @@ -232,7 +232,7 @@ func (c *badRegexpChecker) checkAltAnchor(alt syntax.Expr) { } } if matched { - c.warn("^ applied only to `%s` in %s", first.Value[len(`^`):], alt.Value) + c.warnf("^ applied only to `%s` in %s", first.Value[len(`^`):], alt.Value) } } @@ -247,7 +247,7 @@ func (c *badRegexpChecker) checkAltAnchor(alt syntax.Expr) { } } if matched { - c.warn("$ applied only to `%s` in %s", last.Value[:len(last.Value)-len(`$`)], alt.Value) + c.warnf("$ applied only to `%s` in %s", last.Value[:len(last.Value)-len(`$`)], alt.Value) } } } @@ -429,7 +429,7 @@ func (c *badRegexpChecker) isGoodAnchor(e syntax.Expr) bool { return false } -func (c *badRegexpChecker) warn(format string, args ...interface{}) { +func (c *badRegexpChecker) warnf(format string, args ...interface{}) { c.ctx.Warn(c.cause, format, args...) } diff --git a/vendor/github.com/go-critic/go-critic/checkers/checkers.go b/vendor/github.com/go-critic/go-critic/checkers/checkers.go index 5797dafdf..751c71501 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/checkers.go +++ b/vendor/github.com/go-critic/go-critic/checkers/checkers.go @@ -1,4 +1,4 @@ -// Package checkers is a gocritic linter main checkers collection. +// Package checkers is a go-critic linter main checkers collection. package checkers import ( diff --git a/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go b/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go index c61d773da..bb41d478e 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go @@ -8,6 +8,8 @@ import ( "github.com/go-critic/go-critic/linter" ) +const deprecatedPrefix = "Deprecated: " + func init() { var info linter.CheckerInfo info.Name = "deprecatedComment" @@ -91,20 +93,25 @@ func (c *deprecatedCommentChecker) VisitDocComment(doc *ast.CommentGroup) { // // TODO(quasilyte): there are also multi-line deprecation comments. + // prev stores the previous line after it was trimmed. + // It's used to check whether the deprecation prefix is at the beginning of a new paragraph. + var prev string + for _, comment := range doc.List { if strings.HasPrefix(comment.Text, "/*") { // TODO(quasilyte): handle multi-line doc comments. continue } - l := comment.Text[len("//"):] - if len(l) < len("Deprecated: ") { + rawLine := strings.TrimPrefix(comment.Text, "//") + l := strings.TrimSpace(rawLine) + if len(rawLine) < len(deprecatedPrefix) { + prev = l continue } - l = strings.TrimSpace(l) // Check whether someone messed up with a prefix casing. upcase := strings.ToUpper(l) - if strings.HasPrefix(upcase, "DEPRECATED: ") && !strings.HasPrefix(l, "Deprecated: ") { + if strings.HasPrefix(upcase, "DEPRECATED: ") && !strings.HasPrefix(l, deprecatedPrefix) { c.warnCasing(comment, l) return } @@ -134,6 +141,12 @@ func (c *deprecatedCommentChecker) VisitDocComment(doc *ast.CommentGroup) { return } } + + if strings.HasPrefix(l, deprecatedPrefix) && prev != "" { + c.warnParagraph(comment) + return + } + prev = l } } @@ -154,3 +167,7 @@ func (c *deprecatedCommentChecker) warnTypo(cause ast.Node, line string) { word := strings.Split(line, ":")[0] c.ctx.Warn(cause, "typo in `%s`; should be `Deprecated`", word) } + +func (c *deprecatedCommentChecker) warnParagraph(cause ast.Node) { + c.ctx.Warn(cause, "`Deprecated: ` notices should be in a dedicated paragraph, separated from the rest") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupOption_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupOption_checker.go new file mode 100644 index 000000000..5e7eeda16 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/dupOption_checker.go @@ -0,0 +1,118 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-critic/go-critic/checkers/internal/astwalk" + "github.com/go-critic/go-critic/linter" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astfmt" +) + +func init() { + var info linter.CheckerInfo + info.Name = "dupOption" + info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag} + info.Summary = "Detects duplicated option function arguments in variadic function calls" + info.Before = `doSomething(name, + withWidth(w), + withHeight(h), + withWidth(w), +)` + info.After = `doSomething(name, + withWidth(w), + withHeight(h), +)` + + collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { + c := &dupOptionChecker{ctx: ctx} + return astwalk.WalkerForExpr(c), nil + }) +} + +type dupOptionChecker struct { + astwalk.WalkHandler + ctx *linter.CheckerContext +} + +func (c *dupOptionChecker) VisitExpr(expr ast.Expr) { + call := astcast.ToCallExpr(expr) + variadicArgs, argType := c.getVariadicArgs(call) + if len(variadicArgs) == 0 { + return + } + + if !c.isOptionType(argType) { + return + } + + dupArgs := c.findDupArgs(variadicArgs) + for _, arg := range dupArgs { + c.warn(arg) + } +} + +func (c *dupOptionChecker) getVariadicArgs(call *ast.CallExpr) ([]ast.Expr, types.Type) { + if len(call.Args) == 0 { + return nil, nil + } + + // skip for someFunc(a, b ...) + if call.Ellipsis != token.NoPos { + return nil, nil + } + + funType := c.ctx.TypeOf(call.Fun) + sign, ok := funType.(*types.Signature) + if !ok || !sign.Variadic() { + return nil, nil + } + + last := sign.Params().Len() - 1 + sliceType, ok := sign.Params().At(last).Type().(*types.Slice) + if !ok { + return nil, nil + } + + if last > len(call.Args) { + return nil, nil + } + + argType := sliceType.Elem() + return call.Args[last:], argType +} + +func (c *dupOptionChecker) isOptionType(typeInfo types.Type) bool { + typeInfo = typeInfo.Underlying() + + sign, ok := typeInfo.(*types.Signature) + if !ok { + return false + } + + if sign.Params().Len() == 0 { + return false + } + + return true +} + +func (c *dupOptionChecker) findDupArgs(args []ast.Expr) []ast.Expr { + codeMap := make(map[string]bool) + dupArgs := make([]ast.Expr, 0) + for _, arg := range args { + code := astfmt.Sprint(arg) + if codeMap[code] { + dupArgs = append(dupArgs, arg) + continue + } + codeMap[code] = true + } + return dupArgs +} + +func (c *dupOptionChecker) warn(arg ast.Node) { + c.ctx.Warn(arg, "function argument `%s` is duplicated", arg) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go b/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go index 9889f48e8..19b20e425 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go @@ -45,6 +45,12 @@ func (c *exitAfterDeferChecker) VisitFuncDecl(fn *ast.FuncDecl) { var deferStmt *ast.DeferStmt pre := func(cur *astutil.Cursor) bool { + // If we found a defer statement in the function post traversal. + // and are looking at the Else branch during a pre traversal, stop seeking as it could be false positive. + if deferStmt != nil && cur.Name() == "Else" { + return false + } + // Don't recurse into local anonymous functions. return !astp.IsFuncLit(cur.Node()) } diff --git a/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go b/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go index ace418d48..664145858 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go +++ b/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go @@ -2521,6 +2521,61 @@ var PrecompiledRules = &ir.File{ }, }, }, + { + Line: 799, + Name: "zeroByteRepeat", + MatcherName: "m", + DocTags: []string{"performance"}, + DocSummary: "Detects bytes.Repeat with 0 value", + DocBefore: "bytes.Repeat([]byte{0}, x)", + DocAfter: "make([]byte, x)", + Rules: []ir.Rule{ + { + Line: 800, + SyntaxPatterns: []ir.PatternString{{Line: 800, Value: "bytes.Repeat([]byte{0}, $x)"}}, + ReportTemplate: "avoid bytes.Repeat([]byte{0}, $x); consider using make([]byte, $x) instead", + SuggestTemplate: "make([]byte, $x)", + }, + { + Line: 805, + SyntaxPatterns: []ir.PatternString{{Line: 805, Value: "bytes.Repeat([]byte{$x}, $n)"}}, + ReportTemplate: "avoid bytes.Repeat with a const 0; use make([]byte, $n) instead", + SuggestTemplate: "make([]byte, $n)", + WhereExpr: ir.FilterExpr{ + Line: 806, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Const && m[\"x\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + { + Line: 806, + Op: ir.FilterVarConstOp, + Src: "m[\"x\"].Const", + Value: "x", + }, + { + Line: 806, + Op: ir.FilterEqOp, + Src: "m[\"x\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + { + Line: 806, + Op: ir.FilterVarValueIntOp, + Src: "m[\"x\"].Value.Int()", + Value: "x", + }, + { + Line: 806, + Op: ir.FilterIntOp, + Src: "0", + Value: int64(0), + }, + }, + }, + }, + }, + }, + }, + }, }, } diff --git a/vendor/github.com/go-critic/go-critic/linter/linter.go b/vendor/github.com/go-critic/go-critic/linter/linter.go index d4bc17536..c751d94cc 100644 --- a/vendor/github.com/go-critic/go-critic/linter/linter.go +++ b/vendor/github.com/go-critic/go-critic/linter/linter.go @@ -249,8 +249,8 @@ func NewContext(fset *token.FileSet, sizes types.Sizes) *Context { // It's permitted to have "go" prefix (e.g. "go1.5"). // // Empty string (the default) means that we make no -// Go version assumptions and (like gocritic does) behave -// like all features are available. To make gocritic +// Go version assumptions and (like go-critic does) behave +// like all features are available. To make go-critic // more conservative, the upper Go version level should be adjusted. func (c *Context) SetGoVersion(version string) { v, err := ParseGoVersion(version) diff --git a/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig index 1f664d13a..faef0c91e 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/.editorconfig +++ b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig @@ -16,3 +16,6 @@ indent_style = tab [*.nix] indent_size = 2 + +[.golangci.yaml] +indent_size = 2 diff --git a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml index 763143aa7..bda962566 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml +++ b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml @@ -1,23 +1,48 @@ -run: - timeout: 5m +version: "2" -linters-settings: - gci: - sections: - - standard - - default - - prefix(github.com/go-viper/mapstructure) - golint: - min-confidence: 0 - goimports: - local-prefixes: github.com/go-viper/maptstructure +run: + timeout: 10m linters: - disable-all: true + enable: + - govet + - ineffassign + # - misspell + - nolintlint + # - revive + + disable: + - errcheck + - staticcheck + - unused + + settings: + misspell: + locale: US + nolintlint: + allow-unused: false # report any unused nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + +formatters: enable: - gci - gofmt - gofumpt - goimports - - staticcheck - # - stylecheck + # - golines + + settings: + gci: + sections: + - standard + - default + - localmodule + gofmt: + simplify: true + rewrite-rules: + - pattern: interface{} + replacement: any + + exclusions: + paths: + - internal/ diff --git a/vendor/github.com/go-viper/mapstructure/v2/README.md b/vendor/github.com/go-viper/mapstructure/v2/README.md index dd5ec69dd..45db71975 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/README.md +++ b/vendor/github.com/go-viper/mapstructure/v2/README.md @@ -1,8 +1,9 @@ # mapstructure -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml) [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2) mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. @@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else. Here is a script that can help you with the migration: ```shell -sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go') +sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go') ``` If you need more time to migrate your code, that is absolutely fine. diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go index 1f3c69d4b..a852a0a04 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go +++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -13,7 +13,7 @@ import ( "time" ) -// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns // it into the proper DecodeHookFunc type, such as DecodeHookFuncType. func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Create variables here so we can reference them with the reflect pkg @@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Fill in the variables into this interface and the rest is done // automatically using the reflect package. - potential := []interface{}{f1, f2, f3} + potential := []any{f1, f2, f3} v := reflect.ValueOf(h) vt := v.Type() @@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { return nil } -// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns // it into a closure to be used directly // if the type fails to convert we return a closure always erroring to keep the previous behaviour -func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) { +func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) { switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from.Type(), to.Type(), from.Interface()) } case DecodeHookFuncKind: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from.Kind(), to.Kind(), from.Interface()) } case DecodeHookFuncValue: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from, to) } default: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return nil, errors.New("invalid decode hook signature") } } @@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va func DecodeHookExec( raw DecodeHookFunc, from reflect.Value, to reflect.Value, -) (interface{}, error) { +) (any, error) { switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: return f(from.Type(), to.Type(), from.Interface()) @@ -86,11 +86,11 @@ func DecodeHookExec( // The composed funcs are called in order, with the result of the // previous transformation. func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { - cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs)) + cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs)) for _, f := range fs { cached = append(cached, cachedDecodeHook(f)) } - return func(f reflect.Value, t reflect.Value) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (any, error) { var err error data := f.Interface() @@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { if err != nil { return nil, err } - newFrom = reflect.ValueOf(data) + if v, ok := data.(reflect.Value); ok { + newFrom = v + } else { + newFrom = reflect.ValueOf(data) + } } return data, nil @@ -110,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { - cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff)) + cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff)) for _, f := range ff { cached = append(cached, cachedDecodeHook(f)) } - return func(a, b reflect.Value) (interface{}, error) { + return func(a, b reflect.Value) (any, error) { var allErrs string - var out interface{} + var out any var err error for _, c := range cached { @@ -139,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -157,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc { } } +// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc]. +// +// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice. +// This function removes that check. +func StringToWeakSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + // StringToTimeDurationHookFunc returns a DecodeHookFunc that converts // strings to time.Duration. func StringToTimeDurationHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -173,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc { } // Convert it by parsing - return time.ParseDuration(data.(string)) + d, err := time.ParseDuration(data.(string)) + + return d, wrapTimeParseDurationError(err) + } +} + +// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts +// strings to *time.Location. +func StringToTimeLocationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Local) { + return data, nil + } + d, err := time.LoadLocation(data.(string)) + + return d, wrapTimeParseLocationError(err) } } @@ -183,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -193,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc { } // Convert it by parsing - return url.Parse(data.(string)) + u, err := url.Parse(data.(string)) + + return u, wrapUrlError(err) } } @@ -203,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -215,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc { // Convert it by parsing ip := net.ParseIP(data.(string)) if ip == nil { - return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + return net.IP{}, fmt.Errorf("failed parsing ip") } return ip, nil @@ -228,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -239,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc { // Convert it by parsing _, net, err := net.ParseCIDR(data.(string)) - return net, err + return net, wrapNetParseError(err) } } @@ -249,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -259,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { } // Convert it by parsing - return time.Parse(layout, data.(string)) + ti, err := time.Parse(layout, data.(string)) + + return ti, wrapTimeParseError(err) } } @@ -271,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { func WeaklyTypedHook( f reflect.Kind, t reflect.Kind, - data interface{}, -) (interface{}, error) { + data any, +) (any, error) { dataVal := reflect.ValueOf(data) switch t { case reflect.String: @@ -301,17 +354,17 @@ func WeaklyTypedHook( } func RecursiveStructToMapHookFunc() DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (any, error) { if f.Kind() != reflect.Struct { return f.Interface(), nil } - var i interface{} = struct{}{} + var i any = struct{}{} if t.Type() != reflect.TypeOf(&i).Elem() { return f.Interface(), nil } - m := make(map[string]interface{}) + m := make(map[string]any) t.Set(reflect.ValueOf(m)) return f.Interface(), nil @@ -325,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -352,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -362,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParseAddr(data.(string)) + addr, err := netip.ParseAddr(data.(string)) + + return addr, wrapNetIPParseAddrError(err) } } @@ -372,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -382,7 +437,31 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParseAddrPort(data.(string)) + addrPort, err := netip.ParseAddrPort(data.(string)) + + return addrPort, wrapNetIPParseAddrPortError(err) + } +} + +// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts +// strings to netip.Prefix. +func StringToNetIPPrefixHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.Prefix{}) { + return data, nil + } + + // Convert it by parsing + prefix, err := netip.ParsePrefix(data.(string)) + + return prefix, wrapNetIPParsePrefixError(err) } } @@ -415,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc { // StringToInt8HookFunc returns a DecodeHookFunc that converts // strings to int8. func StringToInt8HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int8 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 8) - return int8(i64), err + return int8(i64), wrapStrconvNumError(err) } } // StringToUint8HookFunc returns a DecodeHookFunc that converts // strings to uint8. func StringToUint8HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 8) - return uint8(u64), err + return uint8(u64), wrapStrconvNumError(err) } } // StringToInt16HookFunc returns a DecodeHookFunc that converts // strings to int16. func StringToInt16HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int16 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 16) - return int16(i64), err + return int16(i64), wrapStrconvNumError(err) } } // StringToUint16HookFunc returns a DecodeHookFunc that converts // strings to uint16. func StringToUint16HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 16) - return uint16(u64), err + return uint16(u64), wrapStrconvNumError(err) } } // StringToInt32HookFunc returns a DecodeHookFunc that converts // strings to int32. func StringToInt32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int32 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 32) - return int32(i64), err + return int32(i64), wrapStrconvNumError(err) } } // StringToUint32HookFunc returns a DecodeHookFunc that converts // strings to uint32. func StringToUint32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 32) - return uint32(u64), err + return uint32(u64), wrapStrconvNumError(err) } } // StringToInt64HookFunc returns a DecodeHookFunc that converts // strings to int64. func StringToInt64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int64 { return data, nil } // Convert it by parsing - return strconv.ParseInt(data.(string), 0, 64) + i64, err := strconv.ParseInt(data.(string), 0, 64) + return int64(i64), wrapStrconvNumError(err) } } // StringToUint64HookFunc returns a DecodeHookFunc that converts // strings to uint64. func StringToUint64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 { return data, nil } // Convert it by parsing - return strconv.ParseUint(data.(string), 0, 64) + u64, err := strconv.ParseUint(data.(string), 0, 64) + return uint64(u64), wrapStrconvNumError(err) } } // StringToIntHookFunc returns a DecodeHookFunc that converts // strings to int. func StringToIntHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 0) - return int(i64), err + return int(i64), wrapStrconvNumError(err) } } // StringToUintHookFunc returns a DecodeHookFunc that converts // strings to uint. func StringToUintHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 0) - return uint(u64), err + return uint(u64), wrapStrconvNumError(err) } } // StringToFloat32HookFunc returns a DecodeHookFunc that converts // strings to float32. func StringToFloat32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Float32 { return data, nil } // Convert it by parsing f64, err := strconv.ParseFloat(data.(string), 32) - return float32(f64), err + return float32(f64), wrapStrconvNumError(err) } } // StringToFloat64HookFunc returns a DecodeHookFunc that converts // strings to float64. func StringToFloat64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Float64 { return data, nil } // Convert it by parsing - return strconv.ParseFloat(data.(string), 64) + f64, err := strconv.ParseFloat(data.(string), 64) + return f64, wrapStrconvNumError(err) } } // StringToBoolHookFunc returns a DecodeHookFunc that converts // strings to bool. func StringToBoolHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Bool { return data, nil } // Convert it by parsing - return strconv.ParseBool(data.(string)) + b, err := strconv.ParseBool(data.(string)) + return b, wrapStrconvNumError(err) } } @@ -605,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc { // StringToComplex64HookFunc returns a DecodeHookFunc that converts // strings to complex64. func StringToComplex64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 { return data, nil } // Convert it by parsing c128, err := strconv.ParseComplex(data.(string), 64) - return complex64(c128), err + return complex64(c128), wrapStrconvNumError(err) } } // StringToComplex128HookFunc returns a DecodeHookFunc that converts // strings to complex128. func StringToComplex128HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 { return data, nil } // Convert it by parsing - return strconv.ParseComplex(data.(string), 128) + c128, err := strconv.ParseComplex(data.(string), 128) + return c128, wrapStrconvNumError(err) } } diff --git a/vendor/github.com/go-viper/mapstructure/v2/errors.go b/vendor/github.com/go-viper/mapstructure/v2/errors.go new file mode 100644 index 000000000..07d31c22a --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/errors.go @@ -0,0 +1,244 @@ +package mapstructure + +import ( + "errors" + "fmt" + "net" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +// Error interface is implemented by all errors emitted by mapstructure. +// +// Use [errors.As] to check if an error implements this interface. +type Error interface { + error + + mapstructure() +} + +// DecodeError is a generic error type that holds information about +// a decoding error together with the name of the field that caused the error. +type DecodeError struct { + name string + err error +} + +func newDecodeError(name string, err error) *DecodeError { + return &DecodeError{ + name: name, + err: err, + } +} + +func (e *DecodeError) Name() string { + return e.name +} + +func (e *DecodeError) Unwrap() error { + return e.err +} + +func (e *DecodeError) Error() string { + return fmt.Sprintf("'%s' %s", e.name, e.err) +} + +func (*DecodeError) mapstructure() {} + +// ParseError is an error type that indicates a value could not be parsed +// into the expected type. +type ParseError struct { + Expected reflect.Value + Value any + Err error +} + +func (e *ParseError) Error() string { + return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err) +} + +func (*ParseError) mapstructure() {} + +// UnconvertibleTypeError is an error type that indicates a value could not be +// converted to the expected type. +type UnconvertibleTypeError struct { + Expected reflect.Value + Value any +} + +func (e *UnconvertibleTypeError) Error() string { + return fmt.Sprintf( + "expected type '%s', got unconvertible type '%s'", + e.Expected.Type(), + reflect.TypeOf(e.Value), + ) +} + +func (*UnconvertibleTypeError) mapstructure() {} + +func wrapStrconvNumError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*strconv.NumError); ok { + return &strconvNumError{Err: err} + } + + return err +} + +type strconvNumError struct { + Err *strconv.NumError +} + +func (e *strconvNumError) Error() string { + return "strconv." + e.Err.Func + ": " + e.Err.Err.Error() +} + +func (e *strconvNumError) Unwrap() error { return e.Err } + +func wrapUrlError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*url.Error); ok { + return &urlError{Err: err} + } + + return err +} + +type urlError struct { + Err *url.Error +} + +func (e *urlError) Error() string { + return fmt.Sprintf("%s", e.Err.Err) +} + +func (e *urlError) Unwrap() error { return e.Err } + +func wrapNetParseError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*net.ParseError); ok { + return &netParseError{Err: err} + } + + return err +} + +type netParseError struct { + Err *net.ParseError +} + +func (e *netParseError) Error() string { + return "invalid " + e.Err.Type +} + +func (e *netParseError) Unwrap() error { return e.Err } + +func wrapTimeParseError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*time.ParseError); ok { + return &timeParseError{Err: err} + } + + return err +} + +type timeParseError struct { + Err *time.ParseError +} + +func (e *timeParseError) Error() string { + if e.Err.Message == "" { + return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem) + } + + return "parsing time " + e.Err.Message +} + +func (e *timeParseError) Unwrap() error { return e.Err } + +func wrapNetIPParseAddrError(err error) error { + if err == nil { + return nil + } + + if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") { + errPieces := strings.Split(errMsg, ": ") + + return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1]) + } + + return err +} + +func wrapNetIPParseAddrPortError(err error) error { + if err == nil { + return nil + } + + errMsg := err.Error() + if strings.HasPrefix(errMsg, "invalid port ") { + return errors.New("invalid port") + } else if strings.HasPrefix(errMsg, "invalid ip:port ") { + return errors.New("invalid ip:port") + } + + return err +} + +func wrapNetIPParsePrefixError(err error) error { + if err == nil { + return nil + } + + if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") { + errPieces := strings.Split(errMsg, ": ") + + return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1]) + } + + return err +} + +func wrapTimeParseDurationError(err error) error { + if err == nil { + return nil + } + + errMsg := err.Error() + if strings.HasPrefix(errMsg, "time: unknown unit ") { + return errors.New("time: unknown unit") + } else if strings.HasPrefix(errMsg, "time: ") { + idx := strings.LastIndex(errMsg, " ") + + return errors.New(errMsg[:idx]) + } + + return err +} + +func wrapTimeParseLocationError(err error) error { + if err == nil { + return nil + } + errMsg := err.Error() + if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") { + return fmt.Errorf("invalid time zone format: %w", err) + } + + return err +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/vendor/github.com/go-viper/mapstructure/v2/flake.lock index 4bea8154e..5e67bdd6b 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/flake.lock +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.lock @@ -2,30 +2,28 @@ "nodes": { "cachix": { "inputs": { - "devenv": "devenv_2", + "devenv": [ + "devenv" + ], "flake-compat": [ - "devenv", - "flake-compat" + "devenv" ], - "nixpkgs": [ - "devenv", - "nixpkgs" + "git-hooks": [ + "devenv" ], - "pre-commit-hooks": [ - "devenv", - "pre-commit-hooks" - ] + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1712055811, - "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "lastModified": 1742042642, + "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=", "owner": "cachix", "repo": "cachix", - "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203", "type": "github" }, "original": { "owner": "cachix", + "ref": "latest", "repo": "cachix", "type": "github" } @@ -33,52 +31,21 @@ "devenv": { "inputs": { "cachix": "cachix", - "flake-compat": "flake-compat_2", - "nix": "nix_2", - "nixpkgs": "nixpkgs_2", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1717245169, - "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", - "owner": "cachix", - "repo": "devenv", - "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "devenv_2": { - "inputs": { - "flake-compat": [ - "devenv", - "cachix", - "flake-compat" - ], + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", "nix": "nix", - "nixpkgs": "nixpkgs", - "poetry2nix": "poetry2nix", - "pre-commit-hooks": [ - "devenv", - "cachix", - "pre-commit-hooks" - ] + "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1708704632, - "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "lastModified": 1744876578, + "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=", "owner": "cachix", "repo": "devenv", - "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1", "type": "github" }, "original": { "owner": "cachix", - "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -86,27 +53,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -117,14 +68,18 @@ }, "flake-parts": { "inputs": { - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] }, "locked": { - "lastModified": 1717285511, - "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", "type": "github" }, "original": { @@ -133,39 +88,46 @@ "type": "github" } }, - "flake-utils": { + "flake-parts_2": { "inputs": { - "systems": "systems" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "flake-utils_2": { + "git-hooks": { "inputs": { - "systems": "systems_2" + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ] }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "cachix", + "repo": "git-hooks.nix", "type": "github" } }, @@ -173,7 +135,7 @@ "inputs": { "nixpkgs": [ "devenv", - "pre-commit-hooks", + "git-hooks", "nixpkgs" ] }, @@ -191,166 +153,109 @@ "type": "github" } }, - "nix": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1712911606, - "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", - "owner": "domenkozar", - "repo": "nix", - "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "devenv-2.21", - "repo": "nix", - "type": "github" - } - }, - "nix-github-actions": { - "inputs": { - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "poetry2nix", - "nixpkgs" - ] - }, + "libgit2": { + "flake": false, "locked": { - "lastModified": 1688870561, - "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", - "owner": "nix-community", - "repo": "nix-github-actions", - "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nix-github-actions", + "owner": "libgit2", + "repo": "libgit2", "type": "github" } }, - "nix_2": { + "nix": { "inputs": { "flake-compat": [ - "devenv", - "flake-compat" + "devenv" ], - "nixpkgs": [ - "devenv", - "nixpkgs" + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" ], - "nixpkgs-regression": "nixpkgs-regression_2" + "pre-commit-hooks": [ + "devenv" + ] }, "locked": { - "lastModified": 1712911606, - "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "lastModified": 1741798497, + "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=", "owner": "domenkozar", "repo": "nix", - "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "devenv-2.21", + "ref": "devenv-2.24", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1692808169, - "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "lastModified": 1733212471, + "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-lib": { "locked": { - "lastModified": 1717284937, - "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-regression_2": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", "type": "github" }, "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "nixpkgs-stable": { + "nixpkgs_2": { "locked": { - "lastModified": 1710695816, - "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "release-24.05", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_2": { + "nixpkgs_3": { "locked": { - "lastModified": 1713361204, - "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "lastModified": 1733477122, + "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=", "owner": "cachix", "repo": "devenv-nixpkgs", - "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", "type": "github" }, "original": { @@ -360,13 +265,13 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { - "lastModified": 1717112898, - "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", "type": "github" }, "original": { @@ -376,94 +281,11 @@ "type": "github" } }, - "poetry2nix": { - "inputs": { - "flake-utils": "flake-utils", - "nix-github-actions": "nix-github-actions", - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1692876271, - "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "poetry2nix", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils_2", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1713775815, - "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "devenv": "devenv", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_3" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_4" } } }, diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/vendor/github.com/go-viper/mapstructure/v2/flake.nix index 4ed0f5331..3b116f426 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/flake.nix +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.nix @@ -5,35 +5,42 @@ devenv.url = "github:cachix/devenv"; }; - outputs = inputs@{ flake-parts, ... }: + outputs = + inputs@{ flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } { imports = [ inputs.devenv.flakeModule ]; - systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ]; + systems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; - perSystem = { config, self', inputs', pkgs, system, ... }: rec { - devenv.shells = { - default = { - languages = { - go.enable = true; - }; + perSystem = + { pkgs, ... }: + rec { + devenv.shells = { + default = { + languages = { + go.enable = true; + }; - pre-commit.hooks = { - nixpkgs-fmt.enable = true; - }; + pre-commit.hooks = { + nixpkgs-fmt.enable = true; + }; - packages = with pkgs; [ - golangci-lint - ]; + packages = with pkgs; [ + golangci-lint + ]; - # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 - containers = pkgs.lib.mkForce { }; - }; + # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 + containers = pkgs.lib.mkForce { }; + }; - ci = devenv.shells.default; + ci = devenv.shells.default; + }; }; - }; }; } diff --git a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go index e77e63ba3..7c35bce02 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go +++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -1,5 +1,5 @@ // Package mapstructure exposes functionality to convert one arbitrary -// Go type into another, typically to convert a map[string]interface{} +// Go type into another, typically to convert a map[string]any // into a native Go structure. // // The Go structure can be arbitrarily complex, containing slices, @@ -54,8 +54,8 @@ // // This would require an input that looks like below: // -// map[string]interface{}{ -// "person": map[string]interface{}{"name": "alice"}, +// map[string]any{ +// "person": map[string]any{"name": "alice"}, // } // // If your "person" value is NOT nested, then you can append ",squash" to @@ -68,7 +68,7 @@ // // Now the following input would be accepted: // -// map[string]interface{}{ +// map[string]any{ // "name": "alice", // } // @@ -79,7 +79,7 @@ // // Will be decoded into a map: // -// map[string]interface{}{ +// map[string]any{ // "name": "alice", // } // @@ -95,18 +95,18 @@ // // You can also use the ",remain" suffix on your tag to collect all unused // values in a map. The field with this tag MUST be a map type and should -// probably be a "map[string]interface{}" or "map[interface{}]interface{}". +// probably be a "map[string]any" or "map[any]any". // See example below: // // type Friend struct { // Name string -// Other map[string]interface{} `mapstructure:",remain"` +// Other map[string]any `mapstructure:",remain"` // } // // Given the input below, Other would be populated with the other // values that weren't used (everything but "name"): // -// map[string]interface{}{ +// map[string]any{ // "name": "bob", // "address": "123 Maple St.", // } @@ -115,15 +115,36 @@ // // When decoding from a struct to any other value, you may use the // ",omitempty" suffix on your tag to omit that value if it equates to -// the zero value. The zero value of all types is specified in the Go -// specification. +// the zero value, or a zero-length element. The zero value of all types is +// specified in the Go specification. // // For example, the zero type of a numeric type is zero ("0"). If the struct // field value is zero and a numeric type, the field is empty, and it won't -// be encoded into the destination type. +// be encoded into the destination type. And likewise for the URLs field, if the +// slice is nil or empty, it won't be encoded into the destination type. // // type Source struct { -// Age int `mapstructure:",omitempty"` +// Age int `mapstructure:",omitempty"` +// URLs []string `mapstructure:",omitempty"` +// } +// +// # Omit Zero Values +// +// When decoding from a struct to any other value, you may use the +// ",omitzero" suffix on your tag to omit that value if it equates to the zero +// value. The zero value of all types is specified in the Go specification. +// +// For example, the zero type of a numeric type is zero ("0"). If the struct +// field value is zero and a numeric type, the field is empty, and it won't +// be encoded into the destination type. And likewise for the URLs field, if the +// slice is nil, it won't be encoded into the destination type. +// +// Note that if the field is a slice, and it is empty but not nil, it will +// still be encoded into the destination type. +// +// type Source struct { +// Age int `mapstructure:",omitzero"` +// URLs []string `mapstructure:",omitzero"` // } // // # Unexported fields @@ -140,7 +161,7 @@ // // Using this map as input: // -// map[string]interface{}{ +// map[string]any{ // "private": "I will be ignored", // "Public": "I made it through!", // } @@ -183,19 +204,19 @@ import ( // we started with Kinds and then realized Types were the better solution, // but have a promise to not break backwards compat so we now support // both. -type DecodeHookFunc interface{} +type DecodeHookFunc any // DecodeHookFuncType is a DecodeHookFunc which has complete information about // the source and target types. -type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) +type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error) // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the // source and target types. -type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error) // DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target // values. -type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error) // DecoderConfig is the configuration that is used to create a new decoder // and allows customization of various aspects of decoding. @@ -222,6 +243,12 @@ type DecoderConfig struct { // will affect all nested structs as well. ErrorUnset bool + // AllowUnsetPointer, if set to true, will prevent fields with pointer types + // from being reported as unset, even if ErrorUnset is true and the field was + // not present in the input data. This allows pointer fields to be optional + // without triggering an error when they are missing. + AllowUnsetPointer bool + // ZeroFields, if set to true, will zero fields before writing them. // For example, a map will be emptied before decoded values are put in // it. If this is false, a map will be merged. @@ -260,7 +287,7 @@ type DecoderConfig struct { // Result is a pointer to the struct that will contain the decoded // value. - Result interface{} + Result any // The tag name that mapstructure reads for field names. This // defaults to "mapstructure" @@ -292,7 +319,7 @@ type DecoderConfig struct { // up the most basic Decoder. type Decoder struct { config *DecoderConfig - cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error) + cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error) } // Metadata contains information about decoding a structure that @@ -313,7 +340,7 @@ type Metadata struct { // Decode takes an input structure and uses reflection to translate it to // the output structure. output must be a pointer to a map or struct. -func Decode(input interface{}, output interface{}) error { +func Decode(input any, output any) error { config := &DecoderConfig{ Metadata: nil, Result: output, @@ -329,7 +356,7 @@ func Decode(input interface{}, output interface{}) error { // WeakDecode is the same as Decode but is shorthand to enable // WeaklyTypedInput. See DecoderConfig for more info. -func WeakDecode(input, output interface{}) error { +func WeakDecode(input, output any) error { config := &DecoderConfig{ Metadata: nil, Result: output, @@ -346,7 +373,7 @@ func WeakDecode(input, output interface{}) error { // DecodeMetadata is the same as Decode, but is shorthand to // enable metadata collection. See DecoderConfig for more info. -func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { +func DecodeMetadata(input any, output any, metadata *Metadata) error { config := &DecoderConfig{ Metadata: metadata, Result: output, @@ -363,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e // WeakDecodeMetadata is the same as Decode, but is shorthand to // enable both WeaklyTypedInput and metadata collection. See // DecoderConfig for more info. -func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { +func WeakDecodeMetadata(input any, output any, metadata *Metadata) error { config := &DecoderConfig{ Metadata: metadata, Result: output, @@ -430,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { // Decode decodes the given raw interface to the target pointer specified // by the configuration. -func (d *Decoder) Decode(input interface{}) error { +func (d *Decoder) Decode(input any) error { err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) // Retain some of the original behavior when multiple errors ocurr @@ -443,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error { } // isNil returns true if the input is nil or a typed nil pointer. -func isNil(input interface{}) bool { +func isNil(input any) bool { if input == nil { return true } @@ -452,7 +479,7 @@ func isNil(input interface{}) bool { } // Decodes an unknown data type into a specific reflection value. -func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { +func (d *Decoder) decode(name string, input any, outVal reflect.Value) error { var ( inputVal = reflect.ValueOf(input) outputKind = getKind(outVal) @@ -489,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e // Hooks need a valid inputVal, so reset it to zero value of outVal type. switch outputKind { case reflect.Struct, reflect.Map: - var mapVal map[string]interface{} + var mapVal map[string]any inputVal = reflect.ValueOf(mapVal) // create nil map pointer case reflect.Slice, reflect.Array: - var sliceVal []interface{} + var sliceVal []any inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer default: inputVal = reflect.Zero(outVal.Type()) @@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e var err error input, err = d.cachedDecodeHook(inputVal, outVal) if err != nil { - return fmt.Errorf("error decoding '%s': %w", name, err) + return newDecodeError(name, err) } } if isNil(input) { @@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e err = d.decodeFunc(name, input, outVal) default: // If we reached this point then we weren't able to decode it - return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind)) } // If we reached here, then we successfully decoded SOMETHING, so @@ -556,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e // This decodes a basic type (bool, int, string, etc.) and sets the // value to "data" of that type. -func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error { if val.IsValid() && val.Elem().IsValid() { elem := val.Elem() @@ -603,16 +630,17 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) dataValType := dataVal.Type() if !dataValType.AssignableTo(val.Type()) { - return fmt.Errorf( - "'%s' expected type '%s', got '%s'", - name, val.Type(), dataValType) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } val.Set(dataVal) return nil } -func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeString(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -656,15 +684,16 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) } if !converted { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -692,26 +721,34 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er if err == nil { val.SetInt(i) } else { - return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := jn.Int64() if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetInt(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e case dataKind == reflect.Int: i := dataVal.Int() if i < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %d overflows uint", - name, i) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: fmt.Errorf("%d overflows uint", i), + }) } val.SetUint(uint64(i)) case dataKind == reflect.Uint: @@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e case dataKind == reflect.Float32: f := dataVal.Float() if f < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %f overflows uint", - name, f) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: fmt.Errorf("%f overflows uint", f), + }) } val.SetUint(uint64(f)) case dataKind == reflect.Bool && d.config.WeaklyTypedInput: @@ -749,26 +792,34 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e if err == nil { val.SetUint(i) } else { - return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := strconv.ParseUint(string(jn), 0, 64) if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } val.SetUint(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -788,18 +839,23 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e } else if dataVal.String() == "" { val.SetBool(false) } else { - return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'", - name, val, dataVal, data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -827,26 +883,34 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) if err == nil { val.SetFloat(f) } else { - return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := jn.Float64() if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetFloat(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -854,15 +918,16 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value case dataKind == reflect.Complex64: val.SetComplex(dataVal.Complex()) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error { valType := val.Type() valKeyType := valType.Key() valElemType := valType.Elem() @@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er fallthrough default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } } @@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // to the map value. v := dataVal.Field(i) if !v.Type().AssignableTo(valMap.Type().Elem()) { - return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()), + ) } tagValue := f.Tag.Get(d.config.TagName) @@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re continue } + // If "omitzero" is specified in the tag, it ignores zero values. + if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() { + continue + } + // If "squash" is specified in the tag, we squash the field down. squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption) if squash { @@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // The final type must be a struct if v.Kind() != reflect.Struct { - return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("cannot squash non-struct type %q", v.Type()), + ) } } else { if strings.Index(tagValue[index+1:], "remain") != -1 { if v.Kind() != reflect.Map { - return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()), + ) } ptr := v.MapRange() @@ -1094,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re return nil } -func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { +func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) { // If the input data is nil, then we want to just set the output // pointer to be nil as well. isNil := data == nil @@ -1141,20 +1223,21 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b return false, nil } -func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error { // Create an element of the concrete (non pointer) type and decode // into that. Then set the value of the pointer to this type. dataVal := reflect.Indirect(reflect.ValueOf(data)) if val.Type() != dataVal.Type() { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } val.Set(dataVal) return nil } -func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataValKind := dataVal.Kind() valType := val.Type() @@ -1176,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return nil } // Create slice of maps of other sizes - return d.decodeSlice(name, []interface{}{data}, val) + return d.decodeSlice(name, []any{data}, val) case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: return d.decodeSlice(name, []byte(dataVal.String()), val) @@ -1185,12 +1268,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) // and "lift" it into it. i.e. a string becomes a string slice. default: // Just re-try this function with data as a slice. - return d.decodeSlice(name, []interface{}{data}, val) + return d.decodeSlice(name, []any{data}, val) } } - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) + return newDecodeError(name, + fmt.Errorf("source data must be an array or slice, got %s", dataValKind)) } // If the input value is nil, then don't allocate since empty != nil @@ -1228,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return errors.Join(errs...) } -func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataValKind := dataVal.Kind() valType := val.Type() @@ -1253,17 +1336,17 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) // and "lift" it into it. i.e. a string becomes a string array. default: // Just re-try this function with data as a slice. - return d.decodeArray(name, []interface{}{data}, val) + return d.decodeArray(name, []any{data}, val) } } - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) + return newDecodeError(name, + fmt.Errorf("source data must be an array or slice, got %s", dataValKind)) } if dataVal.Len() > arrayType.Len() { - return fmt.Errorf( - "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + return newDecodeError(name, + fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len())) } // Make a new array to hold our result, same size as the original data. @@ -1289,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) return errors.Join(errs...) } -func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) // If the type of the value to write to and the data match directly, @@ -1310,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) // as an intermediary. // Make a new map to hold our result - mapType := reflect.TypeOf((map[string]interface{})(nil)) + mapType := reflect.TypeOf((map[string]any)(nil)) mval := reflect.MakeMap(mapType) // Creating a pointer to a map so that other methods can completely @@ -1328,26 +1411,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) return result default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + return newDecodeError(name, + fmt.Errorf("expected a map or struct, got %q", dataValKind)) } } func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { dataValType := dataVal.Type() if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { - return fmt.Errorf( - "'%s' needs a map with string keys, has '%s' keys", - name, dataValType.Key().Kind()) + return newDecodeError(name, + fmt.Errorf("needs a map with string keys, has %q keys", kind)) } dataValKeys := make(map[reflect.Value]struct{}) - dataValKeysUnused := make(map[interface{}]struct{}) + dataValKeysUnused := make(map[any]struct{}) for _, dataValKey := range dataVal.MapKeys() { dataValKeys[dataValKey] = struct{}{} dataValKeysUnused[dataValKey.Interface()] = struct{}{} } - targetValKeysUnused := make(map[interface{}]struct{}) + targetValKeysUnused := make(map[any]struct{}) var errs []error @@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e structs = append(structs, fieldVal.Elem().Elem()) } default: - errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + errs = append(errs, newDecodeError( + name+"."+fieldType.Name, + fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()), + )) } continue } @@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e if !rawMapVal.IsValid() { // There was no matching key in the map for the value in // the struct. Remember it for potential errors and metadata. - targetValKeysUnused[fieldName] = struct{}{} + if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) { + targetValKeysUnused[fieldName] = struct{}{} + } continue } } @@ -1495,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e // we put the unused keys directly into the remain field. if remainField != nil && len(dataValKeysUnused) > 0 { // Build a map of only the unused values - remain := map[interface{}]interface{}{} + remain := map[any]any{} for key := range dataValKeysUnused { remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() } @@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } sort.Strings(keys) - err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) - errs = append(errs, err) + errs = append(errs, newDecodeError( + name, + fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")), + )) } if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { @@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } sort.Strings(keys) - err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) - errs = append(errs, err) + errs = append(errs, newDecodeError( + name, + fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")), + )) } if err := errors.Join(errs...); err != nil { diff --git a/vendor/github.com/godoc-lint/godoc-lint/LICENSE b/vendor/github.com/godoc-lint/godoc-lint/LICENSE new file mode 100644 index 000000000..f51a8f9b5 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Babak K. Shandiz + +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/vendor/github.com/godoc-lint/godoc-lint/pkg/analysis/analyzer.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/analysis/analyzer.go new file mode 100644 index 000000000..052390058 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/analysis/analyzer.go @@ -0,0 +1,108 @@ +// Package analysis provides the main analyzer implementation. +package analysis + +import ( + "errors" + "fmt" + "path/filepath" + + "golang.org/x/tools/go/analysis" + + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const ( + metaName = "godoclint" + metaDoc = "Checks Golang's documentation practice (godoc)" + metaURL = "https://github.com/godoc-lint/godoc-lint" +) + +// Analyzer implements the godoc-lint analyzer. +type Analyzer struct { + baseDir string + cb model.ConfigBuilder + inspector model.Inspector + reg model.Registry + exitFunc func(int, error) + + analyzer *analysis.Analyzer +} + +// NewAnalyzer returns a new instance of the corresponding analyzer. +func NewAnalyzer(baseDir string, cb model.ConfigBuilder, reg model.Registry, inspector model.Inspector, exitFunc func(int, error)) *Analyzer { + result := &Analyzer{ + baseDir: baseDir, + cb: cb, + reg: reg, + inspector: inspector, + exitFunc: exitFunc, + analyzer: &analysis.Analyzer{ + Name: metaName, + Doc: metaDoc, + URL: metaURL, + Requires: []*analysis.Analyzer{inspector.GetAnalyzer()}, + }, + } + + result.analyzer.Run = result.run + return result +} + +// GetAnalyzer returns the underlying analyzer. +func (a *Analyzer) GetAnalyzer() *analysis.Analyzer { + return a.analyzer +} + +func (a *Analyzer) run(pass *analysis.Pass) (any, error) { + if len(pass.Files) == 0 { + return nil, nil + } + + ft := util.GetPassFileToken(pass.Files[0], pass) + if ft == nil { + err := errors.New("cannot prepare config") + if a.exitFunc != nil { + a.exitFunc(2, err) + } + return nil, err + } + + if !util.IsPathUnderBaseDir(a.baseDir, ft.Name()) { + return nil, nil + } + + pkgDir := filepath.Dir(ft.Name()) + cfg, err := a.cb.GetConfig(pkgDir) + if err != nil { + err := fmt.Errorf("cannot prepare config: %w", err) + if a.exitFunc != nil { + a.exitFunc(2, err) + } + return nil, err + } + + ir := pass.ResultOf[a.inspector.GetAnalyzer()].(*model.InspectorResult) + if ir == nil || ir.Files == nil { + return nil, nil + } + + actx := &model.AnalysisContext{ + Config: cfg, + InspectorResult: ir, + Pass: pass, + } + + for _, checker := range a.reg.List() { + // TODO(babakks): This can be done once to improve performance. + ruleSet := checker.GetCoveredRules() + if !actx.Config.IsAnyRuleApplicable(ruleSet) { + continue + } + + if err := checker.Apply(actx); err != nil { + return nil, fmt.Errorf("checker error: %w", err) + } + } + return nil, nil +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/deprecated/deprecated.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/deprecated/deprecated.go new file mode 100644 index 000000000..08915f6c7 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/deprecated/deprecated.go @@ -0,0 +1,114 @@ +// Package deprecated provides a checker for correct usage of deprecation +// markers. +package deprecated + +import ( + "go/ast" + "go/doc/comment" + "regexp" + + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const deprecatedRule = model.DeprecatedRule + +var ruleSet = model.RuleSet{}.Add(deprecatedRule) + +// DeprecatedChecker checks correct usage of "Deprecated:" markers. +type DeprecatedChecker struct{} + +// NewDeprecatedChecker returns a new instance of the corresponding checker. +func NewDeprecatedChecker() *DeprecatedChecker { + return &DeprecatedChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *DeprecatedChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *DeprecatedChecker) Apply(actx *model.AnalysisContext) error { + docs := make(map[*model.CommentGroup]struct{}, 10*len(actx.InspectorResult.Files)) + + for _, ir := range util.AnalysisApplicableFiles(actx, false, model.RuleSet{}.Add(deprecatedRule)) { + if ir.PackageDoc != nil { + docs[ir.PackageDoc] = struct{}{} + } + + for _, sd := range ir.SymbolDecl { + isExported := ast.IsExported(sd.Name) + if !isExported { + continue + } + + if sd.ParentDoc != nil { + docs[sd.ParentDoc] = struct{}{} + } + if sd.Doc == nil { + continue + } + docs[sd.Doc] = struct{}{} + } + } + + for doc := range docs { + checkDeprecations(actx, doc) + } + return nil +} + +// probableDeprecationRE finds probable deprecation markers, including the +// correct usage. +var probableDeprecationRE = regexp.MustCompile(`(?i)^deprecated:.?`) + +const correctDeprecationMarker = "Deprecated: " + +func checkDeprecations(actx *model.AnalysisContext, doc *model.CommentGroup) { + if doc.DisabledRules.All || doc.DisabledRules.Rules.Has(deprecatedRule) { + return + } + + for _, block := range doc.Parsed.Content { + // The correct usage of deprecation markers is to put them at the beginning + // of a paragraph (i.e. not a heading, code block, etc). Also the syntax is + // strict and must only be "Deprecated: " (case-sensitive and with the + // trailing whitespace). + // + // However, not all wrong usages are reliably discoverable. For example: + // + // // Foo is a symbol. + // // deprecated: use Bar. + // // func Foo() {} + // + // In this cases, the "deprecated: " marker is at the beginning of a new + // line, but as of godoc parser, it's just in the middle of the paragraph + // started at the top line. There might be some smart ways to detect these + // cases, but the problem is there will be false-positives to them. For + // instance, a valid case like this should never be detected as a wrong + // usage: + // + // // Foo is a symbol but here are the reasons why it's + // // deprecated: blah, blah, ... + // // func Foo() {} + // + // Needless to say we don't want to deal with human language complexities. + + par, ok := block.(*comment.Paragraph) + if !ok || len(par.Text) == 0 { + continue + } + text, ok := (par.Text[0]).(comment.Plain) + if !ok { + continue + } + + if match := probableDeprecationRE.FindString(string(text)); match == "" || match == correctDeprecationMarker { + continue + } + + actx.Pass.ReportRangef(&doc.CG, "deprecation note should be formatted as %q", correctDeprecationMarker) + break + } +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go new file mode 100644 index 000000000..1d647c49e --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go @@ -0,0 +1,96 @@ +// Package max_len provides a checker for maximum line length of godocs. +package max_len + +import ( + "fmt" + gdc "go/doc/comment" + "strings" + "unicode/utf8" + + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const maxLenRule = model.MaxLenRule + +var ruleSet = model.RuleSet{}.Add(maxLenRule) + +// MaxLenChecker checks maximum line length of godocs. +type MaxLenChecker struct{} + +// NewMaxLenChecker returns a new instance of the corresponding checker. +func NewMaxLenChecker() *MaxLenChecker { + return &MaxLenChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *MaxLenChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *MaxLenChecker) Apply(actx *model.AnalysisContext) error { + includeTests := actx.Config.GetRuleOptions().MaxLenIncludeTests + maxLen := int(actx.Config.GetRuleOptions().MaxLenLength) + + docs := make(map[*model.CommentGroup]struct{}, 10*len(actx.InspectorResult.Files)) + + for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(maxLenRule)) { + if ir.PackageDoc != nil { + docs[ir.PackageDoc] = struct{}{} + } + + for _, sd := range ir.SymbolDecl { + if sd.ParentDoc != nil { + docs[sd.ParentDoc] = struct{}{} + } + if sd.Doc == nil { + continue + } + docs[sd.Doc] = struct{}{} + } + } + + for doc := range docs { + checkMaxLen(actx, doc, maxLen) + } + return nil +} + +func checkMaxLen(actx *model.AnalysisContext, doc *model.CommentGroup, maxLen int) { + if doc.DisabledRules.All || doc.DisabledRules.Rules.Has(maxLenRule) { + return + } + + linkDefsMap := make(map[string]struct{}, len(doc.Parsed.Links)) + for _, linkDef := range doc.Parsed.Links { + linkDefLine := fmt.Sprintf("[%s]: %s", linkDef.Text, linkDef.URL) + linkDefsMap[linkDefLine] = struct{}{} + } + + nonCodeBlocks := make([]gdc.Block, 0, len(doc.Parsed.Content)) + for _, b := range doc.Parsed.Content { + if _, ok := b.(*gdc.Code); ok { + continue + } + nonCodeBlocks = append(nonCodeBlocks, b) + } + strippedCodeAndLinks := &gdc.Doc{ + Content: nonCodeBlocks, + } + text := string((&gdc.Printer{}).Comment(strippedCodeAndLinks)) + linesIter := strings.SplitSeq(removeCarriageReturn(text), "\n") + + for l := range linesIter { + lineLen := utf8.RuneCountInString(l) + if lineLen <= maxLen { + continue + } + actx.Pass.ReportRangef(&doc.CG, "godoc line is too long (%d > %d)", lineLen, maxLen) + break + } +} + +func removeCarriageReturn(s string) string { + return strings.ReplaceAll(s, "\r", "") +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/no_unused_link/no_unused_link.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/no_unused_link/no_unused_link.go new file mode 100644 index 000000000..8910204be --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/no_unused_link/no_unused_link.go @@ -0,0 +1,69 @@ +// Package no_unused_link provides a checker for unused links in godocs. +package no_unused_link + +import ( + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const noUnusedLinkRule = model.NoUnusedLinkRule + +var ruleSet = model.RuleSet{}.Add(noUnusedLinkRule) + +// NoUnusedLinkChecker checks for unused links. +type NoUnusedLinkChecker struct{} + +// NewNoUnusedLinkChecker returns a new instance of the corresponding checker. +func NewNoUnusedLinkChecker() *NoUnusedLinkChecker { + return &NoUnusedLinkChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *NoUnusedLinkChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *NoUnusedLinkChecker) Apply(actx *model.AnalysisContext) error { + includeTests := actx.Config.GetRuleOptions().NoUnusedLinkIncludeTests + + docs := make(map[*model.CommentGroup]struct{}, 10*len(actx.InspectorResult.Files)) + + for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(noUnusedLinkRule)) { + if ir.PackageDoc != nil { + docs[ir.PackageDoc] = struct{}{} + } + + for _, sd := range ir.SymbolDecl { + if sd.ParentDoc != nil { + docs[sd.ParentDoc] = struct{}{} + } + if sd.Doc == nil { + continue + } + docs[sd.Doc] = struct{}{} + } + } + + for doc := range docs { + checkNoUnusedLink(actx, doc) + } + return nil +} + +func checkNoUnusedLink(actx *model.AnalysisContext, doc *model.CommentGroup) { + if doc.DisabledRules.All || doc.DisabledRules.Rules.Has(noUnusedLinkRule) { + return + } + + if doc.Text == "" { + return + } + + for _, linkDef := range doc.Parsed.Links { + if linkDef.Used { + continue + } + actx.Pass.ReportRangef(&doc.CG, "godoc has unused link (%q)", linkDef.Text) + } +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/pkg_doc/pkg_doc.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/pkg_doc/pkg_doc.go new file mode 100644 index 000000000..199b1f54b --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/pkg_doc/pkg_doc.go @@ -0,0 +1,204 @@ +// Package pkg_doc provides a checker for package godocs. +package pkg_doc + +import ( + "go/ast" + "strings" + + "github.com/godoc-lint/godoc-lint/pkg/check/shared" + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const ( + pkgDocRule = model.PkgDocRule + singlePkgDocRule = model.SinglePkgDocRule + requirePkgDocRule = model.RequirePkgDocRule +) + +var ruleSet = model.RuleSet{}.Add( + pkgDocRule, + singlePkgDocRule, + requirePkgDocRule, +) + +// PkgDocChecker checks package godocs. +type PkgDocChecker struct{} + +// NewPkgDocChecker returns a new instance of the corresponding checker. +func NewPkgDocChecker() *PkgDocChecker { + return &PkgDocChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *PkgDocChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *PkgDocChecker) Apply(actx *model.AnalysisContext) error { + checkPkgDocRule(actx) + checkSinglePkgDocRule(actx) + checkRequirePkgDocRule(actx) + return nil +} + +const commandPkgName = "main" +const commandTestPkgName = "main_test" + +func checkPkgDocRule(actx *model.AnalysisContext) { + if !actx.Config.IsAnyRuleApplicable(model.RuleSet{}.Add(pkgDocRule)) { + return + } + + includeTests := actx.Config.GetRuleOptions().PkgDocIncludeTests + + for f, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(pkgDocRule)) { + if ir.PackageDoc == nil { + continue + } + + if ir.PackageDoc.DisabledRules.All || ir.PackageDoc.DisabledRules.Rules.Has(pkgDocRule) { + continue + } + + if f.Name.Name == commandPkgName || f.Name.Name == commandTestPkgName { + // Skip command packages, as they are not required to start with + // "Package main" or "Package main_test". + // + // See for more details: + // - https://github.com/godoc-lint/godoc-lint/issues/10 + // - https://go.dev/doc/comment#cmd + continue + } + + if ir.PackageDoc.Text == "" { + continue + } + + if shared.HasDeprecatedParagraph(ir.PackageDoc.Parsed.Content) { + // If there's a paragraph starting with "Deprecated:", we skip the + // entire godoc. The reason is a deprecated symbol will not appear + // when docs are rendered. + // + // Another reason is that we cannot just skip those paragraphs and + // look for the symbol in the remaining text. To do that, we need + // to iterate over all comment.Block nodes, and check if a block + // is a paragraph AND starts with the deprecation marker. This is + // simple, but the challenge appears when we get to the first block + // that does not have the marker and we want to check if it starts + // with the symbol name. We'd expect that to be a paragraph, but + // that is not always the case. For example, take this decl: + // + // // Deprecated: blah blah + // // + // // Foo is integer + // // + // // Deprecation: blah blah + // type Foo int + // + // The first block is a paragraph which we can easily skip due to + // the "Deprecated:" marker. However, the second block is actually + // parsed as a heading. One can verify this by copy/pasting it in + // a Go file and check the gopls hover. + // + // There might be a workaround for this, but this also means the + // godoc parser behaves in unexpected ways, and until we don't + // really know the extent of its quirks, it's safer to just skip + // further checks on such godocs. + continue + } + + if expectedPrefix, ok := checkPkgDocPrefix(ir.PackageDoc.Text, f.Name.Name); !ok { + actx.Pass.Reportf(ir.PackageDoc.CG.Pos(), "package godoc should start with %q", expectedPrefix+" ") + } + } +} + +func checkPkgDocPrefix(text string, packageName string) (string, bool) { + expectedPrefix := "Package " + packageName + if !strings.HasPrefix(text, expectedPrefix) { + return expectedPrefix, false + } + rest := text[len(expectedPrefix):] + return expectedPrefix, rest == "" || rest[0] == ' ' || rest[0] == '\t' || rest[0] == '\r' || rest[0] == '\n' +} + +func checkSinglePkgDocRule(actx *model.AnalysisContext) { + if !actx.Config.IsAnyRuleApplicable(model.RuleSet{}.Add(singlePkgDocRule)) { + return + } + + includeTests := actx.Config.GetRuleOptions().SinglePkgDocIncludeTests + + documentedPkgs := make(map[string][]*ast.File, 2) + + for f, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(singlePkgDocRule)) { + if ir.PackageDoc == nil || ir.PackageDoc.Text == "" { + continue + } + + if ir.PackageDoc.DisabledRules.All || ir.PackageDoc.DisabledRules.Rules.Has(singlePkgDocRule) { + continue + } + + pkg := f.Name.Name + if _, ok := documentedPkgs[pkg]; !ok { + documentedPkgs[pkg] = make([]*ast.File, 0, 2) + } + documentedPkgs[pkg] = append(documentedPkgs[pkg], f) + } + + for pkg, fs := range documentedPkgs { + if len(fs) < 2 { + continue + } + for _, f := range fs { + ir := actx.InspectorResult.Files[f] + actx.Pass.Reportf(ir.PackageDoc.CG.Pos(), "package has more than one godoc (%q)", pkg) + } + } +} + +func checkRequirePkgDocRule(actx *model.AnalysisContext) { + if !actx.Config.IsAnyRuleApplicable(model.RuleSet{}.Add(requirePkgDocRule)) { + return + } + + includeTests := actx.Config.GetRuleOptions().RequirePkgDocIncludeTests + + pkgFiles := make(map[string][]*ast.File, 2) + + for f := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(requirePkgDocRule)) { + pkg := f.Name.Name + if _, ok := pkgFiles[pkg]; !ok { + pkgFiles[pkg] = make([]*ast.File, 0, len(actx.Pass.Files)) + } + pkgFiles[pkg] = append(pkgFiles[pkg], f) + } + + for pkg, fs := range pkgFiles { + pkgHasGodoc := false + for _, f := range fs { + ir := actx.InspectorResult.Files[f] + + if ir.PackageDoc == nil || ir.PackageDoc.Text == "" { + continue + } + + if ir.PackageDoc.DisabledRules.All || ir.PackageDoc.DisabledRules.Rules.Has(requirePkgDocRule) { + continue + } + + pkgHasGodoc = true + break + } + + if pkgHasGodoc { + continue + } + + // Add a diagnostic message to the first file of the package. + actx.Pass.Reportf(fs[0].Name.Pos(), "package should have a godoc (%q)", pkg) + } +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go new file mode 100644 index 000000000..8452fa02c --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go @@ -0,0 +1,64 @@ +// Package check provides a registry of checkers. +package check + +import ( + "github.com/godoc-lint/godoc-lint/pkg/check/deprecated" + "github.com/godoc-lint/godoc-lint/pkg/check/max_len" + "github.com/godoc-lint/godoc-lint/pkg/check/no_unused_link" + "github.com/godoc-lint/godoc-lint/pkg/check/pkg_doc" + "github.com/godoc-lint/godoc-lint/pkg/check/require_doc" + "github.com/godoc-lint/godoc-lint/pkg/check/start_with_name" + "github.com/godoc-lint/godoc-lint/pkg/model" +) + +// Registry implements a registry of rules. +type Registry struct { + checkers map[model.Checker]struct{} + coveredRules model.RuleSet +} + +// NewRegistry returns a new rule registry instance. +func NewRegistry(checkers ...model.Checker) *Registry { + registry := Registry{ + checkers: make(map[model.Checker]struct{}, len(checkers)+10), + } + for _, c := range checkers { + registry.Add(c) + } + return ®istry +} + +// NewPopulatedRegistry returns a registry with all supported rules registered. +func NewPopulatedRegistry() *Registry { + return NewRegistry( + max_len.NewMaxLenChecker(), + pkg_doc.NewPkgDocChecker(), + require_doc.NewRequireDocChecker(), + start_with_name.NewStartWithNameChecker(), + no_unused_link.NewNoUnusedLinkChecker(), + deprecated.NewDeprecatedChecker(), + ) +} + +// Add implements the corresponding interface method. +func (r *Registry) Add(checker model.Checker) { + if _, ok := r.checkers[checker]; ok { + return + } + r.coveredRules = r.coveredRules.Merge(checker.GetCoveredRules()) + r.checkers[checker] = struct{}{} +} + +// List implements the corresponding interface method. +func (r *Registry) List() []model.Checker { + all := make([]model.Checker, 0, len(r.checkers)) + for c := range r.checkers { + all = append(all, c) + } + return all +} + +// GetCoveredRules implements the corresponding interface method. +func (r *Registry) GetCoveredRules() model.RuleSet { + return r.coveredRules +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go new file mode 100644 index 000000000..afa16bd78 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go @@ -0,0 +1,173 @@ +// Package require_doc provides a checker that requires symbols to have godocs. +package require_doc + +import ( + "go/ast" + + "golang.org/x/tools/go/analysis" + + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const requireDocRule = model.RequireDocRule + +var ruleSet = model.RuleSet{}.Add(requireDocRule) + +// RequireDocChecker checks required godocs. +type RequireDocChecker struct{} + +// NewRequireDocChecker returns a new instance of the corresponding checker. +func NewRequireDocChecker() *RequireDocChecker { + return &RequireDocChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *RequireDocChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *RequireDocChecker) Apply(actx *model.AnalysisContext) error { + includeTests := actx.Config.GetRuleOptions().RequireDocIncludeTests + requirePublic := !actx.Config.GetRuleOptions().RequireDocIgnoreExported + requirePrivate := !actx.Config.GetRuleOptions().RequireDocIgnoreUnexported + + if !requirePublic && !requirePrivate { + return nil + } + + for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(requireDocRule)) { + for _, decl := range ir.SymbolDecl { + isExported := ast.IsExported(decl.Name) + if isExported && !requirePublic || !isExported && !requirePrivate { + continue + } + + if decl.Name == "_" { + // Blank identifiers should be ignored; e.g.: + // + // var _ = 0 + continue + } + + if decl.Doc != nil && (decl.Doc.DisabledRules.All || decl.Doc.DisabledRules.Rules.Has(requireDocRule)) { + continue + } + + if decl.Kind == model.SymbolDeclKindBad { + continue + } + + if decl.Kind == model.SymbolDeclKindFunc { + if decl.Doc == nil || decl.Doc.Text == "" { + reportRange(actx.Pass, decl.Ident) + } + continue + } + + // Now we only have const/var/type declarations. + + if decl.Doc != nil && decl.Doc.Text != "" { + // cases: + // + // // godoc + // const foo = 0 + // + // // godoc + // const foo, bar = 0, 0 + // + // const ( + // // godoc + // foo = 0 + // ) + // + // const ( + // // godoc + // foo, bar = 0, 0 + // ) + // + // // godoc + // type foo int + // + // type ( + // // godoc + // foo int + // ) + continue + } + + if decl.TrailingDoc != nil && decl.TrailingDoc.Text != "" { + // cases: + // + // const foo = 0 // godoc + // + // const foo, bar = 0, 0 // godoc + // + // const ( + // foo = 0 // godoc + // ) + // + // const ( + // foo, bar = 0, 0 // godoc + // ) + // + // type foo int // godoc + // + // type ( + // foo int // godoc + // ) + continue + } + + if decl.ParentDoc != nil && decl.ParentDoc.Text != "" { + // cases: + // + // // godoc + // const ( + // foo = 0 + // ) + // + // // godoc + // const ( + // foo, bar = 0, 0 + // ) + // + // // godoc + // type ( + // foo int + // ) + continue + } + + // At this point there is no godoc for the symbol. + // + // cases: + // + // const foo = 0 + // + // const foo, bar = 0, 0 + // + // const ( + // foo = 0 + // ) + // + // const ( + // foo, bar = 0, 0 + // ) + // + // type foo int + // + // type ( + // foo int + // ) + + reportRange(actx.Pass, decl.Ident) + } + } + return nil +} + +func reportRange(pass *analysis.Pass, ident *ast.Ident) { + pass.ReportRangef(ident, "symbol should have a godoc (%q)", ident.Name) +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/shared/deprecated.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/shared/deprecated.go new file mode 100644 index 000000000..8ebed0e2b --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/shared/deprecated.go @@ -0,0 +1,29 @@ +// Package shared provides shared utilities for checkers. +package shared + +import ( + "go/doc/comment" + "strings" +) + +// HasDeprecatedParagraph reports whether the given comment blocks contain a +// paragraph starting with deprecation marker. +func HasDeprecatedParagraph(blocks []comment.Block) bool { + for _, block := range blocks { + par, ok := block.(*comment.Paragraph) + if !ok || len(par.Text) == 0 { + continue + } + text, ok := (par.Text[0]).(comment.Plain) + if !ok { + continue + } + + // Only an exact match (casing and the trailing whitespace) is considered + // a valid deprecation marker. + if strings.HasPrefix(string(text), "Deprecated: ") { + return true + } + } + return false +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go new file mode 100644 index 000000000..f8c905aab --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go @@ -0,0 +1,132 @@ +// Package start_with_name provides a checker for godocs starting with the +// symbol name. +package start_with_name + +import ( + "go/ast" + "regexp" + "strings" + + "github.com/godoc-lint/godoc-lint/pkg/check/shared" + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const startWithNameRule = model.StartWithNameRule + +var ruleSet = model.RuleSet{}.Add(startWithNameRule) + +// StartWithNameChecker checks starter of godocs. +type StartWithNameChecker struct{} + +// NewStartWithNameChecker returns a new instance of the corresponding checker. +func NewStartWithNameChecker() *StartWithNameChecker { + return &StartWithNameChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *StartWithNameChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *StartWithNameChecker) Apply(actx *model.AnalysisContext) error { + if !actx.Config.IsAnyRuleApplicable(model.RuleSet{}.Add(startWithNameRule)) { + return nil + } + + includeTests := actx.Config.GetRuleOptions().StartWithNameIncludeTests + includePrivate := actx.Config.GetRuleOptions().StartWithNameIncludeUnexported + + for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(startWithNameRule)) { + for _, decl := range ir.SymbolDecl { + isExported := ast.IsExported(decl.Name) + if !isExported && !includePrivate { + continue + } + + if decl.Name == "_" { + // Blank identifiers should be ignored; e.g.: + // + // var _ = 0 + continue + } + + if decl.Kind == model.SymbolDeclKindBad { + continue + } + + if decl.Doc == nil || decl.Doc.Text == "" { + continue + } + + if decl.Doc.DisabledRules.All || decl.Doc.DisabledRules.Rules.Has(startWithNameRule) { + continue + } + + if decl.MultiNameDecl { + continue + } + + if shared.HasDeprecatedParagraph(decl.Doc.Parsed.Content) { + // If there's a paragraph starting with "Deprecated:", we skip the + // entire godoc. The reason is a deprecated symbol will not appear + // when docs are rendered. + // + // Another reason is that we cannot just skip those paragraphs and + // look for the symbol in the remaining text. To do that, we need + // to iterate over all comment.Block nodes, and check if a block + // is a paragraph AND starts with the deprecation marker. This is + // simple, but the challenge appears when we get to the first block + // that does not have the marker and we want to check if it starts + // with the symbol name. We'd expect that to be a paragraph, but + // that is not always the case. For example, take this decl: + // + // // Deprecated: blah blah + // // + // // Foo is integer + // // + // // Deprecation: blah blah + // type Foo int + // + // The first block is a paragraph which we can easily skip due to + // the "Deprecated:" marker. However, the second block is actually + // parsed as a heading. One can verify this by copy/pasting it in + // a Go file and check the gopls hover. + // + // There might be a workaround for this, but this also means the + // godoc parser behaves in unexpected ways, and until we don't + // really know the extent of its quirks, it's safer to just skip + // further checks on such godocs. + continue + } + + if matchSymbolName(decl.Doc.Text, decl.Name) { + continue + } + + actx.Pass.ReportRangef(&decl.Doc.CG, "godoc should start with symbol name (%q)", decl.Name) + } + } + return nil +} + +var startPattern = regexp.MustCompile(`^(?:(A|a|AN|An|an|THE|The|the) )?(?P.+?)\b`) +var startPatternSymbolNameIndex = startPattern.SubexpIndex("symbol_name") + +func matchSymbolName(text string, symbol string) bool { + head := strings.SplitN(text, "\n", 2)[0] + head, _ = strings.CutPrefix(head, "\r") + head = strings.SplitN(head, " ", 2)[0] + head = strings.SplitN(head, "\t", 2)[0] + + if head == symbol { + return true + } + + match := startPattern.FindStringSubmatch(text) + if match == nil { + return false + } + return match[startPatternSymbolNameIndex] == symbol +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/compose/compose.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/compose/compose.go new file mode 100644 index 000000000..7ec04e349 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/compose/compose.go @@ -0,0 +1,53 @@ +// Package compose provides composition of the linter components. +package compose + +import ( + "os" + + "github.com/godoc-lint/godoc-lint/pkg/analysis" + "github.com/godoc-lint/godoc-lint/pkg/check" + "github.com/godoc-lint/godoc-lint/pkg/config" + "github.com/godoc-lint/godoc-lint/pkg/inspect" + "github.com/godoc-lint/godoc-lint/pkg/model" +) + +// Composition holds the composed components of the linter. +type Composition struct { + Registry model.Registry + ConfigBuilder model.ConfigBuilder + Inspector model.Inspector + Analyzer model.Analyzer +} + +// CompositionConfig holds the configuration for composing the linter. +type CompositionConfig struct { + BaseDir string + ExitFunc func(int, error) + + // BaseDirPlainConfig holds the plain configuration for the base directory. + // + // This is meant to be used for integrating with umbrella linters (e.g. + // golangci-lint) where the root config comes from a different source/format. + BaseDirPlainConfig *config.PlainConfig +} + +// Compose composes the linter components based on the given configuration. +func Compose(c CompositionConfig) *Composition { + if c.BaseDir == "" { + // It's a best effort to use the current working directory if not set. + c.BaseDir, _ = os.Getwd() + } + + reg := check.NewPopulatedRegistry() + cb := config.NewConfigBuilder(c.BaseDir).WithBaseDirPlainConfig(c.BaseDirPlainConfig) + ocb := config.NewOnceConfigBuilder(cb) + inspector := inspect.NewInspector(ocb, c.ExitFunc) + analyzer := analysis.NewAnalyzer(c.BaseDir, ocb, reg, inspector, c.ExitFunc) + + return &Composition{ + Registry: reg, + ConfigBuilder: cb, + Inspector: inspector, + Analyzer: analyzer, + } +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go new file mode 100644 index 000000000..aa25cf186 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go @@ -0,0 +1,289 @@ +package config + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "regexp" + "slices" + + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +// ConfigBuilder implements a configuration builder. +type ConfigBuilder struct { + baseDir string + override *model.ConfigOverride + + // baseDirPlainConfig holds the plain config for the base directory. + // + // This is meant to be used for integrating with umbrella linters (e.g. + // golangci-lint) where the root config comes from a different + // source/format. + baseDirPlainConfig *PlainConfig +} + +// NewConfigBuilder crates a new instance of the corresponding struct. +func NewConfigBuilder(baseDir string) *ConfigBuilder { + return &ConfigBuilder{ + baseDir: baseDir, + } +} + +// WithBaseDirPlainConfig sets the plain config for the base directory. This is +// meant to be used for integrating with umbrella linters (e.g. golangci-lint) +// where the root config comes from a different source/format. +func (cb *ConfigBuilder) WithBaseDirPlainConfig(baseDirPlainConfig *PlainConfig) *ConfigBuilder { + cb.baseDirPlainConfig = baseDirPlainConfig + return cb +} + +// GetConfig implements the corresponding interface method. +func (cb *ConfigBuilder) GetConfig(cwd string) (model.Config, error) { + return cb.build(cwd) +} + +func (cb *ConfigBuilder) resolvePlainConfig(cwd string) (*PlainConfig, *PlainConfig, string, string, error) { + def := getDefaultPlainConfig() + + if !util.IsPathUnderBaseDir(cb.baseDir, cwd) { + if pcfg, filePath, err := cb.resolvePlainConfigAtBaseDir(); err != nil { + return nil, nil, "", "", err + } else if pcfg != nil { + return pcfg, def, cb.baseDir, filePath, nil + } + return def, def, cb.baseDir, "", nil + } + + path := cwd + for { + rel, err := filepath.Rel(cb.baseDir, path) + if err != nil { + return nil, nil, "", "", err + } + + if rel == "." { + if pcfg, filePath, err := cb.resolvePlainConfigAtBaseDir(); err != nil { + return nil, nil, "", "", err + } else if pcfg != nil { + return pcfg, def, cb.baseDir, filePath, nil + } + return def, def, cb.baseDir, "", nil + } + + if pcfg, filePath, err := findConventionalConfigFile(path); err != nil { + return nil, nil, "", "", err + } else if pcfg != nil { + return pcfg, def, path, filePath, nil + } + + path = filepath.Dir(path) + } +} + +func (cb *ConfigBuilder) resolvePlainConfigAtBaseDir() (*PlainConfig, string, error) { + // TODO(babakks): refactor this to a sync.OnceValue for performance + + if cb.override != nil && cb.override.ConfigFilePath != nil { + pcfg, err := FromYAMLFile(*cb.override.ConfigFilePath) + if err != nil { + return nil, "", err + } + return pcfg, *cb.override.ConfigFilePath, nil + } + + if pcfg, filePath, err := findConventionalConfigFile(cb.baseDir); err != nil { + return nil, "", err + } else if pcfg != nil { + return pcfg, filePath, nil + } + + if cb.baseDirPlainConfig != nil { + return cb.baseDirPlainConfig, "", nil + } + return nil, "", nil +} + +func findConventionalConfigFile(dir string) (*PlainConfig, string, error) { + for _, dcf := range defaultConfigFiles { + path := filepath.Join(dir, dcf) + if fi, err := os.Stat(path); err != nil || fi.IsDir() { + continue + } + pcfg, err := FromYAMLFile(path) + if err != nil { + return nil, "", err + } + return pcfg, path, nil + } + return nil, "", nil +} + +// build creates the configuration struct. +// +// It checks a sequence of sources: +// 1. Custom config file path +// 2. Default configuration files (e.g., `.godoc-lint.yaml`) +// +// If none was available, the default configuration will be returned. +// +// The method also does the following: +// - Applies override flags (e.g., enable, or disable). +// - Validates the final configuration. +func (cb *ConfigBuilder) build(cwd string) (*config, error) { + pcfg, def, configCWD, configFilePath, err := cb.resolvePlainConfig(cwd) + if err != nil { + return nil, err + } + + if err := pcfg.Validate(); err != nil { + return nil, fmt.Errorf("invalid config at %q: %w", configFilePath, err) + } + + toValidRuleSet := func(s []string) (*model.RuleSet, []string) { + if s == nil { + return nil, nil + } + invalids := make([]string, 0, len(s)) + rules := make([]model.Rule, 0, len(s)) + for _, v := range s { + if !model.AllRules.Has(model.Rule(v)) { + invalids = append(invalids, v) + continue + } + rules = append(rules, model.Rule(v)) + } + set := model.RuleSet{}.Add(rules...) + return &set, invalids + } + + toValidRegexpSlice := func(s []string) ([]*regexp.Regexp, []string) { + if s == nil { + return nil, nil + } + var invalids []string + var regexps []*regexp.Regexp + for _, v := range s { + re, err := regexp.Compile(v) + if err != nil { + invalids = append(invalids, v) + continue + } + regexps = append(regexps, re) + } + return regexps, invalids + } + + var errs []error + + result := &config{ + cwd: configCWD, + configFilePath: configFilePath, + } + + var enabledRules *model.RuleSet + if cb.override != nil && cb.override.Enable != nil { + enabledRules = cb.override.Enable + } else { + raw := pcfg.Enable + if raw == nil { + raw = def.Enable + } + rs, invalids := toValidRuleSet(raw) + if len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid rule(s) name to enable: %q", invalids)) + } else { + enabledRules = rs + } + } + + var disabledRules *model.RuleSet + if cb.override != nil && cb.override.Disable != nil { + disabledRules = cb.override.Disable + } else { + raw := pcfg.Disable + if raw == nil { + raw = def.Disable + } + rs, invalids := toValidRuleSet(raw) + if len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid rule(s) name to disable: %q", invalids)) + } else { + disabledRules = rs + } + } + + if cb.override != nil && cb.override.Include != nil { + result.includeAsRegexp = cb.override.Include + } else { + raw := pcfg.Include + if raw == nil { + raw = def.Include + } + rs, invalids := toValidRegexpSlice(raw) + if len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid path pattern(s) to include: %q", invalids)) + } else { + result.includeAsRegexp = rs + } + } + + if cb.override != nil && cb.override.Exclude != nil { + result.excludeAsRegexp = cb.override.Exclude + } else { + raw := pcfg.Exclude + if raw == nil { + raw = def.Exclude + } + rs, invalids := toValidRegexpSlice(raw) + if len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid path pattern(s) to exclude: %q", invalids)) + } else { + result.excludeAsRegexp = rs + } + } + + if cb.override != nil && cb.override.Default != nil { + result.rulesToApply = model.DefaultSetToRules[*cb.override.Default] + } else { + raw := pcfg.Default + if raw == nil { + raw = def.Default // never nil + } + + if !slices.Contains(model.DefaultSetValues, model.DefaultSet(*raw)) { + errs = append(errs, fmt.Errorf("invalid default set %q; must be one of %q", *raw, model.DefaultSetValues)) + } else { + result.rulesToApply = model.DefaultSetToRules[model.DefaultSet(*raw)] + } + } + + if errs != nil { + return nil, errors.Join(errs...) + } + + if enabledRules != nil { + result.rulesToApply = result.rulesToApply.Merge(*enabledRules) + } + if disabledRules != nil { + result.rulesToApply = result.rulesToApply.Remove(disabledRules.List()...) + } + + // To avoid being too strict, we don't complain if a rule is enabled and disabled at the same time. + + resolvedOptions := &model.RuleOptions{} + transferOptions(resolvedOptions, def.Options) // def.Options is never nil + if pcfg.Options != nil { + transferOptions(resolvedOptions, pcfg.Options) + } + result.options = resolvedOptions + + return result, nil +} + +// SetOverride implements the corresponding interface method. +func (cb *ConfigBuilder) SetOverride(override *model.ConfigOverride) { + cb.override = override +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/config.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/config.go new file mode 100644 index 000000000..9a2cdfc60 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/config.go @@ -0,0 +1,73 @@ +package config + +import ( + "path/filepath" + "regexp" + + "github.com/godoc-lint/godoc-lint/pkg/model" +) + +// config represents the godoc-lint analyzer configuration. +type config struct { + // cwd holds the directory that the configuration is applied to. This is the + // way to find out relative paths to include/exclude based on the config + // file. + cwd string + + // configFilePath holds the path to the configuration file. If there is no + // configuration file, which is the case when the default is used, this will + // be an empty string. + configFilePath string + + includeAsRegexp []*regexp.Regexp + excludeAsRegexp []*regexp.Regexp + rulesToApply model.RuleSet + options *model.RuleOptions +} + +// GetConfigFilePath implements the corresponding interface method. +func (c *config) GetConfigFilePath() string { + return c.configFilePath +} + +// GetCWD implements the corresponding interface method. +func (c *config) GetCWD() string { + return c.cwd +} + +// IsAnyRuleApplicable implements the corresponding interface method. +func (c *config) IsAnyRuleApplicable(rs model.RuleSet) bool { + return c.rulesToApply.HasCommonsWith(rs) +} + +// IsPathApplicable implements the corresponding interface method. +func (c *config) IsPathApplicable(path string) bool { + p, err := filepath.Rel(c.cwd, path) + if err != nil { + p = path + } + + // To ensure a consistent behavior on different platform (with the same + // configuration), we convert the path to a Unix-style path. + asUnixPath := filepath.ToSlash(p) + + for _, re := range c.excludeAsRegexp { + if re.MatchString(asUnixPath) { + return false + } + } + if c.includeAsRegexp == nil { + return true + } + for _, re := range c.includeAsRegexp { + if re.MatchString(asUnixPath) { + return true + } + } + return false +} + +// GetRuleOptions implements the corresponding interface method. +func (c *config) GetRuleOptions() *model.RuleOptions { + return c.options +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.go new file mode 100644 index 000000000..79ba8b670 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.go @@ -0,0 +1,28 @@ +package config + +import ( + _ "embed" + "sync" +) + +// defaultConfigFiles is the list of default configuration file names. +var defaultConfigFiles = []string{ + ".godoc-lint.yaml", + ".godoc-lint.yml", + ".godoc-lint.json", + ".godoclint.yaml", + ".godoclint.yml", + ".godoclint.json", +} + +// defaultConfigYAML is the default configuration (as YAML). +// +//go:embed default.yaml +var defaultConfigYAML []byte + +// getDefaultPlainConfig returns the parsed default configuration. +var getDefaultPlainConfig = sync.OnceValue(func() *PlainConfig { + // Error is nil due to tests. + pcfg, _ := FromYAML(defaultConfigYAML) + return pcfg +}) diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml new file mode 100644 index 000000000..eb244e771 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml @@ -0,0 +1,15 @@ +# Default configuration +version: "1.0" +default: basic +options: + max-len/length: 77 + max-len/include-tests: false + pkg-doc/include-tests: false + single-pkg-doc/include-tests: false + require-pkg-doc/include-tests: false + require-doc/include-tests: false + require-doc/ignore-exported: false + require-doc/ignore-unexported: true + start-with-name/include-tests: false + start-with-name/include-unexported: false + no-unused-link/include-tests: false \ No newline at end of file diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/doc.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/doc.go new file mode 100644 index 000000000..3a015d989 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/doc.go @@ -0,0 +1,2 @@ +// Package config provides configuration building and management. +package config diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/once.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/once.go new file mode 100644 index 000000000..2d865d557 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/once.go @@ -0,0 +1,59 @@ +package config + +import ( + "sync" + + "github.com/godoc-lint/godoc-lint/pkg/model" +) + +// OnceConfigBuilder wraps a config builder and make it a one-time builder, so +// that further attempts to build will return the same result. +// +// This type is concurrent-safe. +type OnceConfigBuilder struct { + builder model.ConfigBuilder + + mu sync.Mutex + m map[string]built +} + +type built struct { + value model.Config + err error +} + +// NewOnceConfigBuilder crates a new instance of the corresponding struct. +func NewOnceConfigBuilder(builder model.ConfigBuilder) *OnceConfigBuilder { + return &OnceConfigBuilder{ + builder: builder, + } +} + +// GetConfig implements the corresponding interface method. +func (ocb *OnceConfigBuilder) GetConfig(cwd string) (model.Config, error) { + ocb.mu.Lock() + defer ocb.mu.Unlock() + + if b, ok := ocb.m[cwd]; ok { + return b.value, b.err + } + + b := built{} + b.value, b.err = ocb.builder.GetConfig(cwd) + if ocb.m == nil { + ocb.m = make(map[string]built, 10) + } + ocb.m[cwd] = b + return b.value, b.err +} + +// SetOverride implements the corresponding interface method. +func (ocb *OnceConfigBuilder) SetOverride(override *model.ConfigOverride) { + ocb.mu.Lock() + defer ocb.mu.Unlock() + + if len(ocb.m) > 0 { + return + } + ocb.builder.SetOverride(override) +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go new file mode 100644 index 000000000..71a04f045 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go @@ -0,0 +1,42 @@ +package config + +import ( + "fmt" + "os" + "strings" + + "gopkg.in/yaml.v3" +) + +// FromYAML parses configuration from given YAML content. +func FromYAML(in []byte) (*PlainConfig, error) { + raw := PlainConfig{} + if err := yaml.Unmarshal(in, &raw); err != nil { + return nil, fmt.Errorf("cannot parse config from YAML file: %w", err) + } + + if raw.Version != nil && !strings.HasPrefix(*raw.Version, "1.") { + return nil, fmt.Errorf("unsupported config version: %s", *raw.Version) + } + + return &raw, nil +} + +// FromYAMLFile parses configuration from given file path. +func FromYAMLFile(path string) (*PlainConfig, error) { + in, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("cannot read file (%s): %w", path, err) + } + + raw := PlainConfig{} + if err := yaml.Unmarshal(in, &raw); err != nil { + return nil, fmt.Errorf("cannot parse config from YAML file: %w", err) + } + + if raw.Version != nil && !strings.HasPrefix(*raw.Version, "1.") { + return nil, fmt.Errorf("unsupported config version: %s", *raw.Version) + } + + return &raw, nil +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go new file mode 100644 index 000000000..d19323f3f --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go @@ -0,0 +1,128 @@ +package config + +import ( + "errors" + "fmt" + "reflect" + "regexp" + "slices" + + "github.com/godoc-lint/godoc-lint/pkg/model" +) + +// PlainConfig represents the plain configuration type as users would provide +// via a config file (e.g., a YAML file). +type PlainConfig struct { + Version *string `yaml:"version" mapstructure:"version"` + Exclude []string `yaml:"exclude" mapstructure:"exclude"` + Include []string `yaml:"include" mapstructure:"include"` + Default *string `yaml:"default" mapstructure:"default"` + Enable []string `yaml:"enable" mapstructure:"enable"` + Disable []string `yaml:"disable" mapstructure:"disable"` + Options *PlainRuleOptions `yaml:"options" mapstructure:"options"` +} + +// PlainRuleOptions represents the plain rule options as users would provide via +// a config file (e.g., a YAML file). +type PlainRuleOptions struct { + MaxLenLength *uint `option:"max-len/length" yaml:"max-len/length" mapstructure:"max-len/length"` + MaxLenIncludeTests *bool `option:"max-len/include-tests" yaml:"max-len/include-tests" mapstructure:"max-len/include-tests"` + PkgDocIncludeTests *bool `option:"pkg-doc/include-tests" yaml:"pkg-doc/include-tests" mapstructure:"pkg-doc/include-tests"` + SinglePkgDocIncludeTests *bool `option:"single-pkg-doc/include-tests" yaml:"single-pkg-doc/include-tests" mapstructure:"single-pkg-doc/include-tests"` + RequirePkgDocIncludeTests *bool `option:"require-pkg-doc/include-tests" yaml:"require-pkg-doc/include-tests" mapstructure:"require-pkg-doc/include-tests"` + RequireDocIncludeTests *bool `option:"require-doc/include-tests" yaml:"require-doc/include-tests" mapstructure:"require-doc/include-tests"` + RequireDocIgnoreExported *bool `option:"require-doc/ignore-exported" yaml:"require-doc/ignore-exported" mapstructure:"require-doc/ignore-exported"` + RequireDocIgnoreUnexported *bool `option:"require-doc/ignore-unexported" yaml:"require-doc/ignore-unexported" mapstructure:"require-doc/ignore-unexported"` + StartWithNameIncludeTests *bool `option:"start-with-name/include-tests" yaml:"start-with-name/include-tests" mapstructure:"start-with-name/include-tests"` + StartWithNameIncludeUnexported *bool `option:"start-with-name/include-unexported" yaml:"start-with-name/include-unexported" mapstructure:"start-with-name/include-unexported"` + NoUnusedLinkIncludeTests *bool `option:"no-unused-link/include-tests" yaml:"no-unused-link/include-tests" mapstructure:"no-unused-link/include-tests"` +} + +func transferOptions(target *model.RuleOptions, source *PlainRuleOptions) { + resV := reflect.ValueOf(target).Elem() + resVT := resV.Type() + + resOptionMap := make(map[string]string, resVT.NumField()) + for i := range resVT.NumField() { + ft := resVT.Field(i) + key, ok := ft.Tag.Lookup("option") + if !ok { + continue + } + resOptionMap[key] = ft.Name + } + + v := reflect.ValueOf(source).Elem() + vt := v.Type() + for i := range vt.NumField() { + ft := vt.Field(i) + key, ok := ft.Tag.Lookup("option") + if !ok { + continue + } + if ft.Type.Kind() != reflect.Pointer { + continue + } + f := v.Field(i) + if f.IsNil() { + continue + } + resFieldName, ok := resOptionMap[key] + if !ok { + continue + } + resV.FieldByName(resFieldName).Set(f.Elem()) + } +} + +// Validate validates the plain configuration. +func (pcfg *PlainConfig) Validate() error { + var errs []error + + if pcfg.Default != nil && !slices.Contains(model.DefaultSetValues, model.DefaultSet(*pcfg.Default)) { + errs = append(errs, fmt.Errorf("invalid default set %q; must be one of %q", *pcfg.Default, model.DefaultSetValues)) + } + + if invalids := getInvalidRules(pcfg.Enable); len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid rule name(s) to enable: %q", invalids)) + } + + if invalids := getInvalidRules(pcfg.Disable); len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid rule name(s) to disable: %q", invalids)) + } + + // To avoid being too strict, we don't complain if a rule is enabled and disabled at the same time. + + if invalids := getInvalidRegexps(pcfg.Include); len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid inclusion pattern(s): %q", invalids)) + } + + if invalids := getInvalidRegexps(pcfg.Exclude); len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid exclusion pattern(s): %q", invalids)) + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + return nil +} + +func getInvalidRules(names []string) []string { + invalids := make([]string, 0, len(names)) + for _, element := range names { + if !model.AllRules.Has(model.Rule(element)) { + invalids = append(invalids, element) + } + } + return invalids +} + +func getInvalidRegexps(values []string) []string { + invalids := make([]string, 0, len(values)) + for _, element := range values { + if _, err := regexp.Compile(element); err != nil { + invalids = append(invalids, element) + } + } + return invalids +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go new file mode 100644 index 000000000..0040be0e0 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go @@ -0,0 +1,312 @@ +// Package inspect provides the pre-run inspection analyzer. +package inspect + +import ( + "errors" + "fmt" + "go/ast" + gdc "go/doc/comment" + "go/token" + "path/filepath" + "reflect" + "regexp" + "strings" + + "golang.org/x/tools/go/analysis" + + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +const ( + metaName = "godoclint_inspect" + metaDoc = "Pre-run inspector for godoclint" + metaURL = "https://github.com/godoc-lint/godoc-lint" +) + +// Inspector implements the godoc-lint pre-run inspector. +type Inspector struct { + cb model.ConfigBuilder + exitFunc func(int, error) + + analyzer *analysis.Analyzer + parser gdc.Parser +} + +// NewInspector returns a new instance of the inspector. +func NewInspector(cb model.ConfigBuilder, exitFunc func(int, error)) *Inspector { + result := &Inspector{ + cb: cb, + exitFunc: exitFunc, + analyzer: &analysis.Analyzer{ + Name: metaName, + Doc: metaDoc, + URL: metaURL, + ResultType: reflect.TypeOf(new(model.InspectorResult)), + }, + } + result.analyzer.Run = result.run + return result +} + +// GetAnalyzer returns the underlying analyzer. +func (i *Inspector) GetAnalyzer() *analysis.Analyzer { + return i.analyzer +} + +var topLevelOrphanCommentGroupPattern = regexp.MustCompile(`(?m)(?:^//.*\r?\n)+(?:\r?\n|\z)`) +var disableDirectivePattern = regexp.MustCompile(`(?m)//godoclint:disable(?: *([^\r\n]+))?\r?$`) + +func (i *Inspector) run(pass *analysis.Pass) (any, error) { + if len(pass.Files) == 0 { + return &model.InspectorResult{}, nil + } + + ft := util.GetPassFileToken(pass.Files[0], pass) + if ft == nil { + err := errors.New("cannot prepare config") + if i.exitFunc != nil { + i.exitFunc(2, err) + } + return nil, err + } + + pkgDir := filepath.Dir(ft.Name()) + cfg, err := i.cb.GetConfig(pkgDir) + if err != nil { + if i.exitFunc != nil { + i.exitFunc(2, err) + } + return nil, err + } + + inspect := func(f *ast.File) (*model.FileInspection, error) { + ft := util.GetPassFileToken(f, pass) + if ft == nil { + return nil, nil + } + + raw, err := pass.ReadFile(ft.Name()) + if err != nil { + return nil, fmt.Errorf("cannot read file %q: %v", ft.Name(), err) + } + + // Extract package godoc, if any. + packageDoc := i.extractCommentGroup(f.Doc) + + // Extract top-level //godoclint:disable directives. + disabledRules := model.InspectorResultDisableRules{} + for _, match := range topLevelOrphanCommentGroupPattern.FindAll(raw, -1) { + d := extractDisableDirectivesInComment(string(match)) + disabledRules.All = disabledRules.All || d.All + disabledRules.Rules = disabledRules.Rules.Merge(d.Rules) + } + + // Extract top-level symbol declarations. + decls := make([]model.SymbolDecl, 0, len(f.Decls)) + for _, d := range f.Decls { + switch dt := d.(type) { + case *ast.FuncDecl: + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: model.SymbolDeclKindFunc, + Name: dt.Name.Name, + Ident: dt.Name, + Doc: i.extractCommentGroup(dt.Doc), + }) + case *ast.BadDecl: + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: model.SymbolDeclKindBad, + }) + case *ast.GenDecl: + switch dt.Tok { + case token.CONST, token.VAR: + kind := model.SymbolDeclKindConst + if dt.Tok == token.VAR { + kind = model.SymbolDeclKindVar + } + if dt.Lparen == token.NoPos { + // cases: + // const ... (single line) + // var ... (single line) + + spec := dt.Specs[0].(*ast.ValueSpec) + if len(spec.Names) == 1 { + // cases: + // const foo = 0 + // var foo = 0 + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: kind, + Name: spec.Names[0].Name, + Ident: spec.Names[0], + Doc: i.extractCommentGroup(dt.Doc), + TrailingDoc: i.extractCommentGroup(spec.Comment), + }) + } else { + // cases: + // const foo, bar = 0, 0 + // var foo, bar = 0, 0 + doc := i.extractCommentGroup(dt.Doc) + trailingDoc := i.extractCommentGroup(spec.Comment) + for ix, n := range spec.Names { + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: kind, + Name: n.Name, + Ident: n, + Doc: doc, + TrailingDoc: trailingDoc, + MultiNameDecl: true, + MultiNameIndex: ix, + }) + } + } + } else { + // cases: + // const ( + // foo = 0 + // ) + // var ( + // foo = 0 + // ) + // const ( + // foo, bar = 0, 0 + // ) + // var ( + // foo, bar = 0, 0 + // ) + + parentDoc := i.extractCommentGroup(dt.Doc) + for spix, s := range dt.Specs { + spec := s.(*ast.ValueSpec) + doc := i.extractCommentGroup(spec.Doc) + trailingDoc := i.extractCommentGroup(spec.Comment) + for ix, n := range spec.Names { + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: kind, + Name: n.Name, + Ident: n, + Doc: doc, + TrailingDoc: trailingDoc, + ParentDoc: parentDoc, + MultiNameDecl: len(spec.Names) > 1, + MultiNameIndex: ix, + MultiSpecDecl: true, + MultiSpecIndex: spix, + }) + } + } + } + case token.TYPE: + if dt.Lparen == token.NoPos { + // case: + // type foo int + + spec := dt.Specs[0].(*ast.TypeSpec) + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: model.SymbolDeclKindType, + IsTypeAlias: spec.Assign != token.NoPos, + Name: spec.Name.Name, + Ident: spec.Name, + Doc: i.extractCommentGroup(dt.Doc), + TrailingDoc: i.extractCommentGroup(spec.Comment), + }) + } else { + // case: + // type ( + // foo int + // ) + + parentDoc := i.extractCommentGroup(dt.Doc) + for spix, s := range dt.Specs { + spec := s.(*ast.TypeSpec) + decls = append(decls, model.SymbolDecl{ + Decl: d, + Kind: model.SymbolDeclKindType, + IsTypeAlias: spec.Assign != token.NoPos, + Name: spec.Name.Name, + Ident: spec.Name, + Doc: i.extractCommentGroup(spec.Doc), + TrailingDoc: i.extractCommentGroup(spec.Comment), + ParentDoc: parentDoc, + MultiSpecDecl: true, + MultiSpecIndex: spix, + }) + } + } + default: + continue + } + } + } + + return &model.FileInspection{ + DisabledRules: disabledRules, + PackageDoc: packageDoc, + SymbolDecl: decls, + }, nil + } + + result := &model.InspectorResult{ + Files: make(map[*ast.File]*model.FileInspection, len(pass.Files)), + } + + for _, f := range pass.Files { + ft := util.GetPassFileToken(f, pass) + if ft == nil { + continue + } + if !cfg.IsPathApplicable(ft.Name()) { + continue + } + + if fi, err := inspect(f); err != nil { + return nil, fmt.Errorf("inspector failed: %w", err) + } else { + result.Files[f] = fi + } + } + return result, nil +} + +func (i *Inspector) extractCommentGroup(cg *ast.CommentGroup) *model.CommentGroup { + if cg == nil { + return nil + } + + lines := make([]string, 0, len(cg.List)) + for _, l := range cg.List { + lines = append(lines, l.Text) + } + rawText := strings.Join(lines, "\n") + + text := cg.Text() + return &model.CommentGroup{ + CG: *cg, + Parsed: *i.parser.Parse(text), + Text: text, + DisabledRules: extractDisableDirectivesInComment(rawText), + } +} + +func extractDisableDirectivesInComment(s string) model.InspectorResultDisableRules { + result := model.InspectorResultDisableRules{} + for _, directive := range disableDirectivePattern.FindAllStringSubmatch(s, -1) { + args := directive[1] + if args == "" { + result.All = true + continue + } + + for name := range strings.SplitSeq(strings.TrimSpace(args), " ") { + if model.AllRules.Has(model.Rule(name)) { + result.Rules = result.Rules.Add(model.Rule(name)) + } + } + } + return result +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/analyzer.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/analyzer.go new file mode 100644 index 000000000..ded44c4e7 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/analyzer.go @@ -0,0 +1,11 @@ +package model + +import ( + "golang.org/x/tools/go/analysis" +) + +// Analyzer defines an analyzer. +type Analyzer interface { + // GetAnalyzer returns the underlying analyzer. + GetAnalyzer() *analysis.Analyzer +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/checker.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/checker.go new file mode 100644 index 000000000..dca42e279 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/checker.go @@ -0,0 +1,24 @@ +package model + +import "golang.org/x/tools/go/analysis" + +// AnalysisContext provides contextual information about the running analysis. +type AnalysisContext struct { + // Config provides analyzer configuration. + Config Config + + // InspectorResult is the analysis result of the pre-run inspector. + InspectorResult *InspectorResult + + // Pass is the analysis Pass instance. + Pass *analysis.Pass +} + +// Checker defines a rule checker. +type Checker interface { + // GetCoveredRules returns the set of rules applied by the checker. + GetCoveredRules() RuleSet + + // Apply checks for the rule(s). + Apply(actx *AnalysisContext) error +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go new file mode 100644 index 000000000..78fa62a27 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go @@ -0,0 +1,123 @@ +package model + +import ( + "maps" + "regexp" + "slices" +) + +// ConfigBuilder defines a configuration builder. +type ConfigBuilder interface { + // SetOverride sets the configuration override. + SetOverride(override *ConfigOverride) + + // GetConfig builds and returns the configuration object for the given path. + GetConfig(cwd string) (Config, error) +} + +// DefaultSet defines the default set of rules to enable. +type DefaultSet string + +const ( + // DefaultSetAll enables all rules. + DefaultSetAll DefaultSet = "all" + // DefaultSetNone disables all rules. + DefaultSetNone DefaultSet = "none" + // DefaultSetBasic enables a basic set of rules. + DefaultSetBasic DefaultSet = "basic" + + // DefaultDefaultSet is the default set of rules to enable. + DefaultDefaultSet = DefaultSetBasic +) + +// DefaultSetToRules maps default sets to the corresponding rule sets. +var DefaultSetToRules = map[DefaultSet]RuleSet{ + DefaultSetAll: AllRules, + DefaultSetNone: {}, + DefaultSetBasic: func() RuleSet { + return RuleSet{}.Add( + PkgDocRule, + SinglePkgDocRule, + StartWithNameRule, + DeprecatedRule, + ) + }(), +} + +// DefaultSetValues holds the valid values for DefaultSet. +var DefaultSetValues = func() []DefaultSet { + values := slices.Collect(maps.Keys(DefaultSetToRules)) + slices.Sort(values) + return values +}() + +// ConfigOverride represents a configuration override. +// +// Non-nil values (including empty slices) indicate that the corresponding field +// is overridden. +type ConfigOverride struct { + // ConfigFilePath is the path to config file. + ConfigFilePath *string + + // Include is the overridden list of regexp patterns matching the files that + // the linter should include. + Include []*regexp.Regexp + + // Exclude is the overridden list of regexp patterns matching the files that + // the linter should exclude. + Exclude []*regexp.Regexp + + // Default is the default set of rules to enable. + Default *DefaultSet + + // Enable is the overridden list of rules to enable. + Enable *RuleSet + + // Disable is the overridden list of rules to disable. + Disable *RuleSet +} + +// NewConfigOverride returns a new config override instance. +func NewConfigOverride() *ConfigOverride { + return &ConfigOverride{} +} + +// Config defines an analyzer configuration. +type Config interface { + // GetCWD returns the directory that the configuration is applied to. This + // is the base to compute relative paths to include/exclude files. + GetCWD() string + + // GetConfigFilePath returns the path to the configuration file. If there is + // no configuration file, which is the case when the default is used, this + // will be an empty string. + GetConfigFilePath() string + + // IsAnyRuleEnabled determines if any of the given rule names is among + // enabled rules, or not among disabled rules. + IsAnyRuleApplicable(RuleSet) bool + + // IsPathApplicable determines if the given path matches the included path + // patterns, or does not match the excluded path patterns. + IsPathApplicable(path string) bool + + // Returns the rule-specific options. + // + // It never returns a nil pointer. + GetRuleOptions() *RuleOptions +} + +// RuleOptions represents individual linter rule configurations. +type RuleOptions struct { + MaxLenLength uint `option:"max-len/length"` + MaxLenIncludeTests bool `option:"max-len/include-tests"` + PkgDocIncludeTests bool `option:"pkg-doc/include-tests"` + SinglePkgDocIncludeTests bool `option:"single-pkg-doc/include-tests"` + RequirePkgDocIncludeTests bool `option:"require-pkg-doc/include-tests"` + RequireDocIncludeTests bool `option:"require-doc/include-tests"` + RequireDocIgnoreExported bool `option:"require-doc/ignore-exported"` + RequireDocIgnoreUnexported bool `option:"require-doc/ignore-unexported"` + StartWithNameIncludeTests bool `option:"start-with-name/include-tests"` + StartWithNameIncludeUnexported bool `option:"start-with-name/include-unexported"` + NoUnusedLinkIncludeTests bool `option:"no-unused-link/include-tests"` +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/doc.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/doc.go new file mode 100644 index 000000000..b4afa8d46 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/doc.go @@ -0,0 +1,2 @@ +// Package model provides data models for the linter. +package model diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go new file mode 100644 index 000000000..3166e17fa --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go @@ -0,0 +1,189 @@ +package model + +import ( + "go/ast" + "go/doc/comment" + + "golang.org/x/tools/go/analysis" +) + +// Inspector defines a pre-run inspector. +type Inspector interface { + // GetAnalyzer returns the underlying analyzer. + GetAnalyzer() *analysis.Analyzer +} + +// InspectorResult represents the result of the inspector analysis. +type InspectorResult struct { + // Files provides extracted information per AST file. + Files map[*ast.File]*FileInspection +} + +// FileInspection represents the inspection result for a single file. +type FileInspection struct { + // DisabledRules contains information about rules disabled at top level. + DisabledRules InspectorResultDisableRules + + // PackageDoc represents the package godoc, if any. + PackageDoc *CommentGroup + + // SymbolDecl represents symbols declared in the package file. + SymbolDecl []SymbolDecl +} + +// InspectorResultDisableRules contains the list of disabled rules. +type InspectorResultDisableRules struct { + // All indicates whether all rules are disabled. + All bool + + // Rules is the set of rules disabled. + Rules RuleSet +} + +// SymbolDeclKind is the enum type for the symbol declarations. +type SymbolDeclKind string + +const ( + // SymbolDeclKindBad represents an unknown declaration kind. + SymbolDeclKindBad SymbolDeclKind = "bad" + // SymbolDeclKindFunc represents a function declaration kind. + SymbolDeclKindFunc SymbolDeclKind = "func" + // SymbolDeclKindConst represents a const declaration kind. + SymbolDeclKindConst SymbolDeclKind = "const" + // SymbolDeclKindType represents a type declaration kind. + SymbolDeclKindType SymbolDeclKind = "type" + // SymbolDeclKindVar represents a var declaration kind. + SymbolDeclKindVar SymbolDeclKind = "var" +) + +// SymbolDecl represents a top level declaration. +type SymbolDecl struct { + // Decl is the underlying declaration node. + Decl ast.Decl + + // Kind is the declaration kind (e.g., func or type). + Kind SymbolDeclKind + + // IsTypeAlias indicates that the type symbol is an alias. For example: + // + // type Foo = int + // + // This is always false for non-type declaration (e.g., const or var). + IsTypeAlias bool + + // Name is the name of the declared symbol. + Name string + + // Ident is the symbol identifier node. + Ident *ast.Ident + + // MultiNameDecl determines whether the symbol is declared as part of a + // multi-name declaration spec; For example: + // + // const foo, bar = 0, 0 + // + // This field is only valid for const, var, or type declarations. + MultiNameDecl bool + + // MultiNameIndex is the index of the declared symbol within the spec. For + // example, in the below declaration, the index of "foo" and "bar" are 0 and + // 1, respectively: + // + // const foo, bar = 0, 0 + // + // In single-name specs, this will be 0. + MultiNameIndex int + + // MultiSpecDecl determines whether the symbol is declared as part of a + // multi-spec declaration. A multi spec declaration is const/var/type + // declaration with a pair of grouping brackets, even if there is only one + // spec between the brackets. For example, these are multi-spec + // declarations: + // + // const ( + // foo = 0 + // ) + // + // const ( + // foo, bar = 0, 0 + // ) + // + // const ( + // foo = 0 + // bar = 0 + // ) + // + // const ( + // foo, bar = 0, 0 + // baz = 0 + // ) + // + MultiSpecDecl bool + + // SpecIndex is the index of the spec where the symbol is declared. For + // example, in the below declaration, the index of "foo" and "bar" are 0 and + // 1, respectively: + // + // const ( + // foo = 0 + // bar = 0 + // ) + // + // In single-spec declarations, this will be 0. + MultiSpecIndex int + + // Doc is the comment group associated to the symbol. For example: + // + // // godoc + // const foo = 0 + // + // const ( + // // godoc + // foo = 0 + // ) + // + // Note that, as in the first example above, for single-spec declarations + // (i.e., single line declarations), the godoc above the const/var/type + // keyword is considered as the declaration doc, and the parent doc will be + // nil. + Doc *CommentGroup + + // TrailingDoc is the comment group that is following the symbol + // declaration. For example, this is a trailing comment group: + // + // const ( + // foo = 0 // trailing comment group. + // ) + // + TrailingDoc *CommentGroup + + // Doc is the comment group associated to the parent declaration. For + // instance: + // + // // parent godoc + // const ( + // // godoc + // Foo = 0 + // ) + // + // Note that for single-spec declarations (i.e., single line declarations), + // the godoc above the const/var/type keyword is considered as the + // declaration doc, and the parent doc will be nil. + ParentDoc *CommentGroup +} + +// CommentGroup represents an ast.CommentGroup and its parsed godoc instance. +type CommentGroup struct { + // CG represents the AST comment group. + CG ast.CommentGroup + + // Parsed represents the comment group parsed into a godoc. + Parsed comment.Doc + + // Test is the comment group text. + Text string + + // DisabledRules contains information about rules disabled in the comment + // group. + DisabledRules InspectorResultDisableRules +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/registry.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/registry.go new file mode 100644 index 000000000..64512291d --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/registry.go @@ -0,0 +1,14 @@ +package model + +// Registry defines a registry of checkers. +type Registry interface { + // Add registers a new checker. + Add(Checker) + + // List returns a slice of the registered checkers. + List() []Checker + + // GetCoveredRules returns the set of rules covered by the registered + // checkers. + GetCoveredRules() RuleSet +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go new file mode 100644 index 000000000..c53fcf61a --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go @@ -0,0 +1,37 @@ +package model + +// Rule represents a rule. +type Rule string + +const ( + // PkgDocRule represents the "pkg-doc" rule. + PkgDocRule Rule = "pkg-doc" + // SinglePkgDocRule represents the "single-pkg-doc" rule. + SinglePkgDocRule Rule = "single-pkg-doc" + // RequirePkgDocRule represents the "require-pkg-doc" rule. + RequirePkgDocRule Rule = "require-pkg-doc" + // StartWithNameRule represents the "start-with-name" rule. + StartWithNameRule Rule = "start-with-name" + // RequireDocRule represents the "require-doc" rule. + RequireDocRule Rule = "require-doc" + // DeprecatedRule represents the "deprecated" rule. + DeprecatedRule Rule = "deprecated" + // MaxLenRule represents the "max-len" rule. + MaxLenRule Rule = "max-len" + // NoUnusedLinkRule represents the "no-unused-link" rule. + NoUnusedLinkRule Rule = "no-unused-link" +) + +// AllRules is the set of all supported rules. +var AllRules = func() RuleSet { + return RuleSet{}.Add( + PkgDocRule, + SinglePkgDocRule, + RequirePkgDocRule, + StartWithNameRule, + RequireDocRule, + DeprecatedRule, + MaxLenRule, + NoUnusedLinkRule, + ) +}() diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/model/ruleset.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/ruleset.go new file mode 100644 index 000000000..0cf195447 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/model/ruleset.go @@ -0,0 +1,97 @@ +package model + +import "slices" + +// RuleSet represents an immutable set of rule names. +// +// A zero rule set represents an empty set. +type RuleSet struct { + m map[Rule]struct{} +} + +// Merge combines the rules in the current and the given rule sets into a new +// set. +func (rs RuleSet) Merge(another RuleSet) RuleSet { + result := RuleSet{ + m: make(map[Rule]struct{}, len(rs.m)+len(another.m)), + } + for r := range rs.m { + result.m[r] = struct{}{} + } + for r := range another.m { + result.m[r] = struct{}{} + } + return result +} + +// Add returns a new rule set containing the rules in the current set and the +// rules provided as arguments. +func (rs RuleSet) Add(rules ...Rule) RuleSet { + result := RuleSet{ + m: make(map[Rule]struct{}, len(rs.m)+len(rules)), + } + for r := range rs.m { + result.m[r] = struct{}{} + } + for _, r := range rules { + result.m[r] = struct{}{} + } + return result +} + +// Remove returns a new rule set containing the rules in the current set +// excluding those provided as arguments. +func (rs RuleSet) Remove(rules ...Rule) RuleSet { + result := RuleSet{ + m: make(map[Rule]struct{}, len(rs.m)), + } + for r := range rs.m { + result.m[r] = struct{}{} + } + for _, r := range rules { + delete(result.m, r) + } + return result +} + +// Has determines whether the given rule is in the set. +func (rs RuleSet) Has(rule Rule) bool { + _, ok := rs.m[rule] + return ok +} + +// HasCommonsWith indicates at least one rule is in common with the given rule +// set. +// +// If the given set is empty/zero, the method will return false. +func (rs RuleSet) HasCommonsWith(another RuleSet) bool { + for r := range another.m { + if _, ok := rs.m[r]; ok { + return true + } + } + return false +} + +// IsSupersetOf indicates that all rules in the given set are in the current +// set. +// +// If the given set is empty/zero, the method will return true. +func (rs RuleSet) IsSupersetOf(another RuleSet) bool { + for r := range another.m { + if _, ok := rs.m[r]; !ok { + return false + } + } + return true +} + +// List returns a slice of the rules in the set. +func (rs RuleSet) List() []Rule { + rules := make([]Rule, 0, len(rs.m)) + for r := range rs.m { + rules = append(rules, r) + } + slices.Sort(rules) + return rules +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/util/ast.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/util/ast.go new file mode 100644 index 000000000..1441001d0 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/util/ast.go @@ -0,0 +1,66 @@ +package util + +import ( + "go/ast" + "go/token" + "iter" + "strings" + + "golang.org/x/tools/go/analysis" + + "github.com/godoc-lint/godoc-lint/pkg/model" +) + +// GetPassFileToken is a helper function to return the file token associated +// with the given AST file. +func GetPassFileToken(f *ast.File, pass *analysis.Pass) *token.File { + if f.Pos() == token.NoPos { + return nil + } + ft := pass.Fset.File(f.Pos()) + if ft == nil { + return nil + } + return ft +} + +// AnalysisApplicableFiles returns an iterator looping over files that are ready +// to be analyzed. +// +// The yield-ed arguments are never nil. +func AnalysisApplicableFiles(actx *model.AnalysisContext, includeTests bool, ruleSet model.RuleSet) iter.Seq2[*ast.File, *model.FileInspection] { + return func(yield func(*ast.File, *model.FileInspection) bool) { + if actx.InspectorResult == nil { + return + } + + for _, f := range actx.Pass.Files { + ir := actx.InspectorResult.Files[f] + + if ir == nil { + continue + } + + ft := GetPassFileToken(f, actx.Pass) + if ft == nil { + continue + } + + if !actx.Config.IsPathApplicable(ft.Name()) { + continue + } + + if !includeTests && strings.HasSuffix(ft.Name(), "_test.go") { + continue + } + + if ir.DisabledRules.All || ir.DisabledRules.Rules.IsSupersetOf(ruleSet) { + continue + } + + if !yield(f, ir) { + return + } + } + } +} diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/util/doc.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/util/doc.go new file mode 100644 index 000000000..1c40b7468 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/util/doc.go @@ -0,0 +1,2 @@ +// Package util provides utility functions for the linter. +package util diff --git a/vendor/github.com/godoc-lint/godoc-lint/pkg/util/path.go b/vendor/github.com/godoc-lint/godoc-lint/pkg/util/path.go new file mode 100644 index 000000000..b7dd451e2 --- /dev/null +++ b/vendor/github.com/godoc-lint/godoc-lint/pkg/util/path.go @@ -0,0 +1,16 @@ +package util + +import ( + "path/filepath" + "strings" +) + +// IsPathUnderBaseDir determines whether the given path is a sub-directory of +// the given base, lexicographically. +func IsPathUnderBaseDir(baseDir, path string) bool { + rel, err := filepath.Rel(baseDir, path) + if err != nil { + return false + } + return rel == "." || rel != ".." && !strings.HasPrefix(filepath.ToSlash(rel), "../") +} diff --git a/vendor/github.com/gofrs/flock/.golangci.yml b/vendor/github.com/gofrs/flock/.golangci.yml index 3ad88a38f..bc837b266 100644 --- a/vendor/github.com/gofrs/flock/.golangci.yml +++ b/vendor/github.com/gofrs/flock/.golangci.yml @@ -1,5 +1,12 @@ -run: - timeout: 10m +version: "2" + +formatters: + enable: + - gofumpt + - goimports + settings: + gofumpt: + extra-rules: true linters: enable: @@ -18,9 +25,7 @@ linters: - gocritic - godot - godox - - gofumpt - goheader - - goimports - gomoddirectives - goprintffuncname - gosec @@ -31,84 +36,81 @@ linters: - misspell - nolintlint - revive - - stylecheck - - tenv + - staticcheck - testifylint - thelper - unconvert - unparam - usestdlibvars - whitespace - -linters-settings: - misspell: - locale: US - godox: - keywords: - - FIXME - goheader: - template: |- - Copyright 2015 Tim Heckman. All rights reserved. - Copyright 2018-{{ YEAR }} The Gofrs. All rights reserved. - Use of this source code is governed by the BSD 3-Clause - license that can be found in the LICENSE file. - gofumpt: - extra-rules: true - gocritic: - enabled-tags: - - diagnostic - - style - - performance - disabled-checks: - - paramTypeCombine # already handle by gofumpt.extra-rules - - whyNoLint # already handle by nonolint - - unnamedResult - - hugeParam - - sloppyReassign - - rangeValCopy - - octalLiteral - - ptrToRefParam - - appendAssign - - ruleguard - - httpNoBody - - exposedSyncMutex - - revive: - rules: - - name: struct-tag - - name: blank-imports - - name: context-as-argument - - name: context-keys-type - - name: dot-imports - - name: error-return - - name: error-strings - - name: error-naming - - name: exported - - name: if-return - - name: increment-decrement - - name: var-naming - - name: var-declaration - - name: package-comments - - name: range - - name: receiver-naming - - name: time-naming - - name: unexported-return - - name: indent-error-flow - - name: errorf - - name: empty-block - - name: superfluous-else - - name: unused-parameter - - name: unreachable-code - - name: redefines-builtin-id + - wsl_v5 + settings: + gocritic: + disabled-checks: + - paramTypeCombine # already handle by gofumpt.extra-rules + - whyNoLint # already handle by nonolint + - unnamedResult + - hugeParam + - sloppyReassign + - rangeValCopy + - octalLiteral + - ptrToRefParam + - appendAssign + - ruleguard + - httpNoBody + - exposedSyncMutex + enabled-tags: + - diagnostic + - style + - performance + godox: + keywords: + - FIXME + goheader: + template: |- + Copyright 2015 Tim Heckman. All rights reserved. + Copyright 2018-{{ YEAR }} The Gofrs. All rights reserved. + Use of this source code is governed by the BSD 3-Clause + license that can be found in the LICENSE file. + gosec: + excludes: + - G115 + misspell: + locale: US + revive: + rules: + - name: struct-tag + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: error-return + - name: error-strings + - name: error-naming + - name: exported + - name: if-return + - name: increment-decrement + - name: var-naming + - name: var-declaration + - name: package-comments + - name: range + - name: receiver-naming + - name: time-naming + - name: unexported-return + - name: indent-error-flow + - name: errorf + - name: empty-block + - name: superfluous-else + - name: unused-parameter + - name: unreachable-code + - name: redefines-builtin-id + exclusions: + presets: + - comments + - common-false-positives + - std-error-handling issues: - exclude-use-default: true max-issues-per-linter: 0 max-same-issues: 0 -output: - show-stats: true - sort-results: true - sort-order: - - linter - - file diff --git a/vendor/github.com/gofrs/flock/LICENSE b/vendor/github.com/gofrs/flock/LICENSE index 7de525bf0..c785e5e4b 100644 --- a/vendor/github.com/gofrs/flock/LICENSE +++ b/vendor/github.com/gofrs/flock/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2024, The Gofrs +Copyright (c) 2018-2025, The Gofrs Copyright (c) 2015-2020, Tim Heckman All rights reserved. diff --git a/vendor/github.com/gofrs/flock/flock.go b/vendor/github.com/gofrs/flock/flock.go index ff942b228..4cb0746a7 100644 --- a/vendor/github.com/gofrs/flock/flock.go +++ b/vendor/github.com/gofrs/flock/flock.go @@ -1,5 +1,5 @@ // Copyright 2015 Tim Heckman. All rights reserved. -// Copyright 2018-2024 The Gofrs. All rights reserved. +// Copyright 2018-2025 The Gofrs. All rights reserved. // Use of this source code is governed by the BSD 3-Clause // license that can be found in the LICENSE file. @@ -62,6 +62,7 @@ type Flock struct { func New(path string, opts ...Option) *Flock { // create it if it doesn't exist, and open the file read-only. flags := os.O_CREATE + switch runtime.GOOS { case "aix", "solaris", "illumos": // AIX cannot preform write-lock (i.e. exclusive) on a read-only file. @@ -124,6 +125,22 @@ func (f *Flock) RLocked() bool { return f.r } +// Stat returns the FileInfo structure describing the lock file. +// If the lock file does not exist or cannot be accessed, an error is returned. +// +// This can be used to check the modification time of the lock file, +// which is useful for detecting stale locks. +func (f *Flock) Stat() (fs.FileInfo, error) { + f.m.RLock() + defer f.m.RUnlock() + + if f.fh != nil { + return f.fh.Stat() + } + + return os.Stat(f.path) +} + func (f *Flock) String() string { return f.path } @@ -158,7 +175,6 @@ func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Durati case <-ctx.Done(): return false, ctx.Err() case <-time.After(retryDelay): - // try again } } } diff --git a/vendor/github.com/gofrs/flock/flock_others.go b/vendor/github.com/gofrs/flock/flock_others.go index 18b14f1bd..92d0f7e95 100644 --- a/vendor/github.com/gofrs/flock/flock_others.go +++ b/vendor/github.com/gofrs/flock/flock_others.go @@ -1,3 +1,8 @@ +// Copyright 2015 Tim Heckman. All rights reserved. +// Copyright 2018-2025 The Gofrs. All rights reserved. +// Use of this source code is governed by the BSD 3-Clause +// license that can be found in the LICENSE file. + //go:build (!unix && !windows) || plan9 package flock diff --git a/vendor/github.com/gofrs/flock/flock_unix.go b/vendor/github.com/gofrs/flock/flock_unix.go index cf8919c7a..77de7a883 100644 --- a/vendor/github.com/gofrs/flock/flock_unix.go +++ b/vendor/github.com/gofrs/flock/flock_unix.go @@ -1,5 +1,5 @@ // Copyright 2015 Tim Heckman. All rights reserved. -// Copyright 2018-2024 The Gofrs. All rights reserved. +// Copyright 2018-2025 The Gofrs. All rights reserved. // Use of this source code is governed by the BSD 3-Clause // license that can be found in the LICENSE file. @@ -155,6 +155,7 @@ func (f *Flock) try(locked *bool, flag int) (bool, error) { } var retried bool + retry: err := unix.Flock(int(f.fh.Fd()), flag|unix.LOCK_NB) diff --git a/vendor/github.com/gofrs/flock/flock_unix_fcntl.go b/vendor/github.com/gofrs/flock/flock_unix_fcntl.go index ea007b47d..05c2f88c6 100644 --- a/vendor/github.com/gofrs/flock/flock_unix_fcntl.go +++ b/vendor/github.com/gofrs/flock/flock_unix_fcntl.go @@ -1,5 +1,5 @@ // Copyright 2015 Tim Heckman. All rights reserved. -// Copyright 2018-2024 The Gofrs. All rights reserved. +// Copyright 2018-2025 The Gofrs. All rights reserved. // Use of this source code is governed by the BSD 3-Clause // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gofrs/flock/flock_windows.go b/vendor/github.com/gofrs/flock/flock_windows.go index dfd31e15f..aa144f156 100644 --- a/vendor/github.com/gofrs/flock/flock_windows.go +++ b/vendor/github.com/gofrs/flock/flock_windows.go @@ -1,5 +1,5 @@ // Copyright 2015 Tim Heckman. All rights reserved. -// Copyright 2018-2024 The Gofrs. All rights reserved. +// Copyright 2018-2025 The Gofrs. All rights reserved. // Use of this source code is governed by the BSD 3-Clause // license that can be found in the LICENSE file. @@ -23,6 +23,8 @@ const winLockfileSharedLock = 0x00000000 // ErrorLockViolation is the error code returned from the Windows syscall when a lock would block, // and you ask to fail immediately. +// +//nolint:errname // It should be renamed to `ErrLockViolation`. const ErrorLockViolation windows.Errno = 0x21 // 33 // Lock is a blocking call to try and take an exclusive file lock. diff --git a/vendor/github.com/olekukonko/tablewriter/.gitignore b/vendor/github.com/golangci/asciicheck/.gitignore similarity index 58% rename from vendor/github.com/olekukonko/tablewriter/.gitignore rename to vendor/github.com/golangci/asciicheck/.gitignore index b66cec635..26938fd81 100644 --- a/vendor/github.com/olekukonko/tablewriter/.gitignore +++ b/vendor/github.com/golangci/asciicheck/.gitignore @@ -1,5 +1,10 @@ -# Created by .ignore support plugin (hsz.mobi) -### Go template +# IntelliJ project files +.idea +*.iml +out +gen + +# Go template # Binaries for programs and plugins *.exe *.exe~ @@ -7,9 +12,10 @@ *.so *.dylib -# Test binary, build with `go test -c` +# Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out +/asciicheck diff --git a/vendor/github.com/golangci/asciicheck/.golangci.yml b/vendor/github.com/golangci/asciicheck/.golangci.yml new file mode 100644 index 000000000..e28845eb5 --- /dev/null +++ b/vendor/github.com/golangci/asciicheck/.golangci.yml @@ -0,0 +1,87 @@ +version: "2" + +formatters: + enable: + - gci + - gofumpt + settings: + gofumpt: + extra-rules: true + +linters: + default: all + disable: + - cyclop # duplicate of gocyclo + - dupl + - errchkjson + - exhaustive + - exhaustruct + - lll + - mnd + - nilnil + - nlreturn + - nonamedreturns + - paralleltest + - prealloc + - rowserrcheck # not relevant (SQL) + - sqlclosecheck # not relevant (SQL) + - testpackage + - tparallel + - varnamelen + - wsl # Deprecated + - forcetypeassert # recheck in the future. + + settings: + depguard: + rules: + main: + deny: + - pkg: github.com/instana/testify + desc: not allowed + - pkg: github.com/pkg/errors + desc: Should be replaced by standard lib errors package + funlen: + lines: -1 + statements: 40 + goconst: + min-len: 5 + min-occurrences: 3 + gocritic: + disabled-checks: + - sloppyReassign + - rangeValCopy + - octalLiteral + - paramTypeCombine # already handle by gofumpt.extra-rules + enabled-tags: + - diagnostic + - style + - performance + settings: + hugeParam: + sizeThreshold: 100 + gocyclo: + min-complexity: 20 + godox: + keywords: + - FIXME + govet: + disable: + - fieldalignment + enable-all: true + misspell: + locale: US + mnd: + ignored-numbers: + - "124" + wsl: + force-case-trailing-whitespace: 1 + allow-trailing-comment: true + exclusions: + presets: + - comments + - std-error-handling + - common-false-positives + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 diff --git a/vendor/github.com/tdakkota/asciicheck/LICENSE b/vendor/github.com/golangci/asciicheck/LICENSE similarity index 100% rename from vendor/github.com/tdakkota/asciicheck/LICENSE rename to vendor/github.com/golangci/asciicheck/LICENSE diff --git a/vendor/github.com/golangci/asciicheck/Makefile b/vendor/github.com/golangci/asciicheck/Makefile new file mode 100644 index 000000000..cdfc26114 --- /dev/null +++ b/vendor/github.com/golangci/asciicheck/Makefile @@ -0,0 +1,15 @@ +.PHONY: clean check test build + +default: clean check test build + +clean: + rm -rf dist/ cover.out + +test: clean + go test -v -cover ./... + +check: + golangci-lint run + +build: + go build -ldflags "-s -w" -trimpath ./cmd/asciicheck/ diff --git a/vendor/github.com/tdakkota/asciicheck/README.md b/vendor/github.com/golangci/asciicheck/README.md similarity index 75% rename from vendor/github.com/tdakkota/asciicheck/README.md rename to vendor/github.com/golangci/asciicheck/README.md index a7ff5884f..0d1da4b97 100644 --- a/vendor/github.com/tdakkota/asciicheck/README.md +++ b/vendor/github.com/golangci/asciicheck/README.md @@ -1,13 +1,19 @@ -# asciicheck [![Go Report Card](https://goreportcard.com/badge/github.com/tdakkota/asciicheck)](https://goreportcard.com/report/github.com/tdakkota/asciicheck) [![codecov](https://codecov.io/gh/tdakkota/asciicheck/branch/master/graph/badge.svg)](https://codecov.io/gh/tdakkota/asciicheck) ![Go](https://github.com/tdakkota/asciicheck/workflows/Go/badge.svg) +# asciicheck + +[![Go Report Card](https://goreportcard.com/badge/github.com/golangci/asciicheck)](https://goreportcard.com/report/github.com/golangci/asciicheck) + Simple linter to check that your code does not contain non-ASCII identifiers -# Install +The project has been moved to the golangci organization because the GitHub account of the original author (@tdakkota) is no longer available. + +## Install +```bash +go install github.com/golangci/asciicheck/cmd/asciicheck@latest ``` -go get -u github.com/tdakkota/asciicheck/cmd/asciicheck -``` -# Reason to use +## Reason to use + So, do you see this code? Looks correct, isn't it? ```go @@ -22,20 +28,24 @@ func main() { fmt.Println(s) } ``` + But if you try to run it, you will get an error: + ``` ./prog.go:8:7: undefined: TestStruct ``` What? `TestStruct` is defined above, but compiler thinks diffrent. Why? **Answer**: + Because `TestStruct` is not `TеstStruct`. ``` type TеstStruct struct{} ^ this 'e' (U+0435) is not 'e' (U+0065) ``` -# Usage +## Usage + asciicheck uses [`singlechecker`](https://pkg.go.dev/golang.org/x/tools/go/analysis/singlechecker) package to run: ``` diff --git a/vendor/github.com/tdakkota/asciicheck/ascii.go b/vendor/github.com/golangci/asciicheck/ascii.go similarity index 100% rename from vendor/github.com/tdakkota/asciicheck/ascii.go rename to vendor/github.com/golangci/asciicheck/ascii.go diff --git a/vendor/github.com/golangci/asciicheck/asciicheck.go b/vendor/github.com/golangci/asciicheck/asciicheck.go new file mode 100644 index 000000000..0983c7270 --- /dev/null +++ b/vendor/github.com/golangci/asciicheck/asciicheck.go @@ -0,0 +1,104 @@ +package asciicheck + +import ( + "fmt" + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +func NewAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "asciicheck", + Doc: "checks that all code identifiers does not have non-ASCII symbols in the name", + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: run, + } +} + +func run(pass *analysis.Pass) (any, error) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + nodeFilter := []ast.Node{ + (*ast.File)(nil), + (*ast.ImportSpec)(nil), + (*ast.TypeSpec)(nil), + (*ast.ValueSpec)(nil), + (*ast.FuncDecl)(nil), + (*ast.StructType)(nil), + (*ast.FuncType)(nil), + (*ast.InterfaceType)(nil), + (*ast.LabeledStmt)(nil), + (*ast.AssignStmt)(nil), + } + + insp.Preorder(nodeFilter, func(n ast.Node) { + switch n := n.(type) { + case *ast.File: + checkIdent(pass, n.Name) + case *ast.ImportSpec: + checkIdent(pass, n.Name) + case *ast.TypeSpec: + checkIdent(pass, n.Name) + checkFieldList(pass, n.TypeParams) + case *ast.ValueSpec: + for _, name := range n.Names { + checkIdent(pass, name) + } + case *ast.FuncDecl: + checkIdent(pass, n.Name) + checkFieldList(pass, n.Recv) + case *ast.StructType: + checkFieldList(pass, n.Fields) + case *ast.FuncType: + checkFieldList(pass, n.TypeParams) + checkFieldList(pass, n.Params) + checkFieldList(pass, n.Results) + case *ast.InterfaceType: + checkFieldList(pass, n.Methods) + case *ast.LabeledStmt: + checkIdent(pass, n.Label) + case *ast.AssignStmt: + if n.Tok == token.DEFINE { + for _, expr := range n.Lhs { + if ident, ok := expr.(*ast.Ident); ok { + checkIdent(pass, ident) + } + } + } + } + }) + + return nil, nil +} + +func checkIdent(pass *analysis.Pass, v *ast.Ident) { + if v == nil { + return + } + + ch, ascii := isASCII(v.Name) + if !ascii { + pass.Report( + analysis.Diagnostic{ + Pos: v.Pos(), + Message: fmt.Sprintf("identifier %q contain non-ASCII character: %#U", v.Name, ch), + }, + ) + } +} + +func checkFieldList(pass *analysis.Pass, f *ast.FieldList) { + if f == nil { + return + } + + for _, f := range f.List { + for _, name := range f.Names { + checkIdent(pass, name) + } + } +} diff --git a/vendor/github.com/golangci/go-printf-func-name/pkg/analyzer/analyzer.go b/vendor/github.com/golangci/go-printf-func-name/pkg/analyzer/analyzer.go index bce4b242e..0b41500f2 100644 --- a/vendor/github.com/golangci/go-printf-func-name/pkg/analyzer/analyzer.go +++ b/vendor/github.com/golangci/go-printf-func-name/pkg/analyzer/analyzer.go @@ -16,7 +16,7 @@ var Analyzer = &analysis.Analyzer{ Requires: []*analysis.Analyzer{inspect.Analyzer}, } -func run(pass *analysis.Pass) (interface{}, error) { +func run(pass *analysis.Pass) (any, error) { insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ @@ -44,24 +44,21 @@ func run(pass *analysis.Pass) (interface{}, error) { return } - if formatParamNames := params[len(params)-2].Names; len(formatParamNames) == 0 || formatParamNames[len(formatParamNames)-1].Name != "format" { + formatParamNames := params[len(params)-2].Names + if len(formatParamNames) == 0 || formatParamNames[len(formatParamNames)-1].Name != "format" { return } argsParamType, ok := params[len(params)-1].Type.(*ast.Ellipsis) - if !ok { // args are not ellipsis (...args) + if !ok { + // args are not ellipsis (...args) return } - elementType, ok := argsParamType.Elt.(*ast.InterfaceType) - if !ok { // args are not of interface type, but we need interface{} + if !isAny(argsParamType) { return } - if elementType.Methods != nil && len(elementType.Methods.List) != 0 { - return // has >= 1 method in interface, but we need an empty interface "interface{}" - } - if strings.HasSuffix(funcDecl.Name.Name, "f") { return } @@ -72,3 +69,22 @@ func run(pass *analysis.Pass) (interface{}, error) { return nil, nil } + +func isAny(ell *ast.Ellipsis) bool { + switch elt := ell.Elt.(type) { + case *ast.InterfaceType: + if elt.Methods != nil && len(elt.Methods.List) != 0 { + // has >= 1 method in interface, but we need an empty interface "interface{}" + return false + } + + return true + + case *ast.Ident: + if elt.Name == "any" { + return true + } + } + + return false +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/cmd/golangci-lint/main.go b/vendor/github.com/golangci/golangci-lint/v2/cmd/golangci-lint/main.go index f7f3091dc..acb09cd8c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/cmd/golangci-lint/main.go +++ b/vendor/github.com/golangci/golangci-lint/v2/cmd/golangci-lint/main.go @@ -4,7 +4,9 @@ import ( "cmp" "fmt" "os" + "regexp" "runtime/debug" + "strings" "github.com/golangci/golangci-lint/v2/pkg/commands" "github.com/golangci/golangci-lint/v2/pkg/exitcodes" @@ -23,7 +25,7 @@ func main() { info := createBuildInfo() if err := commands.Execute(info); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Failed executing command with error: %v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "The command is terminated due to an error: %v\n", err) os.Exit(exitcodes.Failure) } } @@ -49,6 +51,11 @@ func createBuildInfo() commands.BuildInfo { info.Version = buildInfo.Main.Version + matched, _ := regexp.MatchString(`v\d+\.\d+\.\d+`, buildInfo.Main.Version) + if matched { + info.Version = strings.TrimPrefix(buildInfo.Main.Version, "v") + } + var revision string var modified string for _, setting := range buildInfo.Settings { diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go b/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go index 627993d2e..138a36148 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go @@ -166,7 +166,7 @@ func (c *Cache) computePkgHash(pkg *packages.Package) (hashResults, error) { fmt.Fprintf(key, "pkgpath %s\n", pkg.PkgPath) - for _, f := range pkg.CompiledGoFiles { + for _, f := range slices.Concat(pkg.CompiledGoFiles, pkg.IgnoredFiles) { h, fErr := c.fileHash(f) if fErr != nil { return nil, fmt.Errorf("failed to calculate file %s hash: %w", f, fErr) diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisflags/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisflags/readme.md index 4d221d4ca..6035c2226 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisflags/readme.md +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisflags/readme.md @@ -5,4 +5,7 @@ This is just a copy of the code without any changes. ## History -- sync with https://github.com/golang/tools/blob/v0.28.0 +- https://github.com/golangci/golangci-lint/pull/6076 + - sync with https://github.com/golang/tools/blob/v0.37.0/go/analysis/internal/analysisflags +- https://github.com/golangci/golangci-lint/pull/5576 + - sync with https://github.com/golang/tools/blob/v0.28.0/go/analysis/internal/analysisflags diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/analysis.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/analysis.go index bb12600da..b613d1673 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/analysis.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/analysis.go @@ -8,25 +8,30 @@ package analysisinternal import ( "fmt" - "os" + "slices" "golang.org/x/tools/go/analysis" ) -// MakeReadFile returns a simple implementation of the Pass.ReadFile function. -func MakeReadFile(pass *analysis.Pass) func(filename string) ([]byte, error) { +// A ReadFileFunc is a function that returns the +// contents of a file, such as [os.ReadFile]. +type ReadFileFunc = func(filename string) ([]byte, error) + +// CheckedReadFile returns a wrapper around a Pass.ReadFile +// function that performs the appropriate checks. +func CheckedReadFile(pass *analysis.Pass, readFile ReadFileFunc) ReadFileFunc { return func(filename string) ([]byte, error) { if err := CheckReadable(pass, filename); err != nil { return nil, err } - return os.ReadFile(filename) + return readFile(filename) } } // CheckReadable enforces the access policy defined by the ReadFile field of [analysis.Pass]. func CheckReadable(pass *analysis.Pass, filename string) error { - if slicesContains(pass.OtherFiles, filename) || - slicesContains(pass.IgnoredFiles, filename) { + if slices.Contains(pass.OtherFiles, filename) || + slices.Contains(pass.IgnoredFiles, filename) { return nil } for _, f := range pass.Files { @@ -36,13 +41,3 @@ func CheckReadable(pass *analysis.Pass, filename string) error { } return fmt.Errorf("Pass.ReadFile: %s is not among OtherFiles, IgnoredFiles, or names of Files", filename) } - -// TODO(adonovan): use go1.21 slices.Contains. -func slicesContains[S ~[]E, E comparable](slice S, x E) bool { - for _, elem := range slice { - if elem == x { - return true - } - } - return false -} diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/readme.md index f301cdbeb..6c54592d9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/readme.md +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/analysisinternal/readme.md @@ -5,4 +5,7 @@ This is just a copy of the code without any changes. ## History -- sync with https://github.com/golang/tools/blob/v0.28.0 +- https://github.com/golangci/golangci-lint/pull/6076 + - sync with https://github.com/golang/tools/blob/v0.37.0/internal/analysisinternal/ +- https://github.com/golangci/golangci-lint/pull/5576 + - sync with https://github.com/golang/tools/blob/v0.28.0/internal/analysisinternal/ diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/diff.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/diff.go index a13547b7a..c12bdfd2a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/diff.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/diff.go @@ -7,6 +7,7 @@ package diff import ( "fmt" + "slices" "sort" "strings" ) @@ -64,7 +65,7 @@ func ApplyBytes(src []byte, edits []Edit) ([]byte, error) { // It may return a different slice. func validate(src string, edits []Edit) ([]Edit, int, error) { if !sort.IsSorted(editsSort(edits)) { - edits = append([]Edit(nil), edits...) + edits = slices.Clone(edits) SortEdits(edits) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/common.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/common.go index c3e82dd26..27fa9ecbd 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/common.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/common.go @@ -51,7 +51,7 @@ func (l lcs) fix() lcs { // from the set of diagonals in l, find a maximal non-conflicting set // this problem may be NP-complete, but we use a greedy heuristic, // which is quadratic, but with a better data structure, could be D log D. - // indepedent is not enough: {0,3,1} and {3,0,2} can't both occur in an lcs + // independent is not enough: {0,3,1} and {3,0,2} can't both occur in an lcs // which has to have monotone x and y if len(l) == 0 { return nil diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/doc.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/doc.go index 9029dd20b..aa4b0fb59 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/doc.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/doc.go @@ -139,7 +139,7 @@ computed labels. That is the worst case. Had the code noticed (x,y)=(u,v)=(3,3) from the edgegraph. The implementation looks for a number of special cases to try to avoid computing an extra forward path. If the two-sided algorithm has stop early (because D has become too large) it will have found a forward LCS and a -backwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointness may fail and the two +backwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointedness may fail and the two computed LCS may conflict. (An easy example is where A is a suffix of B, and shares a short prefix. The backwards LCS is all of A, and the forward LCS is a prefix of A.) The algorithm combines the two to form a best-effort LCS. In the worst case the forward partial LCS may have to diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go index 4353da15b..4c346706a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go @@ -105,7 +105,7 @@ func forward(e *editGraph) lcs { return ans } // from D to D+1 - for D := 0; D < e.limit; D++ { + for D := range e.limit { e.setForward(D+1, -(D + 1), e.getForward(D, -D)) if ok, ans := e.fdone(D+1, -(D + 1)); ok { return ans @@ -199,13 +199,14 @@ func (e *editGraph) bdone(D, k int) (bool, lcs) { } // run the backward algorithm, until success or up to the limit on D. +// (used only by tests) func backward(e *editGraph) lcs { e.setBackward(0, 0, e.ux) if ok, ans := e.bdone(0, 0); ok { return ans } // from D to D+1 - for D := 0; D < e.limit; D++ { + for D := range e.limit { e.setBackward(D+1, -(D + 1), e.getBackward(D, -D)-1) if ok, ans := e.bdone(D+1, -(D + 1)); ok { return ans @@ -299,7 +300,7 @@ func twosided(e *editGraph) lcs { e.setBackward(0, 0, e.ux) // from D to D+1 - for D := 0; D < e.limit; D++ { + for D := range e.limit { // just finished a backwards pass, so check if got, ok := e.twoDone(D, D); ok { return e.twolcs(D, D, got) @@ -376,10 +377,7 @@ func (e *editGraph) twoDone(df, db int) (int, bool) { if (df+db+e.delta)%2 != 0 { return 0, false // diagonals cannot overlap } - kmin := -db + e.delta - if -df > kmin { - kmin = -df - } + kmin := max(-df, -db+e.delta) kmax := db + e.delta if df < kmax { kmax = df diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go index b429a69ee..1c64d1ecd 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go @@ -72,7 +72,7 @@ func diffRunes(before, after []rune) []Edit { func runes(bytes []byte) []rune { n := utf8.RuneCount(bytes) runes := make([]rune, n) - for i := 0; i < n; i++ { + for i := range n { r, sz := utf8.DecodeRune(bytes) bytes = bytes[sz:] runes[i] = r diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md index 4b9798498..b28e41d9c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md @@ -5,4 +5,7 @@ This is just a copy of the code without any changes. ## History -- sync with https://github.com/golang/tools/blob/v0.28.0 +- https://github.com/golangci/golangci-lint/pull/6076 + - sync with https://github.com/golang/tools/blob/v0.37.0/internal/diff/ +- https://github.com/golangci/golangci-lint/pull/5576 + - sync with https://github.com/golang/tools/blob/v0.28.0/internal/diff/ diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go index cfbda6102..9a786dbbe 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go +++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go @@ -129,12 +129,12 @@ func toUnified(fromName, toName string, content string, edits []Edit, contextLin switch { case h != nil && start == last: - //direct extension + // direct extension case h != nil && start <= last+gap: - //within range of previous lines, add the joiners + // within range of previous lines, add the joiners addEqualLines(h, lines, last, start) default: - //need to start a new hunk + // need to start a new hunk if h != nil { // add the edge to the previous hunk addEqualLines(h, lines, last, last+contextLines) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go index 13e895057..9772841c9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go @@ -21,7 +21,7 @@ func newCacheCommand() *cacheCommand { cacheCmd := &cobra.Command{ Use: "cache", - Short: "Cache control and information", + Short: "Cache control and information.", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return cmd.Help() diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go index 6628aa427..b1889fa42 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go @@ -42,7 +42,7 @@ func newConfigCommand(log logutils.Log, info BuildInfo) *configCommand { configCmd := &cobra.Command{ Use: "config", - Short: "Config file information", + Short: "Configuration file information and verification.", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return cmd.Help() @@ -52,7 +52,7 @@ func newConfigCommand(log logutils.Log, info BuildInfo) *configCommand { verifyCommand := &cobra.Command{ Use: "verify", - Short: "Verify configuration against JSON schema", + Short: "Verify configuration against JSON schema.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.executeVerify, @@ -62,7 +62,7 @@ func newConfigCommand(log logutils.Log, info BuildInfo) *configCommand { pathCommand := &cobra.Command{ Use: "path", - Short: "Print used config path", + Short: "Print used configuration path.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.executePath, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go index ef7a4e094..1bbc47d8d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go @@ -17,7 +17,7 @@ import ( "github.com/santhosh-tekuri/jsonschema/v6" "github.com/spf13/cobra" "github.com/spf13/pflag" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/golangci/golangci-lint/v2/pkg/exitcodes" ) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/custom.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/custom.go index a53197ce3..e6a7f5ed7 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/custom.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/custom.go @@ -5,6 +5,7 @@ import ( "log" "os" + "github.com/fatih/color" "github.com/spf13/cobra" "github.com/golangci/golangci-lint/v2/pkg/commands/internal" @@ -13,11 +14,19 @@ import ( const envKeepTempFiles = "CUSTOM_GCL_KEEP_TEMP_FILES" +type customOptions struct { + version string + name string + destination string +} + type customCommand struct { cmd *cobra.Command cfg *internal.Configuration + opts customOptions + log logutils.Log } @@ -26,13 +35,20 @@ func newCustomCommand(logger logutils.Log) *customCommand { customCmd := &cobra.Command{ Use: "custom", - Short: "Build a version of golangci-lint with custom linters", + Short: "Build a version of golangci-lint with custom linters.", Args: cobra.NoArgs, PreRunE: c.preRunE, RunE: c.runE, SilenceUsage: true, } + flagSet := customCmd.PersistentFlags() + flagSet.SortFlags = false // sort them as they are defined here + + flagSet.StringVar(&c.opts.version, "version", "", color.GreenString("The golangci-lint version used to build the custom binary")) + flagSet.StringVar(&c.opts.name, "name", "", color.GreenString("The name of the custom binary")) + flagSet.StringVar(&c.opts.destination, "destination", "", color.GreenString("The directory path used to store the custom binary")) + c.cmd = customCmd return c @@ -44,6 +60,18 @@ func (c *customCommand) preRunE(_ *cobra.Command, _ []string) error { return err } + if c.opts.version != "" { + cfg.Version = c.opts.version + } + + if c.opts.name != "" { + cfg.Name = c.opts.name + } + + if c.opts.destination != "" { + cfg.Destination = c.opts.destination + } + err = cfg.Validate() if err != nil { return err diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/flagsets.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/flagsets.go index cc4b00436..2b61217c6 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/flagsets.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/flagsets.go @@ -138,5 +138,5 @@ func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) { internal.AddFlagAndBind(v, fs, fs.Bool, "whole-files", "issues.whole-files", false, color.GreenString("Show issues in any part of update files (requires new-from-rev or new-from-patch)")) internal.AddFlagAndBind(v, fs, fs.Bool, "fix", "issues.fix", false, - color.GreenString("Fix found issues (if it's supported by the linter)")) + color.GreenString("Apply the fixes detected by the linters and formatters (if it's supported by the linter)")) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/fmt.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/fmt.go index 502dcebdf..ab1aef45b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/fmt.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/fmt.go @@ -37,22 +37,20 @@ type fmtCommand struct { runner *goformat.Runner - log logutils.Log - debugf logutils.DebugFunc + log logutils.Log } func newFmtCommand(logger logutils.Log, info BuildInfo) *fmtCommand { c := &fmtCommand{ viper: viper.New(), log: logger, - debugf: logutils.Debug(logutils.DebugKeyExec), cfg: config.NewDefault(), buildInfo: info, } fmtCmd := &cobra.Command{ Use: "fmt", - Short: "Format Go source files", + Short: "Format Go source files.", RunE: c.execute, PreRunE: c.preRunE, PersistentPreRunE: c.persistentPreRunE, @@ -115,14 +113,11 @@ func (c *fmtCommand) preRunE(_ *cobra.Command, _ []string) error { } func (c *fmtCommand) execute(_ *cobra.Command, args []string) error { - paths, err := cleanArgs(args) - if err != nil { - return fmt.Errorf("failed to clean arguments: %w", err) - } + paths := cleanArgs(args) c.log.Infof("Formatting Go files...") - err = c.runner.Run(paths) + err := c.runner.Run(paths) if err != nil { return fmt.Errorf("failed to process files: %w", err) } @@ -136,25 +131,15 @@ func (c *fmtCommand) persistentPostRun(_ *cobra.Command, _ []string) { } } -func cleanArgs(args []string) ([]string, error) { +func cleanArgs(args []string) []string { if len(args) == 0 { - abs, err := filepath.Abs(".") - if err != nil { - return nil, err - } - - return []string{abs}, nil + return []string{"."} } var expanded []string for _, arg := range args { - abs, err := filepath.Abs(strings.ReplaceAll(arg, "...", "")) - if err != nil { - return nil, err - } - - expanded = append(expanded, abs) + expanded = append(expanded, filepath.Clean(strings.ReplaceAll(arg, "...", ""))) } - return expanded, nil + return expanded } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/formatters.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/formatters.go index a3fafd1d2..bd6e0e80f 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/formatters.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/formatters.go @@ -47,7 +47,7 @@ func newFormattersCommand(logger logutils.Log) *formattersCommand { formattersCmd := &cobra.Command{ Use: "formatters", - Short: "List current formatters configuration", + Short: "List current formatters configuration.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.execute, @@ -59,7 +59,8 @@ func newFormattersCommand(logger logutils.Log) *formattersCommand { fs.SortFlags = false // sort them as they are defined here setupConfigFileFlagSet(fs, &c.opts.LoaderOptions) - setupLintersFlagSet(c.viper, fs) + + setupFormattersFlagSet(c.viper, fs) fs.BoolVar(&c.opts.JSON, "json", false, color.GreenString("Display as JSON")) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/help.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/help.go index bb5696e7c..6e9393ddd 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/help.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/help.go @@ -31,7 +31,7 @@ func newHelpCommand(logger logutils.Log) *helpCommand { helpCmd := &cobra.Command{ Use: "help", - Short: "Help", + Short: "Display extra help", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return cmd.Help() @@ -40,7 +40,7 @@ func newHelpCommand(logger logutils.Log) *helpCommand { lintersCmd := &cobra.Command{ Use: "linters", - Short: "Help about linters", + Short: "Display help for linters.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.lintersExecute, @@ -56,7 +56,7 @@ func newHelpCommand(logger logutils.Log) *helpCommand { formattersCmd := &cobra.Command{ Use: "formatters", - Short: "Help about formatters", + Short: "Display help for formatters.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.formattersExecute, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go index c008f1930..63f6f2f18 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go @@ -2,6 +2,8 @@ package internal import ( "context" + "crypto/sha256" + "encoding/base64" "fmt" "io" "os" @@ -12,6 +14,8 @@ import ( "time" "unicode" + "golang.org/x/mod/sumdb/dirhash" + "github.com/golangci/golangci-lint/v2/pkg/logutils" ) @@ -88,7 +92,7 @@ func (b Builder) clone(ctx context.Context) error { //nolint:gosec // the variable is sanitized. cmd := exec.CommandContext(ctx, "git", "clone", "--branch", sanitizeVersion(b.cfg.Version), - "--single-branch", "--depth", "1", "-c advice.detachedHead=false", "-q", + "--single-branch", "--depth", "1", "-c", "advice.detachedHead=false", "-q", "https://github.com/golangci/golangci-lint.git", ) cmd.Dir = b.root @@ -173,13 +177,17 @@ func (b Builder) goModTidy(ctx context.Context) error { } func (b Builder) goBuild(ctx context.Context, binaryName string) error { + version, err := b.createVersion(b.cfg.Version) + if err != nil { + return fmt.Errorf("custom version: %w", err) + } + + b.log.Infof("version: %s", version) + //nolint:gosec // the variable is sanitized. cmd := exec.CommandContext(ctx, "go", "build", "-ldflags", - fmt.Sprintf( - "-s -w -X 'main.version=%s-custom-gcl' -X 'main.date=%s'", - sanitizeVersion(b.cfg.Version), time.Now().UTC().String(), - ), + fmt.Sprintf("-s -w -X 'main.version=%s' -X 'main.date=%s'", version, time.Now().UTC().String()), "-o", binaryName, "./cmd/golangci-lint", ) @@ -241,6 +249,30 @@ func (b Builder) getBinaryName() string { return name } +func (b Builder) createVersion(orig string) (string, error) { + hash := sha256.New() + + for _, plugin := range b.cfg.Plugins { + if plugin.Path == "" { + continue + } + + dh, err := hashDir(plugin.Path, "", dirhash.DefaultHash) + if err != nil { + return "", fmt.Errorf("hash plugin directory: %w", err) + } + + b.log.Infof("%s: %s", plugin.Path, dh) + + hash.Write([]byte(dh)) + } + + return fmt.Sprintf("%s-custom-gcl-%s", + sanitizeVersion(orig), + sanitizeVersion(base64.URLEncoding.EncodeToString(hash.Sum(nil))), + ), nil +} + func sanitizeVersion(v string) string { fn := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '.' && c != '/' diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/configuration.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/configuration.go index f9de4c47a..0982c3eca 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/configuration.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/configuration.go @@ -7,7 +7,7 @@ import ( "path/filepath" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) const base = ".custom-gcl" diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/dirhash.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/dirhash.go new file mode 100644 index 000000000..16ea6a856 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/dirhash.go @@ -0,0 +1,93 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "golang.org/x/mod/sumdb/dirhash" +) + +// Slightly modified copy of [dirhash.HashDir]. +// https://github.com/golang/mod/blob/v0.28.0/sumdb/dirhash/hash.go#L67-L79 +func hashDir(dir, prefix string, hash dirhash.Hash) (string, error) { + files, err := dirFiles(dir, prefix) + if err != nil { + return "", err + } + + osOpen := func(name string) (io.ReadCloser, error) { + return os.Open(filepath.Join(dir, strings.TrimPrefix(name, prefix))) + } + + return hash(files, osOpen) +} + +// Modified copy of [dirhash.DirFiles]. +// https://github.com/golang/mod/blob/v0.28.0/sumdb/dirhash/hash.go#L81-L109 +// And adapted to globally follows the rules from https://github.com/golang/mod/blob/v0.28.0/zip/zip.go +func dirFiles(dir, prefix string) ([]string, error) { + var files []string + + dir = filepath.Clean(dir) + + err := filepath.Walk(dir, func(file string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + if dir == file { + // Don't skip the top-level directory. + return nil + } + + switch info.Name() { + // Skip vendor and node directories. + case "vendor", "node_modules": + return filepath.SkipDir + + // Skip VCS directories. + case ".bzr", ".git", ".hg", ".svn": + return filepath.SkipDir + } + + // Skip submodules (directories containing go.mod files). + if goModInfo, err := os.Lstat(filepath.Join(dir, "go.mod")); err == nil && !goModInfo.IsDir() { + return filepath.SkipDir + } + + return nil + } + + if file == dir { + return fmt.Errorf("%s is not a directory", dir) + } + + if !info.Mode().IsRegular() { + return nil + } + + rel := file + + if dir != "." { + rel = file[len(dir)+1:] + } + + f := filepath.Join(prefix, rel) + + files = append(files, filepath.ToSlash(f)) + + return nil + }) + if err != nil { + return nil, err + } + return files, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linter_names.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linter_names.go index da003e9af..bbb178ab3 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linter_names.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linter_names.go @@ -749,11 +749,8 @@ func allEnabled(old versionone.Linters, linters []LinterInfo) []LinterInfo { var results []LinterInfo for _, linter := range linters { - for _, name := range old.Enable { - if linter.isName(name) { - results = append(results, linter) - break - } + if slices.ContainsFunc(old.Enable, linter.isName) { + results = append(results, linter) } } @@ -764,11 +761,8 @@ func allDisabled(old versionone.Linters, linters []LinterInfo) []LinterInfo { var results []LinterInfo for _, linter := range linters { - for _, name := range old.Disable { - if linter.isName(name) { - results = append(results, linter) - break - } + if slices.ContainsFunc(old.Disable, linter.isName) { + results = append(results, linter) } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go index 5accd9f59..4656842d6 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go @@ -998,8 +998,8 @@ func toWrapcheckSettings(old versionone.WrapcheckSettings) versiontwo.WrapcheckS } } -func toWSLSettings(old versionone.WSLSettings) versiontwo.WSLSettings { - return versiontwo.WSLSettings{ +func toWSLSettings(old versionone.WSLSettings) versiontwo.WSLv4Settings { + return versiontwo.WSLv4Settings{ StrictAppend: old.StrictAppend, AllowAssignAndCallCuddle: old.AllowAssignAndCallCuddle, AllowAssignAndAnythingCuddle: old.AllowAssignAndAnythingCuddle, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/parser/parser.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/parser/parser.go index ea00b41f5..293eaf18a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/parser/parser.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/parser/parser.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/pelletier/go-toml/v2" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) type File interface { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go index 44583b7d3..3c641541c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go @@ -3,7 +3,7 @@ package versionone import ( "encoding" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr" ) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go index 408a07ab6..a3d86fc1d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go @@ -24,9 +24,7 @@ type OutputFormat struct { type OutputFormats []OutputFormat func (p *OutputFormats) UnmarshalText(text []byte) error { - formats := strings.Split(string(text), ",") - - for _, item := range formats { + for item := range strings.SplitSeq(string(text), ",") { format, path, _ := strings.Cut(item, ":") *p = append(*p, OutputFormat{ diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versiontwo/linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versiontwo/linters_settings.go index 3a0d6b7b6..be35d1390 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versiontwo/linters_settings.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versiontwo/linters_settings.go @@ -5,84 +5,86 @@ package versiontwo type LintersSettings struct { FormatterSettings `yaml:"-,omitempty" toml:"-,multiline,omitempty"` - Asasalint AsasalintSettings `yaml:"asasalint,omitempty" toml:"asasalint,multiline,omitempty"` - BiDiChk BiDiChkSettings `yaml:"bidichk,omitempty" toml:"bidichk,multiline,omitempty"` - CopyLoopVar CopyLoopVarSettings `yaml:"copyloopvar,omitempty" toml:"copyloopvar,multiline,omitempty"` - Cyclop CyclopSettings `yaml:"cyclop,omitempty" toml:"cyclop,multiline,omitempty"` - Decorder DecorderSettings `yaml:"decorder,omitempty" toml:"decorder,multiline,omitempty"` - Depguard DepGuardSettings `yaml:"depguard,omitempty" toml:"depguard,multiline,omitempty"` - Dogsled DogsledSettings `yaml:"dogsled,omitempty" toml:"dogsled,multiline,omitempty"` - Dupl DuplSettings `yaml:"dupl,omitempty" toml:"dupl,multiline,omitempty"` - DupWord DupWordSettings `yaml:"dupword,omitempty" toml:"dupword,multiline,omitempty"` - Errcheck ErrcheckSettings `yaml:"errcheck,omitempty" toml:"errcheck,multiline,omitempty"` - ErrChkJSON ErrChkJSONSettings `yaml:"errchkjson,omitempty" toml:"errchkjson,multiline,omitempty"` - ErrorLint ErrorLintSettings `yaml:"errorlint,omitempty" toml:"errorlint,multiline,omitempty"` - Exhaustive ExhaustiveSettings `yaml:"exhaustive,omitempty" toml:"exhaustive,multiline,omitempty"` - Exhaustruct ExhaustructSettings `yaml:"exhaustruct,omitempty" toml:"exhaustruct,multiline,omitempty"` - Fatcontext FatcontextSettings `yaml:"fatcontext,omitempty" toml:"fatcontext,multiline,omitempty"` - Forbidigo ForbidigoSettings `yaml:"forbidigo,omitempty" toml:"forbidigo,multiline,omitempty"` - FuncOrder FuncOrderSettings `yaml:"funcorder,omitempty" toml:"funcorder,multiline,omitempty"` - Funlen FunlenSettings `yaml:"funlen,omitempty" toml:"funlen,multiline,omitempty"` - GinkgoLinter GinkgoLinterSettings `yaml:"ginkgolinter,omitempty" toml:"ginkgolinter,multiline,omitempty"` - Gocognit GocognitSettings `yaml:"gocognit,omitempty" toml:"gocognit,multiline,omitempty"` - GoChecksumType GoChecksumTypeSettings `yaml:"gochecksumtype,omitempty" toml:"gochecksumtype,multiline,omitempty"` - Goconst GoConstSettings `yaml:"goconst,omitempty" toml:"goconst,multiline,omitempty"` - Gocritic GoCriticSettings `yaml:"gocritic,omitempty" toml:"gocritic,multiline,omitempty"` - Gocyclo GoCycloSettings `yaml:"gocyclo,omitempty" toml:"gocyclo,multiline,omitempty"` - Godot GodotSettings `yaml:"godot,omitempty" toml:"godot,multiline,omitempty"` - Godox GodoxSettings `yaml:"godox,omitempty" toml:"godox,multiline,omitempty"` - Goheader GoHeaderSettings `yaml:"goheader,omitempty" toml:"goheader,multiline,omitempty"` - GoModDirectives GoModDirectivesSettings `yaml:"gomoddirectives,omitempty" toml:"gomoddirectives,multiline,omitempty"` - Gomodguard GoModGuardSettings `yaml:"gomodguard,omitempty" toml:"gomodguard,multiline,omitempty"` - Gosec GoSecSettings `yaml:"gosec,omitempty" toml:"gosec,multiline,omitempty"` - Gosmopolitan GosmopolitanSettings `yaml:"gosmopolitan,omitempty" toml:"gosmopolitan,multiline,omitempty"` - Govet GovetSettings `yaml:"govet,omitempty" toml:"govet,multiline,omitempty"` - Grouper GrouperSettings `yaml:"grouper,omitempty" toml:"grouper,multiline,omitempty"` - Iface IfaceSettings `yaml:"iface,omitempty" toml:"iface,multiline,omitempty"` - ImportAs ImportAsSettings `yaml:"importas,omitempty" toml:"importas,multiline,omitempty"` - Inamedparam INamedParamSettings `yaml:"inamedparam,omitempty" toml:"inamedparam,multiline,omitempty"` - InterfaceBloat InterfaceBloatSettings `yaml:"interfacebloat,omitempty" toml:"interfacebloat,multiline,omitempty"` - Ireturn IreturnSettings `yaml:"ireturn,omitempty" toml:"ireturn,multiline,omitempty"` - Lll LllSettings `yaml:"lll,omitempty" toml:"lll,multiline,omitempty"` - LoggerCheck LoggerCheckSettings `yaml:"loggercheck,omitempty" toml:"loggercheck,multiline,omitempty"` - MaintIdx MaintIdxSettings `yaml:"maintidx,omitempty" toml:"maintidx,multiline,omitempty"` - Makezero MakezeroSettings `yaml:"makezero,omitempty" toml:"makezero,multiline,omitempty"` - Misspell MisspellSettings `yaml:"misspell,omitempty" toml:"misspell,multiline,omitempty"` - Mnd MndSettings `yaml:"mnd,omitempty" toml:"mnd,multiline,omitempty"` - MustTag MustTagSettings `yaml:"musttag,omitempty" toml:"musttag,multiline,omitempty"` - Nakedret NakedretSettings `yaml:"nakedret,omitempty" toml:"nakedret,multiline,omitempty"` - Nestif NestifSettings `yaml:"nestif,omitempty" toml:"nestif,multiline,omitempty"` - NilNil NilNilSettings `yaml:"nilnil,omitempty" toml:"nilnil,multiline,omitempty"` - Nlreturn NlreturnSettings `yaml:"nlreturn,omitempty" toml:"nlreturn,multiline,omitempty"` - NoLintLint NoLintLintSettings `yaml:"nolintlint,omitempty" toml:"nolintlint,multiline,omitempty"` - NoNamedReturns NoNamedReturnsSettings `yaml:"nonamedreturns,omitempty" toml:"nonamedreturns,multiline,omitempty"` - ParallelTest ParallelTestSettings `yaml:"paralleltest,omitempty" toml:"paralleltest,multiline,omitempty"` - PerfSprint PerfSprintSettings `yaml:"perfsprint,omitempty" toml:"perfsprint,multiline,omitempty"` - Prealloc PreallocSettings `yaml:"prealloc,omitempty" toml:"prealloc,multiline,omitempty"` - Predeclared PredeclaredSettings `yaml:"predeclared,omitempty" toml:"predeclared,multiline,omitempty"` - Promlinter PromlinterSettings `yaml:"promlinter,omitempty" toml:"promlinter,multiline,omitempty"` - ProtoGetter ProtoGetterSettings `yaml:"protogetter,omitempty" toml:"protogetter,multiline,omitempty"` - Reassign ReassignSettings `yaml:"reassign,omitempty" toml:"reassign,multiline,omitempty"` - Recvcheck RecvcheckSettings `yaml:"recvcheck,omitempty" toml:"recvcheck,multiline,omitempty"` - Revive ReviveSettings `yaml:"revive,omitempty" toml:"revive,multiline,omitempty"` - RowsErrCheck RowsErrCheckSettings `yaml:"rowserrcheck,omitempty" toml:"rowserrcheck,multiline,omitempty"` - SlogLint SlogLintSettings `yaml:"sloglint,omitempty" toml:"sloglint,multiline,omitempty"` - Spancheck SpancheckSettings `yaml:"spancheck,omitempty" toml:"spancheck,multiline,omitempty"` - Staticcheck StaticCheckSettings `yaml:"staticcheck,omitempty" toml:"staticcheck,multiline,omitempty"` - TagAlign TagAlignSettings `yaml:"tagalign,omitempty" toml:"tagalign,multiline,omitempty"` - Tagliatelle TagliatelleSettings `yaml:"tagliatelle,omitempty" toml:"tagliatelle,multiline,omitempty"` - Testifylint TestifylintSettings `yaml:"testifylint,omitempty" toml:"testifylint,multiline,omitempty"` - Testpackage TestpackageSettings `yaml:"testpackage,omitempty" toml:"testpackage,multiline,omitempty"` - Thelper ThelperSettings `yaml:"thelper,omitempty" toml:"thelper,multiline,omitempty"` - Unconvert UnconvertSettings `yaml:"unconvert,omitempty" toml:"unconvert,multiline,omitempty"` - Unparam UnparamSettings `yaml:"unparam,omitempty" toml:"unparam,multiline,omitempty"` - Unused UnusedSettings `yaml:"unused,omitempty" toml:"unused,multiline,omitempty"` - UseStdlibVars UseStdlibVarsSettings `yaml:"usestdlibvars,omitempty" toml:"usestdlibvars,multiline,omitempty"` - UseTesting UseTestingSettings `yaml:"usetesting,omitempty" toml:"usetesting,multiline,omitempty"` - Varnamelen VarnamelenSettings `yaml:"varnamelen,omitempty" toml:"varnamelen,multiline,omitempty"` - Whitespace WhitespaceSettings `yaml:"whitespace,omitempty" toml:"whitespace,multiline,omitempty"` - Wrapcheck WrapcheckSettings `yaml:"wrapcheck,omitempty" toml:"wrapcheck,multiline,omitempty"` - WSL WSLSettings `yaml:"wsl,omitempty" toml:"wsl,multiline,omitempty"` + Asasalint AsasalintSettings `yaml:"asasalint,omitempty" toml:"asasalint,multiline,omitempty"` + BiDiChk BiDiChkSettings `yaml:"bidichk,omitempty" toml:"bidichk,multiline,omitempty"` + CopyLoopVar CopyLoopVarSettings `yaml:"copyloopvar,omitempty" toml:"copyloopvar,multiline,omitempty"` + Cyclop CyclopSettings `yaml:"cyclop,omitempty" toml:"cyclop,multiline,omitempty"` + Decorder DecorderSettings `yaml:"decorder,omitempty" toml:"decorder,multiline,omitempty"` + Depguard DepGuardSettings `yaml:"depguard,omitempty" toml:"depguard,multiline,omitempty"` + Dogsled DogsledSettings `yaml:"dogsled,omitempty" toml:"dogsled,multiline,omitempty"` + Dupl DuplSettings `yaml:"dupl,omitempty" toml:"dupl,multiline,omitempty"` + DupWord DupWordSettings `yaml:"dupword,omitempty" toml:"dupword,multiline,omitempty"` + EmbeddedStructFieldCheck EmbeddedStructFieldCheckSettings `yaml:"embeddedstructfieldcheck,omitempty" toml:"embeddedstructfieldcheck,multiline,omitempty"` + Errcheck ErrcheckSettings `yaml:"errcheck,omitempty" toml:"errcheck,multiline,omitempty"` + ErrChkJSON ErrChkJSONSettings `yaml:"errchkjson,omitempty" toml:"errchkjson,multiline,omitempty"` + ErrorLint ErrorLintSettings `yaml:"errorlint,omitempty" toml:"errorlint,multiline,omitempty"` + Exhaustive ExhaustiveSettings `yaml:"exhaustive,omitempty" toml:"exhaustive,multiline,omitempty"` + Exhaustruct ExhaustructSettings `yaml:"exhaustruct,omitempty" toml:"exhaustruct,multiline,omitempty"` + Fatcontext FatcontextSettings `yaml:"fatcontext,omitempty" toml:"fatcontext,multiline,omitempty"` + Forbidigo ForbidigoSettings `yaml:"forbidigo,omitempty" toml:"forbidigo,multiline,omitempty"` + FuncOrder FuncOrderSettings `yaml:"funcorder,omitempty" toml:"funcorder,multiline,omitempty"` + Funlen FunlenSettings `yaml:"funlen,omitempty" toml:"funlen,multiline,omitempty"` + GinkgoLinter GinkgoLinterSettings `yaml:"ginkgolinter,omitempty" toml:"ginkgolinter,multiline,omitempty"` + Gocognit GocognitSettings `yaml:"gocognit,omitempty" toml:"gocognit,multiline,omitempty"` + GoChecksumType GoChecksumTypeSettings `yaml:"gochecksumtype,omitempty" toml:"gochecksumtype,multiline,omitempty"` + Goconst GoConstSettings `yaml:"goconst,omitempty" toml:"goconst,multiline,omitempty"` + Gocritic GoCriticSettings `yaml:"gocritic,omitempty" toml:"gocritic,multiline,omitempty"` + Gocyclo GoCycloSettings `yaml:"gocyclo,omitempty" toml:"gocyclo,multiline,omitempty"` + Godot GodotSettings `yaml:"godot,omitempty" toml:"godot,multiline,omitempty"` + Godox GodoxSettings `yaml:"godox,omitempty" toml:"godox,multiline,omitempty"` + Goheader GoHeaderSettings `yaml:"goheader,omitempty" toml:"goheader,multiline,omitempty"` + GoModDirectives GoModDirectivesSettings `yaml:"gomoddirectives,omitempty" toml:"gomoddirectives,multiline,omitempty"` + Gomodguard GoModGuardSettings `yaml:"gomodguard,omitempty" toml:"gomodguard,multiline,omitempty"` + Gosec GoSecSettings `yaml:"gosec,omitempty" toml:"gosec,multiline,omitempty"` + Gosmopolitan GosmopolitanSettings `yaml:"gosmopolitan,omitempty" toml:"gosmopolitan,multiline,omitempty"` + Govet GovetSettings `yaml:"govet,omitempty" toml:"govet,multiline,omitempty"` + Grouper GrouperSettings `yaml:"grouper,omitempty" toml:"grouper,multiline,omitempty"` + Iface IfaceSettings `yaml:"iface,omitempty" toml:"iface,multiline,omitempty"` + ImportAs ImportAsSettings `yaml:"importas,omitempty" toml:"importas,multiline,omitempty"` + Inamedparam INamedParamSettings `yaml:"inamedparam,omitempty" toml:"inamedparam,multiline,omitempty"` + InterfaceBloat InterfaceBloatSettings `yaml:"interfacebloat,omitempty" toml:"interfacebloat,multiline,omitempty"` + Ireturn IreturnSettings `yaml:"ireturn,omitempty" toml:"ireturn,multiline,omitempty"` + Lll LllSettings `yaml:"lll,omitempty" toml:"lll,multiline,omitempty"` + LoggerCheck LoggerCheckSettings `yaml:"loggercheck,omitempty" toml:"loggercheck,multiline,omitempty"` + MaintIdx MaintIdxSettings `yaml:"maintidx,omitempty" toml:"maintidx,multiline,omitempty"` + Makezero MakezeroSettings `yaml:"makezero,omitempty" toml:"makezero,multiline,omitempty"` + Misspell MisspellSettings `yaml:"misspell,omitempty" toml:"misspell,multiline,omitempty"` + Mnd MndSettings `yaml:"mnd,omitempty" toml:"mnd,multiline,omitempty"` + MustTag MustTagSettings `yaml:"musttag,omitempty" toml:"musttag,multiline,omitempty"` + Nakedret NakedretSettings `yaml:"nakedret,omitempty" toml:"nakedret,multiline,omitempty"` + Nestif NestifSettings `yaml:"nestif,omitempty" toml:"nestif,multiline,omitempty"` + NilNil NilNilSettings `yaml:"nilnil,omitempty" toml:"nilnil,multiline,omitempty"` + Nlreturn NlreturnSettings `yaml:"nlreturn,omitempty" toml:"nlreturn,multiline,omitempty"` + NoLintLint NoLintLintSettings `yaml:"nolintlint,omitempty" toml:"nolintlint,multiline,omitempty"` + NoNamedReturns NoNamedReturnsSettings `yaml:"nonamedreturns,omitempty" toml:"nonamedreturns,multiline,omitempty"` + ParallelTest ParallelTestSettings `yaml:"paralleltest,omitempty" toml:"paralleltest,multiline,omitempty"` + PerfSprint PerfSprintSettings `yaml:"perfsprint,omitempty" toml:"perfsprint,multiline,omitempty"` + Prealloc PreallocSettings `yaml:"prealloc,omitempty" toml:"prealloc,multiline,omitempty"` + Predeclared PredeclaredSettings `yaml:"predeclared,omitempty" toml:"predeclared,multiline,omitempty"` + Promlinter PromlinterSettings `yaml:"promlinter,omitempty" toml:"promlinter,multiline,omitempty"` + ProtoGetter ProtoGetterSettings `yaml:"protogetter,omitempty" toml:"protogetter,multiline,omitempty"` + Reassign ReassignSettings `yaml:"reassign,omitempty" toml:"reassign,multiline,omitempty"` + Recvcheck RecvcheckSettings `yaml:"recvcheck,omitempty" toml:"recvcheck,multiline,omitempty"` + Revive ReviveSettings `yaml:"revive,omitempty" toml:"revive,multiline,omitempty"` + RowsErrCheck RowsErrCheckSettings `yaml:"rowserrcheck,omitempty" toml:"rowserrcheck,multiline,omitempty"` + SlogLint SlogLintSettings `yaml:"sloglint,omitempty" toml:"sloglint,multiline,omitempty"` + Spancheck SpancheckSettings `yaml:"spancheck,omitempty" toml:"spancheck,multiline,omitempty"` + Staticcheck StaticCheckSettings `yaml:"staticcheck,omitempty" toml:"staticcheck,multiline,omitempty"` + TagAlign TagAlignSettings `yaml:"tagalign,omitempty" toml:"tagalign,multiline,omitempty"` + Tagliatelle TagliatelleSettings `yaml:"tagliatelle,omitempty" toml:"tagliatelle,multiline,omitempty"` + Testifylint TestifylintSettings `yaml:"testifylint,omitempty" toml:"testifylint,multiline,omitempty"` + Testpackage TestpackageSettings `yaml:"testpackage,omitempty" toml:"testpackage,multiline,omitempty"` + Thelper ThelperSettings `yaml:"thelper,omitempty" toml:"thelper,multiline,omitempty"` + Unconvert UnconvertSettings `yaml:"unconvert,omitempty" toml:"unconvert,multiline,omitempty"` + Unparam UnparamSettings `yaml:"unparam,omitempty" toml:"unparam,multiline,omitempty"` + Unused UnusedSettings `yaml:"unused,omitempty" toml:"unused,multiline,omitempty"` + UseStdlibVars UseStdlibVarsSettings `yaml:"usestdlibvars,omitempty" toml:"usestdlibvars,multiline,omitempty"` + UseTesting UseTestingSettings `yaml:"usetesting,omitempty" toml:"usetesting,multiline,omitempty"` + Varnamelen VarnamelenSettings `yaml:"varnamelen,omitempty" toml:"varnamelen,multiline,omitempty"` + Whitespace WhitespaceSettings `yaml:"whitespace,omitempty" toml:"whitespace,multiline,omitempty"` + Wrapcheck WrapcheckSettings `yaml:"wrapcheck,omitempty" toml:"wrapcheck,multiline,omitempty"` + WSL WSLv4Settings `yaml:"wsl,omitempty" toml:"wsl,multiline,omitempty"` + WSLv5 WSLv5Settings `yaml:"wsl_v5,omitempty" toml:"wsl_v5,multiline,omitempty"` Custom map[string]CustomLinterSettings `yaml:"custom,omitempty" toml:"custom,multiline,omitempty"` } @@ -153,11 +155,16 @@ type DupWordSettings struct { Ignore []string `yaml:"ignore,omitempty" toml:"ignore,multiline,omitempty"` } +type EmbeddedStructFieldCheckSettings struct { + ForbidMutex *bool `yaml:"forbid-mutex,omitempty" toml:"forbid-mutex,multiline,omitempty"` +} + type ErrcheckSettings struct { DisableDefaultExclusions *bool `yaml:"disable-default-exclusions,omitempty" toml:"disable-default-exclusions,multiline,omitempty"` CheckTypeAssertions *bool `yaml:"check-type-assertions,omitempty" toml:"check-type-assertions,multiline,omitempty"` CheckAssignToBlank *bool `yaml:"check-blank,omitempty" toml:"check-blank,multiline,omitempty"` ExcludeFunctions []string `yaml:"exclude-functions,omitempty" toml:"exclude-functions,multiline,omitempty"` + Verbose *bool `yaml:"verbose,omitempty" toml:"verbose,multiline,omitempty"` } type ErrChkJSONSettings struct { @@ -214,6 +221,7 @@ type ForbidigoPattern struct { type FuncOrderSettings struct { Constructor *bool `yaml:"constructor,omitempty,omitempty" toml:"constructor,omitempty,multiline,omitempty"` StructMethod *bool `yaml:"struct-method,omitempty,omitempty" toml:"struct-method,omitempty,multiline,omitempty"` + Alphabetical *bool `yaml:"alphabetical,omitempty,omitempty" toml:"alphabetical,omitempty,multiline,omitempty"` } type FunlenSettings struct { @@ -695,6 +703,7 @@ type UseStdlibVarsSettings struct { SQLIsolationLevel *bool `yaml:"sql-isolation-level,omitempty" toml:"sql-isolation-level,multiline,omitempty"` TLSSignatureScheme *bool `yaml:"tls-signature-scheme,omitempty" toml:"tls-signature-scheme,multiline,omitempty"` ConstantKind *bool `yaml:"constant-kind,omitempty" toml:"constant-kind,multiline,omitempty"` + TimeDateMonth *bool `yaml:"time-date-month,omitempty" toml:"time-date-month,multiline,omitempty"` } type UseTestingSettings struct { @@ -752,7 +761,7 @@ type WrapcheckSettings struct { ReportInternalErrors *bool `yaml:"report-internal-errors,omitempty" toml:"report-internal-errors,multiline,omitempty"` } -type WSLSettings struct { +type WSLv4Settings struct { StrictAppend *bool `yaml:"strict-append,omitempty" toml:"strict-append,multiline,omitempty"` AllowAssignAndCallCuddle *bool `yaml:"allow-assign-and-call,omitempty" toml:"allow-assign-and-call,multiline,omitempty"` AllowAssignAndAnythingCuddle *bool `yaml:"allow-assign-and-anything,omitempty" toml:"allow-assign-and-anything,multiline,omitempty"` @@ -769,6 +778,16 @@ type WSLSettings struct { ForceExclusiveShortDeclarations *bool `yaml:"force-short-decl-cuddling,omitempty" toml:"force-short-decl-cuddling,multiline,omitempty"` } +type WSLv5Settings struct { + AllowFirstInBlock *bool `yaml:"allow-first-in-block,omitempty" toml:"allow-first-in-block,multiline,omitempty"` + AllowWholeBlock *bool `yaml:"allow-whole-block,omitempty" toml:"allow-whole-block,multiline,omitempty"` + BranchMaxLines *int `yaml:"branch-max-lines,omitempty" toml:"branch-max-lines,multiline,omitempty"` + CaseMaxLines *int `yaml:"case-max-lines,omitempty" toml:"case-max-lines,multiline,omitempty"` + Default *string `yaml:"default,omitempty" toml:"default,multiline,omitempty"` + Enable []string `yaml:"enable,omitempty" toml:"enable,multiline,omitempty"` + Disable []string `yaml:"disable,omitempty" toml:"disable,multiline,omitempty"` +} + type CustomLinterSettings struct { Type *string `yaml:"type,omitempty" toml:"type,multiline,omitempty"` diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/linters.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/linters.go index 40036bb85..4be11ab56 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/linters.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/linters.go @@ -47,7 +47,7 @@ func newLintersCommand(logger logutils.Log) *lintersCommand { lintersCmd := &cobra.Command{ Use: "linters", - Short: "List current linters configuration", + Short: "List current linters configuration.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.execute, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go index 7c73209ed..7012e9226 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go @@ -51,7 +51,7 @@ func newMigrateCommand(log logutils.Log, info BuildInfo) *migrateCommand { migrateCmd := &cobra.Command{ Use: "migrate", - Short: "Migrate configuration file from v1 to v2", + Short: "Migrate configuration file from v1 to v2.", SilenceUsage: true, SilenceErrors: true, Args: cobra.NoArgs, @@ -81,10 +81,6 @@ func newMigrateCommand(log logutils.Log, info BuildInfo) *migrateCommand { } func (c *migrateCommand) execute(_ *cobra.Command, _ []string) error { - if c.cfg.Version != "" { - return fmt.Errorf("configuration version is already set: %s", c.cfg.Version) - } - srcPath := c.viper.ConfigFileUsed() if srcPath == "" { c.log.Warnf("No config file detected") @@ -97,7 +93,7 @@ func (c *migrateCommand) execute(_ *cobra.Command, _ []string) error { } c.log.Warnf("The configuration comments are not migrated.") - c.log.Warnf("Details about the migration: https://golangci-lint.run/product/migration-guide/") + c.log.Warnf("Details about the migration: https://golangci-lint.run/docs/product/migration-guide/") c.log.Infof("Migrating v1 configuration file: %s", srcPath) @@ -141,6 +137,10 @@ func (c *migrateCommand) preRunE(cmd *cobra.Command, _ []string) error { return fmt.Errorf("unsupported format: %s", c.opts.format) } + if c.cfg.Version != "" { + return fmt.Errorf("configuration version is already set: %s", c.cfg.Version) + } + if c.opts.skipValidation { return nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/root.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/root.go index e3dcc527b..9fa36f25f 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/root.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/root.go @@ -115,6 +115,9 @@ func setupLogger(logger logutils.Log) error { logger.Fatalf("invalid value %q for --color; must be 'always', 'auto', or 'never'", opts.Color) } + // For log level colors (mainly for verbose output) + logutils.DisableColors(color.NoColor) + return nil } @@ -124,7 +127,7 @@ func forceRootParsePersistentFlags() (*rootOptions, error) { fs := pflag.NewFlagSet("config flag set", pflag.ContinueOnError) // Ignore unknown flags because we will parse the command flags later. - fs.ParseErrorsWhitelist = pflag.ParseErrorsWhitelist{UnknownFlags: true} + fs.ParseErrorsAllowlist = pflag.ParseErrorsAllowlist{UnknownFlags: true} opts := &rootOptions{} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go index 53902eafa..93efa6d9c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go @@ -26,8 +26,8 @@ import ( "github.com/spf13/pflag" "github.com/spf13/viper" "go.uber.org/automaxprocs/maxprocs" + "go.yaml.in/yaml/v3" "golang.org/x/mod/sumdb/dirhash" - "gopkg.in/yaml.v3" "github.com/golangci/golangci-lint/v2/internal/cache" "github.com/golangci/golangci-lint/v2/pkg/config" @@ -111,7 +111,7 @@ func newRunCommand(logger logutils.Log, info BuildInfo) *runCommand { runCmd := &cobra.Command{ Use: "run", - Short: "Run the linters", + Short: "Lint the code.", Run: c.execute, PreRunE: c.preRunE, PostRun: c.postRun, @@ -376,7 +376,7 @@ func (c *runCommand) runAndPrint(ctx context.Context) error { } // runAnalysis executes the linters that have been enabled in the configuration. -func (c *runCommand) runAnalysis(ctx context.Context) ([]result.Issue, error) { +func (c *runCommand) runAnalysis(ctx context.Context) ([]*result.Issue, error) { lintersToRun, err := c.dbManager.GetOptimizedLinters() if err != nil { return nil, err @@ -408,7 +408,7 @@ func (c *runCommand) setOutputToDevNull() (savedStdout, savedStderr *os.File) { return } -func (c *runCommand) setExitCodeIfIssuesFound(issues []result.Issue) { +func (c *runCommand) setExitCodeIfIssuesFound(issues []*result.Issue) { if len(issues) != 0 { c.exitCode = c.cfg.Run.ExitCodeIfIssuesFound } @@ -430,10 +430,21 @@ func (c *runCommand) printDeprecatedLinterMessages(enabledLinters map[string]*li } c.log.Warnf("The linter '%s' is deprecated (since %s) due to: %s %s", name, lc.Deprecation.Since, lc.Deprecation.Message, extra) + + if lc.Deprecation.ConfigSuggestion != nil { + suggestion, err := lc.Deprecation.ConfigSuggestion() + if err != nil { + c.log.Errorf("New configuration suggestion error: %v", err) + } + + if suggestion != "" { + c.log.Warnf("Suggested new configuration:\n%s", suggestion) + } + } } } -func (c *runCommand) printStats(issues []result.Issue) { +func (c *runCommand) printStats(issues []*result.Issue) { if !c.cfg.Output.ShowStats { return } @@ -584,6 +595,7 @@ func setupConfigFileFlagSet(fs *pflag.FlagSet, cfg *config.LoaderOptions) { func setupRunPersistentFlags(fs *pflag.FlagSet, opts *runOptions) { fs.BoolVar(&opts.PrintResourcesUsage, "print-resources-usage", false, color.GreenString("Print avg and max memory usage of golangci-lint and total time")) + _ = fs.MarkDeprecated("print-resources-usage", "use --verbose instead") fs.StringVar(&opts.CPUProfilePath, "cpu-profile-path", "", color.GreenString("Path to CPU profile output file")) fs.StringVar(&opts.MemProfilePath, "mem-profile-path", "", color.GreenString("Path to memory profile output file")) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/version.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/version.go index 2bcb12f47..c8057a86c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/version.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/version.go @@ -42,7 +42,7 @@ func newVersionCommand(info BuildInfo) *versionCommand { versionCmd := &cobra.Command{ Use: "version", - Short: "Version", + Short: "Display the golangci-lint version.", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, RunE: c.execute, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters.go index 590d9448a..2669f2e64 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters.go @@ -49,5 +49,5 @@ func (l *Linters) validateNoFormatters() error { } func getAllFormatterNames() []string { - return []string{"gci", "gofmt", "gofumpt", "goimports", "golines"} + return []string{"gci", "gofmt", "gofumpt", "goimports", "golines", "swaggo"} } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go index 16a8bb950..fefa94ca3 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go @@ -24,6 +24,9 @@ var defaultLintersSettings = LintersSettings{ Dupl: DuplSettings{ Threshold: 150, }, + EmbeddedStructFieldCheck: EmbeddedStructFieldCheckSettings{ + EmptyLine: true, + }, ErrorLint: ErrorLintSettings{ Errorf: true, ErrorfMulti: true, @@ -128,6 +131,7 @@ var defaultLintersSettings = LintersSettings{ StrConcat: true, BoolFormat: true, HexFormat: true, + ConcatLoop: true, }, Prealloc: PreallocSettings{ Simple: true, @@ -159,6 +163,9 @@ var defaultLintersSettings = LintersSettings{ SkipRegexp: `(export|internal)_test\.go`, AllowPackages: []string{"main"}, }, + Unqueryvet: UnqueryvetSettings{ + CheckSQLBuilders: true, + }, Unused: UnusedSettings{ FieldWritesAreUses: true, PostStatementsAreReads: false, @@ -172,8 +179,8 @@ var defaultLintersSettings = LintersSettings{ HTTPStatusCode: true, }, UseTesting: UseTestingSettings{ - ContextBackground: true, - ContextTodo: true, + ContextBackground: false, + ContextTodo: false, OSChdir: true, OSMkdirTemp: true, OSSetenv: true, @@ -184,7 +191,7 @@ var defaultLintersSettings = LintersSettings{ MaxDistance: 5, MinNameLength: 3, }, - WSL: WSLSettings{ + WSL: WSLv4Settings{ StrictAppend: true, AllowAssignAndCallCuddle: true, AllowAssignAndAnythingCuddle: false, @@ -200,89 +207,105 @@ var defaultLintersSettings = LintersSettings{ ErrorVariableNames: []string{"err"}, ForceExclusiveShortDeclarations: false, }, + WSLv5: WSLv5Settings{ + AllowFirstInBlock: true, + AllowWholeBlock: false, + BranchMaxLines: 2, + CaseMaxLines: 0, + Default: "default", + Enable: nil, + Disable: nil, + }, } type LintersSettings struct { FormatterSettings `mapstructure:"-"` - Asasalint AsasalintSettings `mapstructure:"asasalint"` - BiDiChk BiDiChkSettings `mapstructure:"bidichk"` - CopyLoopVar CopyLoopVarSettings `mapstructure:"copyloopvar"` - Cyclop CyclopSettings `mapstructure:"cyclop"` - Decorder DecorderSettings `mapstructure:"decorder"` - Depguard DepGuardSettings `mapstructure:"depguard"` - Dogsled DogsledSettings `mapstructure:"dogsled"` - Dupl DuplSettings `mapstructure:"dupl"` - DupWord DupWordSettings `mapstructure:"dupword"` - Errcheck ErrcheckSettings `mapstructure:"errcheck"` - ErrChkJSON ErrChkJSONSettings `mapstructure:"errchkjson"` - ErrorLint ErrorLintSettings `mapstructure:"errorlint"` - Exhaustive ExhaustiveSettings `mapstructure:"exhaustive"` - Exhaustruct ExhaustructSettings `mapstructure:"exhaustruct"` - Fatcontext FatcontextSettings `mapstructure:"fatcontext"` - Forbidigo ForbidigoSettings `mapstructure:"forbidigo"` - FuncOrder FuncOrderSettings `mapstructure:"funcorder"` - Funlen FunlenSettings `mapstructure:"funlen"` - GinkgoLinter GinkgoLinterSettings `mapstructure:"ginkgolinter"` - Gocognit GocognitSettings `mapstructure:"gocognit"` - GoChecksumType GoChecksumTypeSettings `mapstructure:"gochecksumtype"` - Goconst GoConstSettings `mapstructure:"goconst"` - Gocritic GoCriticSettings `mapstructure:"gocritic"` - Gocyclo GoCycloSettings `mapstructure:"gocyclo"` - Godot GodotSettings `mapstructure:"godot"` - Godox GodoxSettings `mapstructure:"godox"` - Goheader GoHeaderSettings `mapstructure:"goheader"` - GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"` - Gomodguard GoModGuardSettings `mapstructure:"gomodguard"` - Gosec GoSecSettings `mapstructure:"gosec"` - Gosmopolitan GosmopolitanSettings `mapstructure:"gosmopolitan"` - Govet GovetSettings `mapstructure:"govet"` - Grouper GrouperSettings `mapstructure:"grouper"` - Iface IfaceSettings `mapstructure:"iface"` - ImportAs ImportAsSettings `mapstructure:"importas"` - Inamedparam INamedParamSettings `mapstructure:"inamedparam"` - InterfaceBloat InterfaceBloatSettings `mapstructure:"interfacebloat"` - Ireturn IreturnSettings `mapstructure:"ireturn"` - Lll LllSettings `mapstructure:"lll"` - LoggerCheck LoggerCheckSettings `mapstructure:"loggercheck"` - MaintIdx MaintIdxSettings `mapstructure:"maintidx"` - Makezero MakezeroSettings `mapstructure:"makezero"` - Misspell MisspellSettings `mapstructure:"misspell"` - Mnd MndSettings `mapstructure:"mnd"` - MustTag MustTagSettings `mapstructure:"musttag"` - Nakedret NakedretSettings `mapstructure:"nakedret"` - Nestif NestifSettings `mapstructure:"nestif"` - NilNil NilNilSettings `mapstructure:"nilnil"` - Nlreturn NlreturnSettings `mapstructure:"nlreturn"` - NoLintLint NoLintLintSettings `mapstructure:"nolintlint"` - NoNamedReturns NoNamedReturnsSettings `mapstructure:"nonamedreturns"` - ParallelTest ParallelTestSettings `mapstructure:"paralleltest"` - PerfSprint PerfSprintSettings `mapstructure:"perfsprint"` - Prealloc PreallocSettings `mapstructure:"prealloc"` - Predeclared PredeclaredSettings `mapstructure:"predeclared"` - Promlinter PromlinterSettings `mapstructure:"promlinter"` - ProtoGetter ProtoGetterSettings `mapstructure:"protogetter"` - Reassign ReassignSettings `mapstructure:"reassign"` - Recvcheck RecvcheckSettings `mapstructure:"recvcheck"` - Revive ReviveSettings `mapstructure:"revive"` - RowsErrCheck RowsErrCheckSettings `mapstructure:"rowserrcheck"` - SlogLint SlogLintSettings `mapstructure:"sloglint"` - Spancheck SpancheckSettings `mapstructure:"spancheck"` - Staticcheck StaticCheckSettings `mapstructure:"staticcheck"` - TagAlign TagAlignSettings `mapstructure:"tagalign"` - Tagliatelle TagliatelleSettings `mapstructure:"tagliatelle"` - Testifylint TestifylintSettings `mapstructure:"testifylint"` - Testpackage TestpackageSettings `mapstructure:"testpackage"` - Thelper ThelperSettings `mapstructure:"thelper"` - Unconvert UnconvertSettings `mapstructure:"unconvert"` - Unparam UnparamSettings `mapstructure:"unparam"` - Unused UnusedSettings `mapstructure:"unused"` - UseStdlibVars UseStdlibVarsSettings `mapstructure:"usestdlibvars"` - UseTesting UseTestingSettings `mapstructure:"usetesting"` - Varnamelen VarnamelenSettings `mapstructure:"varnamelen"` - Whitespace WhitespaceSettings `mapstructure:"whitespace"` - Wrapcheck WrapcheckSettings `mapstructure:"wrapcheck"` - WSL WSLSettings `mapstructure:"wsl"` + Asasalint AsasalintSettings `mapstructure:"asasalint"` + BiDiChk BiDiChkSettings `mapstructure:"bidichk"` + CopyLoopVar CopyLoopVarSettings `mapstructure:"copyloopvar"` + Cyclop CyclopSettings `mapstructure:"cyclop"` + Decorder DecorderSettings `mapstructure:"decorder"` + Depguard DepGuardSettings `mapstructure:"depguard"` + Dogsled DogsledSettings `mapstructure:"dogsled"` + Dupl DuplSettings `mapstructure:"dupl"` + DupWord DupWordSettings `mapstructure:"dupword"` + EmbeddedStructFieldCheck EmbeddedStructFieldCheckSettings `mapstructure:"embeddedstructfieldcheck"` + Errcheck ErrcheckSettings `mapstructure:"errcheck"` + ErrChkJSON ErrChkJSONSettings `mapstructure:"errchkjson"` + ErrorLint ErrorLintSettings `mapstructure:"errorlint"` + Exhaustive ExhaustiveSettings `mapstructure:"exhaustive"` + Exhaustruct ExhaustructSettings `mapstructure:"exhaustruct"` + Fatcontext FatcontextSettings `mapstructure:"fatcontext"` + Forbidigo ForbidigoSettings `mapstructure:"forbidigo"` + FuncOrder FuncOrderSettings `mapstructure:"funcorder"` + Funlen FunlenSettings `mapstructure:"funlen"` + GinkgoLinter GinkgoLinterSettings `mapstructure:"ginkgolinter"` + Gocognit GocognitSettings `mapstructure:"gocognit"` + GoChecksumType GoChecksumTypeSettings `mapstructure:"gochecksumtype"` + Goconst GoConstSettings `mapstructure:"goconst"` + Gocritic GoCriticSettings `mapstructure:"gocritic"` + Gocyclo GoCycloSettings `mapstructure:"gocyclo"` + Godoclint GodoclintSettings `mapstructure:"godoclint"` + Godot GodotSettings `mapstructure:"godot"` + Godox GodoxSettings `mapstructure:"godox"` + Goheader GoHeaderSettings `mapstructure:"goheader"` + GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"` + Gomodguard GoModGuardSettings `mapstructure:"gomodguard"` + Gosec GoSecSettings `mapstructure:"gosec"` + Gosmopolitan GosmopolitanSettings `mapstructure:"gosmopolitan"` + Unqueryvet UnqueryvetSettings `mapstructure:"unqueryvet"` + Govet GovetSettings `mapstructure:"govet"` + Grouper GrouperSettings `mapstructure:"grouper"` + Iface IfaceSettings `mapstructure:"iface"` + ImportAs ImportAsSettings `mapstructure:"importas"` + Inamedparam INamedParamSettings `mapstructure:"inamedparam"` + Ineffassign IneffassignSettings `mapstructure:"ineffassign"` + InterfaceBloat InterfaceBloatSettings `mapstructure:"interfacebloat"` + IotaMixing IotaMixingSettings `mapstructure:"iotamixing"` + Ireturn IreturnSettings `mapstructure:"ireturn"` + Lll LllSettings `mapstructure:"lll"` + LoggerCheck LoggerCheckSettings `mapstructure:"loggercheck"` + MaintIdx MaintIdxSettings `mapstructure:"maintidx"` + Makezero MakezeroSettings `mapstructure:"makezero"` + Misspell MisspellSettings `mapstructure:"misspell"` + Mnd MndSettings `mapstructure:"mnd"` + Modernize ModernizeSettings `mapstructure:"modernize"` + MustTag MustTagSettings `mapstructure:"musttag"` + Nakedret NakedretSettings `mapstructure:"nakedret"` + Nestif NestifSettings `mapstructure:"nestif"` + NilNil NilNilSettings `mapstructure:"nilnil"` + Nlreturn NlreturnSettings `mapstructure:"nlreturn"` + NoLintLint NoLintLintSettings `mapstructure:"nolintlint"` + NoNamedReturns NoNamedReturnsSettings `mapstructure:"nonamedreturns"` + ParallelTest ParallelTestSettings `mapstructure:"paralleltest"` + PerfSprint PerfSprintSettings `mapstructure:"perfsprint"` + Prealloc PreallocSettings `mapstructure:"prealloc"` + Predeclared PredeclaredSettings `mapstructure:"predeclared"` + Promlinter PromlinterSettings `mapstructure:"promlinter"` + ProtoGetter ProtoGetterSettings `mapstructure:"protogetter"` + Reassign ReassignSettings `mapstructure:"reassign"` + Recvcheck RecvcheckSettings `mapstructure:"recvcheck"` + Revive ReviveSettings `mapstructure:"revive"` + RowsErrCheck RowsErrCheckSettings `mapstructure:"rowserrcheck"` + SlogLint SlogLintSettings `mapstructure:"sloglint"` + Spancheck SpancheckSettings `mapstructure:"spancheck"` + Staticcheck StaticCheckSettings `mapstructure:"staticcheck"` + TagAlign TagAlignSettings `mapstructure:"tagalign"` + Tagliatelle TagliatelleSettings `mapstructure:"tagliatelle"` + Testifylint TestifylintSettings `mapstructure:"testifylint"` + Testpackage TestpackageSettings `mapstructure:"testpackage"` + Thelper ThelperSettings `mapstructure:"thelper"` + Unconvert UnconvertSettings `mapstructure:"unconvert"` + Unparam UnparamSettings `mapstructure:"unparam"` + Unused UnusedSettings `mapstructure:"unused"` + UseStdlibVars UseStdlibVarsSettings `mapstructure:"usestdlibvars"` + UseTesting UseTestingSettings `mapstructure:"usetesting"` + Varnamelen VarnamelenSettings `mapstructure:"varnamelen"` + Whitespace WhitespaceSettings `mapstructure:"whitespace"` + Wrapcheck WrapcheckSettings `mapstructure:"wrapcheck"` + WSL WSLv4Settings `mapstructure:"wsl"` // Deprecated: use WSLv5 instead. + WSLv5 WSLv5Settings `mapstructure:"wsl_v5"` Custom map[string]CustomLinterSettings `mapstructure:"custom"` } @@ -363,8 +386,14 @@ type DuplSettings struct { } type DupWordSettings struct { - Keywords []string `mapstructure:"keywords"` - Ignore []string `mapstructure:"ignore"` + Keywords []string `mapstructure:"keywords"` + Ignore []string `mapstructure:"ignore"` + CommentsOnly bool `mapstructure:"comments-only"` +} + +type EmbeddedStructFieldCheckSettings struct { + ForbidMutex bool `mapstructure:"forbid-mutex"` + EmptyLine bool `mapstructure:"empty-line"` } type ErrcheckSettings struct { @@ -372,6 +401,7 @@ type ErrcheckSettings struct { CheckTypeAssertions bool `mapstructure:"check-type-assertions"` CheckAssignToBlank bool `mapstructure:"check-blank"` ExcludeFunctions []string `mapstructure:"exclude-functions"` + Verbose bool `mapstructure:"verbose"` } type ErrChkJSONSettings struct { @@ -405,8 +435,12 @@ type ExhaustiveSettings struct { } type ExhaustructSettings struct { - Include []string `mapstructure:"include"` - Exclude []string `mapstructure:"exclude"` + Include []string `mapstructure:"include"` + Exclude []string `mapstructure:"exclude"` + AllowEmpty bool `mapstructure:"allow-empty"` + AllowEmptyRx []string `mapstructure:"allow-empty-rx"` + AllowEmptyReturns bool `mapstructure:"allow-empty-returns"` + AllowEmptyDeclarations bool `mapstructure:"allow-empty-declarations"` } type FatcontextSettings struct { @@ -428,6 +462,7 @@ type ForbidigoPattern struct { type FuncOrderSettings struct { Constructor bool `mapstructure:"constructor,omitempty"` StructMethod bool `mapstructure:"struct-method,omitempty"` + Alphabetical bool `mapstructure:"alphabetical,omitempty"` } type FunlenSettings struct { @@ -449,6 +484,8 @@ type GinkgoLinterSettings struct { ValidateAsyncIntervals bool `mapstructure:"validate-async-intervals"` ForbidSpecPollution bool `mapstructure:"forbid-spec-pollution"` ForceSucceedForFuncs bool `mapstructure:"force-succeed"` + ForceAssertionDescription bool `mapstructure:"force-assertion-description"` + ForeToNot bool `mapstructure:"force-tonot"` } type GoChecksumTypeSettings struct { @@ -493,6 +530,24 @@ type GoCycloSettings struct { MinComplexity int `mapstructure:"min-complexity"` } +type GodoclintSettings struct { + Default *string `mapstructure:"default"` + Enable []string `mapstructure:"enable"` + Disable []string `mapstructure:"disable"` + Options struct { + MaxLen struct { + Length *uint `mapstructure:"length"` + } `mapstructure:"max-len"` + RequireDoc struct { + IgnoreExported *bool `mapstructure:"ignore-exported"` + IgnoreUnexported *bool `mapstructure:"ignore-unexported"` + } `mapstructure:"require-doc"` + StartWithName struct { + IncludeUnexported *bool `mapstructure:"include-unexported"` + } `mapstructure:"start-with-name"` + } `mapstructure:"options"` +} + type GodotSettings struct { Scope string `mapstructure:"scope"` Exclude []string `mapstructure:"exclude"` @@ -618,10 +673,18 @@ type INamedParamSettings struct { SkipSingleParam bool `mapstructure:"skip-single-param"` } +type IneffassignSettings struct { + CheckEscapingErrors bool `mapstructure:"check-escaping-errors"` +} + type InterfaceBloatSettings struct { Max int `mapstructure:"max"` } +type IotaMixingSettings struct { + ReportIndividual bool `mapstructure:"report-individual"` +} + type IreturnSettings struct { Allow []string `mapstructure:"allow"` Reject []string `mapstructure:"reject"` @@ -698,6 +761,10 @@ type MndSettings struct { IgnoredFunctions []string `mapstructure:"ignored-functions"` } +type ModernizeSettings struct { + Disable []string `mapstructure:"disable"` +} + type NoLintLintSettings struct { RequireExplanation bool `mapstructure:"require-explanation"` RequireSpecific bool `mapstructure:"require-specific"` @@ -729,6 +796,9 @@ type PerfSprintSettings struct { BoolFormat bool `mapstructure:"bool-format"` HexFormat bool `mapstructure:"hex-format"` + + ConcatLoop bool `mapstructure:"concat-loop"` + LoopOtherOps bool `mapstructure:"loop-other-ops"` } type PreallocSettings struct { @@ -764,15 +834,16 @@ type RecvcheckSettings struct { } type ReviveSettings struct { - Go string `mapstructure:"-"` - MaxOpenFiles int `mapstructure:"max-open-files"` - Confidence float64 `mapstructure:"confidence"` - Severity string `mapstructure:"severity"` - EnableAllRules bool `mapstructure:"enable-all-rules"` - Rules []ReviveRule `mapstructure:"rules"` - ErrorCode int `mapstructure:"error-code"` - WarningCode int `mapstructure:"warning-code"` - Directives []ReviveDirective `mapstructure:"directives"` + Go string `mapstructure:"-"` + MaxOpenFiles int `mapstructure:"max-open-files"` + Confidence float64 `mapstructure:"confidence"` + Severity string `mapstructure:"severity"` + EnableAllRules bool `mapstructure:"enable-all-rules"` + EnableDefaultRules bool `mapstructure:"enable-default-rules"` + Rules []ReviveRule `mapstructure:"rules"` + ErrorCode int `mapstructure:"error-code"` + WarningCode int `mapstructure:"warning-code"` + Directives []ReviveDirective `mapstructure:"directives"` } type ReviveRule struct { @@ -820,7 +891,7 @@ type StaticCheckSettings struct { } func (s *StaticCheckSettings) HasConfiguration() bool { - return len(s.Initialisms) > 0 || len(s.HTTPStatusCodeWhitelist) > 0 || len(s.DotImportWhitelist) > 0 || len(s.Checks) > 0 + return s.Initialisms == nil || s.HTTPStatusCodeWhitelist == nil || s.DotImportWhitelist == nil || s.Checks == nil } type TagAlignSettings struct { @@ -927,6 +998,7 @@ type UseStdlibVarsSettings struct { SQLIsolationLevel bool `mapstructure:"sql-isolation-level"` TLSSignatureScheme bool `mapstructure:"tls-signature-scheme"` ConstantKind bool `mapstructure:"constant-kind"` + TimeDateMonth bool `mapstructure:"time-date-month"` } type UseTestingSettings struct { @@ -948,6 +1020,11 @@ type UnparamSettings struct { CheckExported bool `mapstructure:"check-exported"` } +type UnqueryvetSettings struct { + CheckSQLBuilders bool `mapstructure:"check-sql-builders"` + AllowedPatterns []string `mapstructure:"allowed-patterns"` +} + type UnusedSettings struct { FieldWritesAreUses bool `mapstructure:"field-writes-are-uses"` PostStatementsAreReads bool `mapstructure:"post-statements-are-reads"` @@ -984,7 +1061,8 @@ type WrapcheckSettings struct { ReportInternalErrors bool `mapstructure:"report-internal-errors"` } -type WSLSettings struct { +// Deprecated: use WSLv5Settings instead. +type WSLv4Settings struct { StrictAppend bool `mapstructure:"strict-append"` AllowAssignAndCallCuddle bool `mapstructure:"allow-assign-and-call"` AllowAssignAndAnythingCuddle bool `mapstructure:"allow-assign-and-anything"` @@ -1001,6 +1079,16 @@ type WSLSettings struct { ForceExclusiveShortDeclarations bool `mapstructure:"force-short-decl-cuddling"` } +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"` +} + // CustomLinterSettings encapsulates the meta-data of a private linter. type CustomLinterSettings struct { // Type plugin type. diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/loader.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/loader.go index 3ff930648..511c3ab7d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/loader.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/loader.go @@ -153,7 +153,7 @@ func (l *Loader) appendStringSlice(name string, current *[]string) { func (l *Loader) checkConfigurationVersion() error { if l.cfg.GetConfigDir() != "" && l.cfg.Version != "2" { return fmt.Errorf("unsupported version of the configuration: %q "+ - "See https://golangci-lint.run/product/migration-guide for migration instructions", l.cfg.Version) + "See https://golangci-lint.run/docs/product/migration-guide for migration instructions", l.cfg.Version) } return nil diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/issue.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/issue.go index c41702595..88a59e53d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/issue.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/issue.go @@ -9,13 +9,13 @@ import ( ) type Issue struct { - result.Issue + *result.Issue Pass *analysis.Pass } -func NewIssue(issue *result.Issue, pass *analysis.Pass) Issue { - return Issue{ - Issue: *issue, +func NewIssue(issue *result.Issue, pass *analysis.Pass) *Issue { + return &Issue{ + Issue: issue, Pass: pass, } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/linter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/linter.go index 80ccfe456..153e538b5 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/linter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/linter.go @@ -13,11 +13,6 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -const ( - TheOnlyAnalyzerName = "the_only_name" - TheOnlyanalyzerDoc = "the_only_doc" -) - type LoadMode int func (loadMode LoadMode) String() string { @@ -45,7 +40,7 @@ type Linter struct { name, desc string analyzers []*analysis.Analyzer cfg map[string]map[string]any - issuesReporter func(*linter.Context) []Issue + issuesReporter func(*linter.Context) []*Issue contextSetter func(*linter.Context) loadMode LoadMode needUseOriginalPackages bool @@ -55,7 +50,11 @@ func NewLinter(name, desc string, analyzers []*analysis.Analyzer, cfg map[string return &Linter{name: name, desc: desc, analyzers: analyzers, cfg: cfg} } -func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) { +func NewLinterFromAnalyzer(analyzer *analysis.Analyzer) *Linter { + return NewLinter(analyzer.Name, analyzer.Doc, []*analysis.Analyzer{analyzer}, nil) +} + +func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]*result.Issue, error) { if err := lnt.preRun(lintCtx); err != nil { return nil, err } @@ -71,12 +70,49 @@ func (lnt *Linter) LoadMode() LoadMode { return lnt.loadMode } +func (lnt *Linter) WithDesc(desc string) *Linter { + lnt.desc = desc + + return lnt +} + +func (lnt *Linter) WithVersion(v int) *Linter { + if v == 0 { + return lnt + } + + for _, analyzer := range lnt.analyzers { + if lnt.name != analyzer.Name { + continue + } + + // The analyzer name should be the same as the linter name to avoid displaying the name inside the reports. + analyzer.Name = fmt.Sprintf("%s_v%d", analyzer.Name, v) + } + + lnt.name = fmt.Sprintf("%s_v%d", lnt.name, v) + + return lnt +} + +func (lnt *Linter) WithConfig(cfg map[string]any) *Linter { + if len(cfg) == 0 { + return lnt + } + + lnt.cfg = map[string]map[string]any{ + lnt.name: cfg, + } + + return lnt +} + func (lnt *Linter) WithLoadMode(loadMode LoadMode) *Linter { lnt.loadMode = loadMode return lnt } -func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []Issue) *Linter { +func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []*Issue) *Linter { lnt.issuesReporter = r return lnt } @@ -176,7 +212,7 @@ func (lnt *Linter) useOriginalPackages() bool { return lnt.needUseOriginalPackages } -func (lnt *Linter) reportIssues(lintCtx *linter.Context) []Issue { +func (lnt *Linter) reportIssues(lintCtx *linter.Context) []*Issue { if lnt.issuesReporter != nil { return lnt.issuesReporter(lintCtx) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/metalinter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/metalinter.go index 4db143bad..b9a210a66 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/metalinter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/metalinter.go @@ -21,7 +21,7 @@ func NewMetaLinter(linters []*Linter) *MetaLinter { return ml } -func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) { +func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]*result.Issue, error) { for _, l := range ml.linters { if err := l.preRun(lintCtx); err != nil { return nil, fmt.Errorf("failed to pre-run %s: %w", l.Name(), err) @@ -65,8 +65,8 @@ func (MetaLinter) useOriginalPackages() bool { return false // `unused` can't be run by this metalinter } -func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []Issue { - var ret []Issue +func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []*Issue { + var ret []*Issue for _, lnt := range ml.linters { if lnt.issuesReporter != nil { ret = append(ret, lnt.issuesReporter(lintCtx)...) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/errors.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/errors.go index 587e72720..5d2b816ac 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/errors.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/errors.go @@ -18,8 +18,9 @@ func (e *IllTypedError) Error() string { return fmt.Sprintf("IllTypedError: errors in package: %v", e.Pkg.Errors) } -func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]result.Issue, error) { - var issues []result.Issue +func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]*result.Issue, error) { + var issues []*result.Issue + uniqReportedIssues := map[string]bool{} var other error @@ -39,11 +40,19 @@ func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]resu if uniqReportedIssues[err.Msg] { continue } + uniqReportedIssues[err.Msg] = true lintCtx.Log.Errorf("typechecking error: %s", err.Msg) } else { + key := fmt.Sprintf("%s.%d.%d.%s", issue.FilePath(), issue.Line(), issue.Column(), issue.Text) + if uniqReportedIssues[key] { + continue + } + + uniqReportedIssues[key] = true + issue.Pkg = ill.Pkg // to save to cache later - issues = append(issues, *issue) + issues = append(issues, issue) } } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/extract.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/extract.go index d1257e663..76a4c9022 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/extract.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/extract.go @@ -2,6 +2,7 @@ package pkgerrors import ( "fmt" + "maps" "regexp" "strings" @@ -18,7 +19,9 @@ func extractErrors(pkg *packages.Package) []packages.Error { return errors } + skippedErrors := map[string]packages.Error{} seenErrors := map[string]bool{} + var uniqErrors []packages.Error for _, err := range errors { msg := stackCrusher(err.Error()) @@ -26,15 +29,35 @@ func extractErrors(pkg *packages.Package) []packages.Error { continue } + // This `if` is important to avoid duplicate errors. + // The goal is to keep the most relevant error. if msg != err.Error() { + prev, alreadySkip := skippedErrors[msg] + if !alreadySkip { + skippedErrors[msg] = err + continue + } + + if len(err.Error()) < len(prev.Error()) { + skippedErrors[msg] = err + } + continue } + delete(skippedErrors, msg) + seenErrors[msg] = true uniqErrors = append(uniqErrors, err) } + // In some cases, the error stack doesn't contain the tip error. + // We must keep at least one of the original errors that contain the specific message. + for skippedError := range maps.Values(skippedErrors) { + uniqErrors = append(uniqErrors, skippedError) + } + if len(pkg.GoFiles) != 0 { // errors were extracted from deps and have at least one file in package for i := range uniqErrors { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/parse.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/parse.go index 8c49a5592..2fe1fb529 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/parse.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/pkgerrors/parse.go @@ -26,7 +26,7 @@ func parseError(srcErr packages.Error) (*result.Issue, error) { } func parseErrorPosition(pos string) (*token.Position, error) { - // file:line(:colon) + // file:line(:column) parts := strings.Split(pos, ":") if len(parts) == 1 { return nil, errors.New("no colons") @@ -39,7 +39,7 @@ func parseErrorPosition(pos string) (*token.Position, error) { } var column int - if len(parts) == 3 { // no column + if len(parts) == 3 { // got column column, err = strconv.Atoi(parts[2]) if err != nil { return nil, fmt.Errorf("failed to parse column from %q: %w", parts[2], err) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner.go index 808c9d2ad..ba9c0bd06 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner.go @@ -5,6 +5,7 @@ package goanalysis import ( + "context" "encoding/gob" "fmt" "go/token" @@ -76,7 +77,7 @@ func newRunner(prefix string, logger logutils.Log, pkgCache *cache.Cache, loadGu // It provides most of the logic for the main functions of both the // singlechecker and the multi-analysis commands. // It returns the appropriate exit code. -func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]Diagnostic, +func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]*Diagnostic, []error, map[*analysis.Pass]*packages.Package, ) { debugf("Analyzing %d packages on load mode %s", len(initialPackages), r.loadMode) @@ -257,25 +258,34 @@ func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyze // Limit memory and IO usage. gomaxprocs := runtime.GOMAXPROCS(-1) debugf("Analyzing at most %d packages in parallel", gomaxprocs) + loadSem := make(chan struct{}, gomaxprocs) - var wg sync.WaitGroup debugf("There are %d initial and %d total packages", len(initialPkgs), len(loadingPackages)) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var wg sync.WaitGroup + for _, lp := range loadingPackages { if lp.isInitial { wg.Add(1) + go func(lp *loadingPackage) { - lp.analyzeRecursive(r.loadMode, loadSem) + lp.analyzeRecursive(ctx, cancel, r.loadMode, loadSem) + wg.Done() }(lp) } } + wg.Wait() return rootActions } -func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []error) { +func extractDiagnostics(roots []*action) (retDiags []*Diagnostic, retErrors []error) { extracted := make(map[*action]bool) var extract func(*action) var visitAll func(actions []*action) @@ -322,7 +332,7 @@ func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []err } seen[k] = true - retDiag := Diagnostic{ + retDiag := &Diagnostic{ File: file, Diagnostic: diag, Analyzer: act.Analyzer, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action.go index 2c332d83e..eafc2e4d8 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action.go @@ -1,6 +1,7 @@ package goanalysis import ( + "context" "fmt" "runtime/debug" @@ -28,10 +29,14 @@ func (actAlloc *actionAllocator) alloc() *action { return act } -func (act *action) waitUntilDependingAnalyzersWorked() { +func (act *action) waitUntilDependingAnalyzersWorked(ctx context.Context) { for _, dep := range act.Deps { if dep.Package == act.Package { - <-dep.analysisDoneCh + select { + case <-ctx.Done(): + return + case <-dep.analysisDoneCh: + } } } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_checker.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_checker.go index 569002ed4..e8fda9947 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_checker.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_checker.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "go/types" + "os" "reflect" "time" @@ -160,7 +161,7 @@ func (act *action) analyze() { AllObjectFacts: act.AllObjectFacts, AllPackageFacts: act.AllPackageFacts, } - pass.ReadFile = analysisinternal.MakeReadFile(pass) + pass.ReadFile = analysisinternal.CheckedReadFile(pass, os.ReadFile) act.pass = pass act.runner.passToPkgGuard.Lock() diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go index d22dbea30..217803bba 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go @@ -1,6 +1,7 @@ package goanalysis import ( + "context" "errors" "fmt" "go/ast" @@ -14,6 +15,7 @@ import ( "sync" "sync/atomic" + "golang.org/x/sync/errgroup" "golang.org/x/tools/go/gcexportdata" "golang.org/x/tools/go/packages" @@ -39,54 +41,83 @@ type loadingPackage struct { decUseMutex sync.Mutex } -func (lp *loadingPackage) analyzeRecursive(loadMode LoadMode, loadSem chan struct{}) { +func (lp *loadingPackage) analyzeRecursive(ctx context.Context, cancel context.CancelFunc, loadMode LoadMode, loadSem chan struct{}) { lp.analyzeOnce.Do(func() { // Load the direct dependencies, in parallel. var wg sync.WaitGroup + wg.Add(len(lp.imports)) + for _, imp := range lp.imports { go func(imp *loadingPackage) { - imp.analyzeRecursive(loadMode, loadSem) + imp.analyzeRecursive(ctx, cancel, loadMode, loadSem) + wg.Done() }(imp) } + wg.Wait() - lp.analyze(loadMode, loadSem) + + lp.analyze(ctx, cancel, loadMode, loadSem) }) } -func (lp *loadingPackage) analyze(loadMode LoadMode, loadSem chan struct{}) { - loadSem <- struct{}{} - defer func() { - <-loadSem - }() +func (lp *loadingPackage) analyze(ctx context.Context, cancel context.CancelFunc, loadMode LoadMode, loadSem chan struct{}) { + select { + case <-ctx.Done(): + return + case loadSem <- struct{}{}: + defer func() { + <-loadSem + }() + } // Save memory on unused more fields. defer lp.decUse(loadMode < LoadModeWholeProgram) if err := lp.loadWithFacts(loadMode); err != nil { + // Note: this error is ignored when there is no facts loading (e.g. with 98% of linters). + // But this is not a problem because the errors are added to the package.Errors. + // You through an error, try to add it to actions, but there is no action annnddd it's gone! werr := fmt.Errorf("failed to load package %s: %w", lp.pkg.Name, err) + // Don't need to write error to errCh, it will be extracted and reported on another layer. // Unblock depending on actions and propagate error. for _, act := range lp.actions { close(act.analysisDoneCh) + act.Err = werr } + + if len(lp.actions) == 0 { + lp.log.Warnf("no action but there is an error: %v", err) + } + return } - var actsWg sync.WaitGroup - actsWg.Add(len(lp.actions)) + actsWg, ctxGroup := errgroup.WithContext(ctx) + for _, act := range lp.actions { - go func(act *action) { - defer actsWg.Done() + actsWg.Go(func() error { + act.waitUntilDependingAnalyzersWorked(ctxGroup) - act.waitUntilDependingAnalyzersWorked() + select { + case <-ctxGroup.Done(): + return nil + default: + } act.analyzeSafe() - }(act) + + return act.Err + }) + } + + err := actsWg.Wait() + if err != nil { + cancel() } - actsWg.Wait() } func (lp *loadingPackage) loadFromSource(loadMode LoadMode) error { @@ -213,9 +244,11 @@ func (lp *loadingPackage) loadFromExportData() error { return fmt.Errorf("dependency %q hasn't been loaded yet", path) } } + if pkg.ExportFile == "" { return fmt.Errorf("no export data for %q", pkg.ID) } + f, err := os.Open(pkg.ExportFile) if err != nil { return err @@ -306,13 +339,15 @@ func (lp *loadingPackage) loadImportedPackageWithFacts(loadMode LoadMode) error if srcErr := lp.loadFromSource(loadMode); srcErr != nil { return srcErr } + // Make sure this package can't be imported successfully pkg.Errors = append(pkg.Errors, packages.Error{ Pos: "-", Msg: fmt.Sprintf("could not load export data: %s", err), Kind: packages.ParseError, }) - return fmt.Errorf("could not load export data: %w", err) + + return nil } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners.go index fe8d8fe85..bcbc0033e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners.go @@ -3,6 +3,7 @@ package goanalysis import ( "fmt" "go/token" + "slices" "strings" "golang.org/x/tools/go/analysis" @@ -20,11 +21,11 @@ type runAnalyzersConfig interface { getLinterNameForDiagnostic(*Diagnostic) string getAnalyzers() []*analysis.Analyzer useOriginalPackages() bool - reportIssues(*linter.Context) []Issue + reportIssues(*linter.Context) []*Issue getLoadMode() LoadMode } -func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Issue, error) { +func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]*result.Issue, error) { log := lintCtx.Log.Child(logutils.DebugKeyGoAnalysis) sw := timeutils.NewStopwatch("analyzers", log) @@ -56,18 +57,19 @@ func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Iss } }() - buildAllIssues := func() []result.Issue { - var retIssues []result.Issue + buildAllIssues := func() []*result.Issue { + var retIssues []*result.Issue + reportedIssues := cfg.reportIssues(lintCtx) - for i := range reportedIssues { - issue := &reportedIssues[i].Issue - if issue.Pkg == nil { - issue.Pkg = passToPkg[reportedIssues[i].Pass] + for _, reportedIssue := range reportedIssues { + if reportedIssue.Pkg == nil { + reportedIssue.Pkg = passToPkg[reportedIssue.Pass] } - retIssues = append(retIssues, *issue) + + retIssues = append(retIssues, reportedIssue.Issue) } - retIssues = append(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic)...) - return retIssues + + return slices.Concat(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic)) } errIssues, err := pkgerrors.BuildIssuesFromIllTypedError(errs, lintCtx) @@ -81,11 +83,10 @@ func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Iss return issues, nil } -func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []result.Issue { - var issues []result.Issue +func buildIssues(diags []*Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []*result.Issue { + var issues []*result.Issue - for i := range diags { - diag := &diags[i] + for _, diag := range diags { linterName := linterNameBuilder(diag) var text string @@ -126,7 +127,7 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st suggestedFixes = append(suggestedFixes, nsf) } - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ FromLinter: linterName, Text: text, Pos: diag.Position, @@ -142,7 +143,7 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st relatedPos = diag.Position } - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ FromLinter: linterName, Text: fmt.Sprintf("%s(related information): %s", diag.Analyzer.Name, info.Message), Pos: relatedPos, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners_cache.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners_cache.go index 9673197c9..5cd8a6b1c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners_cache.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runners_cache.go @@ -17,13 +17,12 @@ import ( ) func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.Package]bool, - issues []result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer, + issues []*result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer, ) { startedAt := time.Now() - perPkgIssues := map[*packages.Package][]result.Issue{} - for ind := range issues { - i := &issues[ind] - perPkgIssues[i.Pkg] = append(perPkgIssues[i.Pkg], *i) + perPkgIssues := map[*packages.Package][]*result.Issue{} + for _, issue := range issues { + perPkgIssues[issue.Pkg] = append(perPkgIssues[issue.Pkg], issue) } var savedIssuesCount int64 = 0 @@ -34,23 +33,22 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages. wg.Add(workerCount) pkgCh := make(chan *packages.Package, len(allPkgs)) - for i := 0; i < workerCount; i++ { + for range workerCount { go func() { defer wg.Done() for pkg := range pkgCh { pkgIssues := perPkgIssues[pkg] encodedIssues := make([]EncodingIssue, 0, len(pkgIssues)) - for ind := range pkgIssues { - i := &pkgIssues[ind] + for _, issue := range pkgIssues { encodedIssues = append(encodedIssues, EncodingIssue{ - FromLinter: i.FromLinter, - Text: i.Text, - Severity: i.Severity, - Pos: i.Pos, - LineRange: i.LineRange, - SuggestedFixes: i.SuggestedFixes, - ExpectNoLint: i.ExpectNoLint, - ExpectedNoLintLinter: i.ExpectedNoLintLinter, + FromLinter: issue.FromLinter, + Text: issue.Text, + Severity: issue.Severity, + Pos: issue.Pos, + LineRange: issue.LineRange, + SuggestedFixes: issue.SuggestedFixes, + ExpectNoLint: issue.ExpectNoLint, + ExpectedNoLintLinter: issue.ExpectedNoLintLinter, }) } @@ -81,12 +79,12 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages. func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, analyzers []*analysis.Analyzer, -) (issuesFromCache []result.Issue, pkgsFromCache map[*packages.Package]bool) { +) (issuesFromCache []*result.Issue, pkgsFromCache map[*packages.Package]bool) { startedAt := time.Now() lintResKey := getIssuesCacheKey(analyzers) type cacheRes struct { - issues []result.Issue + issues []*result.Issue loadErr error } pkgToCacheRes := make(map[*packages.Package]*cacheRes, len(pkgs)) @@ -103,7 +101,7 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, go func() { defer wg.Done() for pkg := range pkgCh { - var pkgIssues []EncodingIssue + var pkgIssues []*EncodingIssue err := lintCtx.PkgCache.Get(pkg, cache.HashModeNeedAllDeps, lintResKey, &pkgIssues) cacheRes := pkgToCacheRes[pkg] cacheRes.loadErr = err @@ -114,10 +112,9 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, continue } - issues := make([]result.Issue, 0, len(pkgIssues)) - for i := range pkgIssues { - issue := &pkgIssues[i] - issues = append(issues, result.Issue{ + issues := make([]*result.Issue, 0, len(pkgIssues)) + for _, issue := range pkgIssues { + issues = append(issues, &result.Issue{ FromLinter: issue.FromLinter, Text: issue.Text, Severity: issue.Severity, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformat/runner.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformat/runner.go index fa1d1acc3..650fb8f5e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformat/runner.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformat/runner.go @@ -57,7 +57,7 @@ func (c *Runner) Run(paths []string) error { } if c.opts.stdin { - return c.process("", savedStdout, os.Stdin) + return c.formatStdIn("", savedStdout, os.Stdin) } for _, path := range paths { @@ -121,15 +121,6 @@ func (c *Runner) process(path string, stdout io.Writer, in io.Reader) error { output := c.metaFormatter.Format(path, input) - if c.opts.stdin { - _, err = stdout.Write(output) - if err != nil { - return err - } - - return nil - } - if bytes.Equal(input, output) { return nil } @@ -168,6 +159,38 @@ func (c *Runner) process(path string, stdout io.Writer, in io.Reader) error { return os.WriteFile(path, output, perms) } +func (c *Runner) formatStdIn(path string, stdout io.Writer, in io.Reader) error { + input, err := io.ReadAll(in) + if err != nil { + return err + } + + match, err := c.matcher.IsGeneratedFile(path, input) + if err != nil { + return err + } + + if match { + // If the file is generated, + // the input should be written to the stdout to avoid emptied the file. + _, err = stdout.Write(input) + if err != nil { + return err + } + + return nil + } + + output := c.metaFormatter.Format(path, input) + + _, err = stdout.Write(output) + if err != nil { + return err + } + + return nil +} + func (c *Runner) setOutputToDevNull() { devNull, err := os.Open(os.DevNull) if err != nil { @@ -200,8 +223,14 @@ func NewRunnerOptions(cfg *config.Config, diff, diffColored, stdin bool) (Runner return RunnerOptions{}, fmt.Errorf("get base path: %w", err) } + // Required to be consistent with `RunnerOptions.MatchAnyPattern`. + absBasePath, err := filepath.Abs(basePath) + if err != nil { + return RunnerOptions{}, err + } + opts := RunnerOptions{ - basePath: basePath, + basePath: absBasePath, generated: cfg.Formatters.Exclusions.Generated, diff: diff || diffColored, colors: diffColored, @@ -228,7 +257,12 @@ func (o RunnerOptions) MatchAnyPattern(path string) (bool, error) { return false, nil } - rel, err := filepath.Rel(o.basePath, path) + abs, err := filepath.Abs(path) + if err != nil { + return false, err + } + + rel, err := filepath.Rel(o.basePath, abs) if err != nil { return false, err } @@ -249,7 +283,7 @@ func skipDir(name string) bool { return true default: - return strings.HasPrefix(name, ".") + return strings.HasPrefix(name, ".") && name != "." } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/gci.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/gci.go index 3eba10f10..cf1e86515 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/gci.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/gci.go @@ -2,6 +2,7 @@ package gci import ( "context" + "go/format" gcicfg "github.com/daixiang0/gci/pkg/config" "github.com/daixiang0/gci/pkg/gci" @@ -60,5 +61,14 @@ func (*Formatter) Name() string { func (f *Formatter) Format(filename string, src []byte) ([]byte, error) { _, formatted, err := gci.LoadFormat(src, filename, *f.config) - return formatted, err + if err != nil { + return nil, err + } + + // gci format the code only when the imports are modified, + // this produced inconsistencies. + // To be always consistent, the code should always be formatted. + // https://github.com/daixiang0/gci/blob/c4f689991095c0e54843dca76fb9c3bad58ec5c7/pkg/gci/gci.go#L148-L151 + // https://github.com/daixiang0/gci/blob/c4f689991095c0e54843dca76fb9c3bad58ec5c7/pkg/gci/gci.go#L215 + return format.Source(formatted) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/config/config.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/config/config.go index c859b442f..13ca6dd86 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/config/config.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/config/config.go @@ -4,7 +4,7 @@ import ( "sort" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/daixiang0/gci/pkg/config" "github.com/daixiang0/gci/pkg/section" diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go index 2fddded70..f84eb0f33 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go @@ -1,182 +1,185 @@ package section -// Code generated based on go1.24.0 X:boringcrypto,arenas,synctest. DO NOT EDIT. +// Code generated based on go1.25.0 X:boringcrypto,arenas,synctest,jsonv2. DO NOT EDIT. var standardPackages = map[string]struct{}{ - "archive/tar": {}, - "archive/zip": {}, - "arena": {}, - "bufio": {}, - "bytes": {}, - "cmp": {}, - "compress/bzip2": {}, - "compress/flate": {}, - "compress/gzip": {}, - "compress/lzw": {}, - "compress/zlib": {}, - "container/heap": {}, - "container/list": {}, - "container/ring": {}, - "context": {}, - "crypto": {}, - "crypto/aes": {}, - "crypto/boring": {}, - "crypto/cipher": {}, - "crypto/des": {}, - "crypto/dsa": {}, - "crypto/ecdh": {}, - "crypto/ecdsa": {}, - "crypto/ed25519": {}, - "crypto/elliptic": {}, - "crypto/fips140": {}, - "crypto/hkdf": {}, - "crypto/hmac": {}, - "crypto/md5": {}, - "crypto/mlkem": {}, - "crypto/pbkdf2": {}, - "crypto/rand": {}, - "crypto/rc4": {}, - "crypto/rsa": {}, - "crypto/sha1": {}, - "crypto/sha256": {}, - "crypto/sha3": {}, - "crypto/sha512": {}, - "crypto/subtle": {}, - "crypto/tls": {}, - "crypto/tls/fipsonly": {}, - "crypto/x509": {}, - "crypto/x509/pkix": {}, - "database/sql": {}, - "database/sql/driver": {}, - "debug/buildinfo": {}, - "debug/dwarf": {}, - "debug/elf": {}, - "debug/gosym": {}, - "debug/macho": {}, - "debug/pe": {}, - "debug/plan9obj": {}, - "embed": {}, - "encoding": {}, - "encoding/ascii85": {}, - "encoding/asn1": {}, - "encoding/base32": {}, - "encoding/base64": {}, - "encoding/binary": {}, - "encoding/csv": {}, - "encoding/gob": {}, - "encoding/hex": {}, - "encoding/json": {}, - "encoding/pem": {}, - "encoding/xml": {}, - "errors": {}, - "expvar": {}, - "flag": {}, - "fmt": {}, - "go/ast": {}, - "go/build": {}, - "go/build/constraint": {}, - "go/constant": {}, - "go/doc": {}, - "go/doc/comment": {}, - "go/format": {}, - "go/importer": {}, - "go/parser": {}, - "go/printer": {}, - "go/scanner": {}, - "go/token": {}, - "go/types": {}, - "go/version": {}, - "hash": {}, - "hash/adler32": {}, - "hash/crc32": {}, - "hash/crc64": {}, - "hash/fnv": {}, - "hash/maphash": {}, - "html": {}, - "html/template": {}, - "image": {}, - "image/color": {}, - "image/color/palette": {}, - "image/draw": {}, - "image/gif": {}, - "image/jpeg": {}, - "image/png": {}, - "index/suffixarray": {}, - "io": {}, - "io/fs": {}, - "io/ioutil": {}, - "iter": {}, - "log": {}, - "log/slog": {}, - "log/syslog": {}, - "maps": {}, - "math": {}, - "math/big": {}, - "math/bits": {}, - "math/cmplx": {}, - "math/rand": {}, - "math/rand/v2": {}, - "mime": {}, - "mime/multipart": {}, - "mime/quotedprintable": {}, - "net": {}, - "net/http": {}, - "net/http/cgi": {}, - "net/http/cookiejar": {}, - "net/http/fcgi": {}, - "net/http/httptest": {}, - "net/http/httptrace": {}, - "net/http/httputil": {}, - "net/http/pprof": {}, - "net/mail": {}, - "net/netip": {}, - "net/rpc": {}, - "net/rpc/jsonrpc": {}, - "net/smtp": {}, - "net/textproto": {}, - "net/url": {}, - "os": {}, - "os/exec": {}, - "os/signal": {}, - "os/user": {}, - "path": {}, - "path/filepath": {}, - "plugin": {}, - "reflect": {}, - "regexp": {}, - "regexp/syntax": {}, - "runtime": {}, - "runtime/cgo": {}, - "runtime/coverage": {}, - "runtime/debug": {}, - "runtime/metrics": {}, - "runtime/pprof": {}, - "runtime/race": {}, - "runtime/trace": {}, - "slices": {}, - "sort": {}, - "strconv": {}, - "strings": {}, - "structs": {}, - "sync": {}, - "sync/atomic": {}, - "syscall": {}, - "testing": {}, - "testing/fstest": {}, - "testing/iotest": {}, - "testing/quick": {}, - "testing/slogtest": {}, - "testing/synctest": {}, - "text/scanner": {}, - "text/tabwriter": {}, - "text/template": {}, - "text/template/parse": {}, - "time": {}, - "time/tzdata": {}, - "unicode": {}, - "unicode/utf16": {}, - "unicode/utf8": {}, - "unique": {}, - "unsafe": {}, - "weak": {}, + "archive/tar": {}, + "archive/zip": {}, + "arena": {}, + "bufio": {}, + "bytes": {}, + "cmp": {}, + "compress/bzip2": {}, + "compress/flate": {}, + "compress/gzip": {}, + "compress/lzw": {}, + "compress/zlib": {}, + "container/heap": {}, + "container/list": {}, + "container/ring": {}, + "context": {}, + "crypto": {}, + "crypto/aes": {}, + "crypto/boring": {}, + "crypto/cipher": {}, + "crypto/des": {}, + "crypto/dsa": {}, + "crypto/ecdh": {}, + "crypto/ecdsa": {}, + "crypto/ed25519": {}, + "crypto/elliptic": {}, + "crypto/fips140": {}, + "crypto/hkdf": {}, + "crypto/hmac": {}, + "crypto/md5": {}, + "crypto/mlkem": {}, + "crypto/pbkdf2": {}, + "crypto/rand": {}, + "crypto/rc4": {}, + "crypto/rsa": {}, + "crypto/sha1": {}, + "crypto/sha256": {}, + "crypto/sha3": {}, + "crypto/sha512": {}, + "crypto/subtle": {}, + "crypto/tls": {}, + "crypto/tls/fipsonly": {}, + "crypto/x509": {}, + "crypto/x509/pkix": {}, + "database/sql": {}, + "database/sql/driver": {}, + "debug/buildinfo": {}, + "debug/dwarf": {}, + "debug/elf": {}, + "debug/gosym": {}, + "debug/macho": {}, + "debug/pe": {}, + "debug/plan9obj": {}, + "embed": {}, + "encoding": {}, + "encoding/ascii85": {}, + "encoding/asn1": {}, + "encoding/base32": {}, + "encoding/base64": {}, + "encoding/binary": {}, + "encoding/csv": {}, + "encoding/gob": {}, + "encoding/hex": {}, + "encoding/json": {}, + "encoding/json/jsontext": {}, + "encoding/json/v2": {}, + "encoding/pem": {}, + "encoding/xml": {}, + "errors": {}, + "expvar": {}, + "flag": {}, + "fmt": {}, + "go/ast": {}, + "go/build": {}, + "go/build/constraint": {}, + "go/constant": {}, + "go/doc": {}, + "go/doc/comment": {}, + "go/format": {}, + "go/importer": {}, + "go/parser": {}, + "go/printer": {}, + "go/scanner": {}, + "go/token": {}, + "go/types": {}, + "go/version": {}, + "hash": {}, + "hash/adler32": {}, + "hash/crc32": {}, + "hash/crc64": {}, + "hash/fnv": {}, + "hash/maphash": {}, + "html": {}, + "html/template": {}, + "image": {}, + "image/color": {}, + "image/color/palette": {}, + "image/draw": {}, + "image/gif": {}, + "image/jpeg": {}, + "image/png": {}, + "index/suffixarray": {}, + "io": {}, + "io/fs": {}, + "io/ioutil": {}, + "iter": {}, + "log": {}, + "log/slog": {}, + "log/syslog": {}, + "maps": {}, + "math": {}, + "math/big": {}, + "math/bits": {}, + "math/cmplx": {}, + "math/rand": {}, + "math/rand/v2": {}, + "mime": {}, + "mime/multipart": {}, + "mime/quotedprintable": {}, + "net": {}, + "net/http": {}, + "net/http/cgi": {}, + "net/http/cookiejar": {}, + "net/http/fcgi": {}, + "net/http/httptest": {}, + "net/http/httptrace": {}, + "net/http/httputil": {}, + "net/http/pprof": {}, + "net/mail": {}, + "net/netip": {}, + "net/rpc": {}, + "net/rpc/jsonrpc": {}, + "net/smtp": {}, + "net/textproto": {}, + "net/url": {}, + "os": {}, + "os/exec": {}, + "os/signal": {}, + "os/user": {}, + "path": {}, + "path/filepath": {}, + "plugin": {}, + "reflect": {}, + "regexp": {}, + "regexp/syntax": {}, + "runtime": {}, + "runtime/cgo": {}, + "runtime/coverage": {}, + "runtime/debug": {}, + "runtime/metrics": {}, + "runtime/pprof": {}, + "runtime/race": {}, + "runtime/trace": {}, + "slices": {}, + "sort": {}, + "strconv": {}, + "strings": {}, + "structs": {}, + "sync": {}, + "sync/atomic": {}, + "syscall": {}, + "syscall/js": {}, + "testing": {}, + "testing/fstest": {}, + "testing/iotest": {}, + "testing/quick": {}, + "testing/slogtest": {}, + "testing/synctest": {}, + "text/scanner": {}, + "text/tabwriter": {}, + "text/template": {}, + "text/template/parse": {}, + "time": {}, + "time/tzdata": {}, + "unicode": {}, + "unicode/utf16": {}, + "unicode/utf8": {}, + "unique": {}, + "unsafe": {}, + "weak": {}, } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/internal/diff.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/internal/diff.go index 7b9f80bc4..fcec87bb8 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/internal/diff.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/internal/diff.go @@ -250,10 +250,7 @@ func ExtractDiagnosticFromPatch( } func toDiagnostic(ft *token.File, change Change, adjLine int) analysis.Diagnostic { - from := change.From + adjLine - if from > ft.LineCount() { - from = ft.LineCount() - } + from := min(change.From+adjLine, ft.LineCount()) start := ft.LineStart(from) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/meta_formatter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/meta_formatter.go index 718caaa96..dbedcd4cb 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/meta_formatter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/meta_formatter.go @@ -12,6 +12,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt" "github.com/golangci/golangci-lint/v2/pkg/goformatters/goimports" "github.com/golangci/golangci-lint/v2/pkg/goformatters/golines" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/logutils" ) @@ -41,6 +42,10 @@ func NewMetaFormatter(log logutils.Log, cfg *config.Formatters, runCfg *config.R m.formatters = append(m.formatters, goimports.New(&cfg.Settings.GoImports)) } + if slices.Contains(cfg.Enable, swaggo.Name) { + m.formatters = append(m.formatters, swaggo.New()) + } + // gci is a last because the only goal of gci is to handle imports. if slices.Contains(cfg.Enable, gci.Name) { formatter, err := gci.New(&cfg.Settings.Gci) @@ -86,5 +91,5 @@ func (m *MetaFormatter) Format(filename string, src []byte) []byte { } func IsFormatter(name string) bool { - return slices.Contains([]string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name}, name) + return slices.Contains([]string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name, swaggo.Name}, name) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo/swaggo.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo/swaggo.go new file mode 100644 index 000000000..2479fb35b --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo/swaggo.go @@ -0,0 +1,23 @@ +package swaggo + +import "github.com/golangci/swaggoswag" + +const Name = "swaggo" + +type Formatter struct { + formatter *swaggoswag.Formatter +} + +func New() *Formatter { + return &Formatter{ + formatter: swaggoswag.NewFormatter(), + } +} + +func (*Formatter) Name() string { + return Name +} + +func (f *Formatter) Format(path string, src []byte) ([]byte, error) { + return f.formatter.Format(path, src) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/arangolint/arangolint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/arangolint/arangolint.go new file mode 100644 index 000000000..1598d532a --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/arangolint/arangolint.go @@ -0,0 +1,13 @@ +package arangolint + +import ( + "go.augendre.info/arangolint/pkg/analyzer" + + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New() *goanalysis.Linter { + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asasalint/asasalint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asasalint/asasalint.go index 5f33428c2..0261e109d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asasalint/asasalint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asasalint/asasalint.go @@ -2,7 +2,6 @@ package asasalint import ( "github.com/alingse/asasalint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -19,15 +18,12 @@ func New(settings *config.AsasalintSettings) *goanalysis.Linter { cfg.IgnoreTest = false } - a, err := asasalint.NewAnalyzer(cfg) + analyzer, err := asasalint.NewAnalyzer(cfg) if err != nil { internal.LinterLogger.Fatalf("asasalint: create analyzer: %v", err) } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck/asciicheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck/asciicheck.go index b5cdaa80b..6a34b256a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck/asciicheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck/asciicheck.go @@ -1,19 +1,13 @@ package asciicheck import ( - "github.com/tdakkota/asciicheck" - "golang.org/x/tools/go/analysis" + "github.com/golangci/asciicheck" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := asciicheck.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(asciicheck.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk/bidichk.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk/bidichk.go index 2d2a8d664..c35daafbf 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk/bidichk.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk/bidichk.go @@ -4,16 +4,14 @@ import ( "strings" "github.com/breml/bidichk/pkg/bidichk" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.BiDiChkSettings) *goanalysis.Linter { - a := bidichk.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { var opts []string @@ -45,15 +43,13 @@ func New(settings *config.BiDiChkSettings) *goanalysis.Linter { opts = append(opts, "POP-DIRECTIONAL-ISOLATE") } - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "disallowed-runes": strings.Join(opts, ","), } } - return goanalysis.NewLinter( - a.Name, - "Checks for dangerous unicode character sequences", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(bidichk.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go index 0c86fbe76..f68c4d0a9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go @@ -2,18 +2,12 @@ package bodyclose import ( "github.com/timakin/bodyclose/passes/bodyclose" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := bodyclose.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(bodyclose.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader/canonicalheader.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader/canonicalheader.go index bda1dfbd2..24e95f143 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader/canonicalheader.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader/canonicalheader.go @@ -2,18 +2,12 @@ package canonicalheader import ( "github.com/lasiar/canonicalheader" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := canonicalheader.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(canonicalheader.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx/containedctx.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx/containedctx.go index 6bdb08350..6d17b8e46 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx/containedctx.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx/containedctx.go @@ -2,18 +2,12 @@ package containedctx import ( "github.com/sivchari/containedctx" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := containedctx.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(containedctx.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck/contextcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck/contextcheck.go index 9d01fb7a2..b01df7d98 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck/contextcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck/contextcheck.go @@ -2,7 +2,8 @@ package contextcheck import ( "github.com/kkHAIKE/contextcheck" - "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/ctrlflow" + "golang.org/x/tools/go/analysis/passes/inspect" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/lint/linter" @@ -10,13 +11,16 @@ import ( func New() *goanalysis.Linter { analyzer := contextcheck.NewAnalyzer(contextcheck.Configuration{}) + // TODO(ldez) there is a problem with this linter: + // I think the problem related to facts. + // The BuildSSA pass has been changed inside (0.39.0): + // https://github.com/golang/tools/commit/b74c09864920a69a4d2f6ef0ecb4f9cff226893a + analyzer.Requires = append(analyzer.Requires, ctrlflow.Analyzer, inspect.Analyzer) - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = contextcheck.NewRun(lintCtx.Packages, false) - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = contextcheck.NewRun(lintCtx.Packages, false) + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar/copyloopvar.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar/copyloopvar.go index f6ca96f99..9dc81de58 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar/copyloopvar.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar/copyloopvar.go @@ -2,28 +2,22 @@ package copyloopvar import ( "github.com/karamaru-alpha/copyloopvar" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.CopyLoopVarSettings) *goanalysis.Linter { - a := copyloopvar.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - "check-alias": settings.CheckAlias, - }, + cfg = map[string]any{ + "check-alias": settings.CheckAlias, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(copyloopvar.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/cyclop/cyclop.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/cyclop/cyclop.go index 41db272cd..0a0e2dbc6 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/cyclop/cyclop.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/cyclop/cyclop.go @@ -2,37 +2,29 @@ package cyclop import ( "github.com/bkielbasa/cyclop/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.CyclopSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() + cfg := map[string]any{} - var cfg map[string]map[string]any if settings != nil { - d := map[string]any{ - // Should be managed with `linters.exclusions.rules`. - "skipTests": false, - } + // Should be managed with `linters.exclusions.rules`. + cfg["skipTests"] = false if settings.MaxComplexity != 0 { - d["maxComplexity"] = settings.MaxComplexity + cfg["maxComplexity"] = settings.MaxComplexity } if settings.PackageAverage != 0 { - d["packageAverage"] = settings.PackageAverage + cfg["packageAverage"] = settings.PackageAverage } - - cfg = map[string]map[string]any{a.Name: d} } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/decorder/decorder.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/decorder/decorder.go index 03a7853c2..a67bdfade 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/decorder/decorder.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/decorder/decorder.go @@ -4,15 +4,12 @@ import ( "strings" "gitlab.com/bosi/decorder" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.DecorderSettings) *goanalysis.Linter { - a := decorder.Analyzer - // disable all rules/checks by default cfg := map[string]any{ "ignore-underscore-vars": false, @@ -35,10 +32,8 @@ func New(settings *config.DecorderSettings) *goanalysis.Linter { cfg["disable-init-func-first-check"] = settings.DisableInitFuncFirstCheck } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - map[string]map[string]any{a.Name: cfg}, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(decorder.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/depguard/depguard.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/depguard/depguard.go index c1f66b0c8..cc01f4f47 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/depguard/depguard.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/depguard/depguard.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/OpenPeeDeeP/depguard/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -41,17 +40,15 @@ func New(settings *config.DepGuardSettings, replacer *strings.Replacer) *goanaly } } - a := depguard.NewUncompiledAnalyzer(&conf) - - return goanalysis.NewLinter( - a.Analyzer.Name, - a.Analyzer.Doc, - []*analysis.Analyzer{a.Analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - err := a.Compile() - if err != nil { - lintCtx.Log.Errorf("create analyzer: %v", err) - } - }).WithLoadMode(goanalysis.LoadModeSyntax) + analyzer := depguard.NewUncompiledAnalyzer(&conf) + + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + err := analyzer.Compile() + if err != nil { + lintCtx.Log.Errorf("create analyzer: %v", err) + } + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dogsled/dogsled.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dogsled/dogsled.go index 23d48ba57..5516d2b39 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dogsled/dogsled.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dogsled/dogsled.go @@ -11,24 +11,17 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "dogsled" - func New(settings *config.DogsledSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - return run(pass, settings.MaxBlankIdentifiers) - }, - Requires: []*analysis.Analyzer{inspect.Analyzer}, - } - - return goanalysis.NewLinter( - linterName, - "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "dogsled", + Doc: "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())", + Run: func(pass *analysis.Pass) (any, error) { + return run(pass, settings.MaxBlankIdentifiers) + }, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func run(pass *analysis.Pass, maxBlanks int) (any, error) { @@ -37,18 +30,14 @@ func run(pass *analysis.Pass, maxBlanks int) (any, error) { return nil, nil } - nodeFilter := []ast.Node{ - (*ast.FuncDecl)(nil), - } - - insp.Preorder(nodeFilter, func(node ast.Node) { + for node := range insp.PreorderSeq((*ast.FuncDecl)(nil)) { funcDecl, ok := node.(*ast.FuncDecl) if !ok { - return + continue } if funcDecl.Body == nil { - return + continue } for _, expr := range funcDecl.Body.List { @@ -72,7 +61,7 @@ func run(pass *analysis.Pass, maxBlanks int) (any, error) { pass.Reportf(assgnStmt.Pos(), "declaration has %v blank identifiers", numBlank) } } - }) + } return nil, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupl/dupl.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupl/dupl.go index 993bfd6f2..0b6b3a162 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupl/dupl.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupl/dupl.go @@ -20,40 +20,36 @@ const linterName = "dupl" func New(settings *config.DuplSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := runDupl(pass, settings) - if err != nil { - return nil, err - } - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } + var resIssues []*goanalysis.Issue + + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Detects duplicate fragments of code.", + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runDupl(pass, settings) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Detects duplicate fragments of code.", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } -func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.Issue, error) { +func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]*goanalysis.Issue, error) { issues, err := duplAPI.Run(internal.GetGoFileNames(pass), settings.Threshold) if err != nil { return nil, err @@ -63,7 +59,7 @@ func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.I return nil, nil } - res := make([]goanalysis.Issue, 0, len(issues)) + res := make([]*goanalysis.Issue, 0, len(issues)) for _, i := range issues { toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "") @@ -74,7 +70,7 @@ func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.I dupl := fmt.Sprintf("%s:%d-%d", toFilename, i.To.LineStart(), i.To.LineEnd()) text := fmt.Sprintf("%d-%d lines are duplicate of %s", i.From.LineStart(), i.From.LineEnd(), - internal.FormatCode(dupl, nil)) + internal.FormatCode(dupl)) res = append(res, goanalysis.NewIssue(&result.Issue{ Pos: token.Position{ diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go index 62851475f..0308534e3 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go @@ -4,27 +4,25 @@ import ( "strings" "github.com/Abirdcfly/dupword" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.DupWordSettings) *goanalysis.Linter { - a := dupword.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ - "keyword": strings.Join(settings.Keywords, ","), - "ignore": strings.Join(settings.Ignore, ","), + cfg = map[string]any{ + "keyword": strings.Join(settings.Keywords, ","), + "ignore": strings.Join(settings.Ignore, ","), + "comments-only": settings.CommentsOnly, } } - return goanalysis.NewLinter( - a.Name, - "checks for duplicate words in the source code", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(dupword.NewAnalyzer()). + WithDesc("Checks for duplicate words in the source code"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck/durationcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck/durationcheck.go index d3e74231f..b6723fa12 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck/durationcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck/durationcheck.go @@ -2,18 +2,12 @@ package durationcheck import ( "github.com/charithe/durationcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := durationcheck.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(durationcheck.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go new file mode 100644 index 000000000..ba4c06eb7 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go @@ -0,0 +1,24 @@ +package embeddedstructfieldcheck + +import ( + "github.com/manuelarte/embeddedstructfieldcheck/analyzer" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New(settings *config.EmbeddedStructFieldCheckSettings) *goanalysis.Linter { + var cfg map[string]any + + if settings != nil { + cfg = map[string]any{ + analyzer.ForbidMutexCheck: settings.ForbidMutex, + analyzer.EmptyLineCheck: settings.EmptyLine, + } + } + + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/err113/err113.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/err113/err113.go index 78ef99d6a..d3b3a4c1c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/err113/err113.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/err113/err113.go @@ -2,18 +2,13 @@ package err113 import ( "github.com/Djarvur/go-err113" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := err113.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - "Go linter to check the errors handling expressions", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(err113.NewAnalyzer()). + WithDesc("Check errors handling expressions"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck/errcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck/errcheck.go index 56d00c350..6bd473845 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck/errcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck/errcheck.go @@ -21,43 +21,42 @@ const linterName = "errcheck" func New(settings *config.ErrcheckSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue analyzer := &analysis.Analyzer{ Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, + Doc: "errcheck is a program for checking for unchecked errors in Go code. " + + "These unchecked errors can be critical bugs in some cases", + Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "errcheck is a program for checking for unchecked errors in Go code. "+ - "These unchecked errors can be critical bugs in some cases", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - checker := getChecker(settings) - checker.Tags = lintCtx.Cfg.Run.BuildTags + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + checker := getChecker(settings) + checker.Tags = lintCtx.Cfg.Run.BuildTags - analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues := runErrCheck(lintCtx, pass, checker) + analyzer.Run = func(pass *analysis.Pass) (any, error) { + issues := runErrCheck(pass, checker, settings.Verbose) - if len(issues) == 0 { - return nil, nil - } + if len(issues) == 0 { + return nil, nil + } - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runErrCheck(lintCtx *linter.Context, pass *analysis.Pass, checker *errcheck.Checker) []goanalysis.Issue { +func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) []*goanalysis.Issue { pkg := &packages.Package{ Fset: pass.Fset, Syntax: pass.Files, @@ -70,15 +69,18 @@ func runErrCheck(lintCtx *linter.Context, pass *analysis.Pass, checker *errcheck return nil } - issues := make([]goanalysis.Issue, len(lintIssues.UncheckedErrors)) + issues := make([]*goanalysis.Issue, len(lintIssues.UncheckedErrors)) for i, err := range lintIssues.UncheckedErrors { text := "Error return value is not checked" if err.FuncName != "" { code := cmp.Or(err.SelectorName, err.FuncName) + if verbose { + code = err.FuncName + } - text = fmt.Sprintf("Error return value of %s is not checked", internal.FormatCode(code, lintCtx.Cfg)) + text = fmt.Sprintf("Error return value of %s is not checked", internal.FormatCode(code)) } issues[i] = goanalysis.NewIssue( diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson/errchkjson.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson/errchkjson.go index a705406e4..02510ab49 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson/errchkjson.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson/errchkjson.go @@ -2,30 +2,25 @@ package errchkjson import ( "github.com/breml/errchkjson" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ErrChkJSONSettings) *goanalysis.Linter { - a := errchkjson.NewAnalyzer() - - cfg := map[string]map[string]any{} - cfg[a.Name] = map[string]any{ + cfg := map[string]any{ "omit-safe": true, } + if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "omit-safe": !settings.CheckErrorFreeEncoding, "report-no-exported": settings.ReportNoExported, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(errchkjson.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errname/errname.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errname/errname.go index 36d6f1235..a66f3211f 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errname/errname.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errname/errname.go @@ -2,18 +2,12 @@ package errname import ( "github.com/Antonboom/errname/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.New() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go index 7560bc0af..f32217796 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go @@ -2,7 +2,6 @@ package errorlint import ( "github.com/polyfloyd/go-errorlint/errorlint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -23,12 +22,10 @@ func New(settings *config.ErrorLintSettings) *goanalysis.Linter { } } - a := errorlint.NewAnalyzer(opts...) - - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "errorf": settings.Errorf, "errorf-multi": settings.ErrorfMulti, "asserts": settings.Asserts, @@ -36,13 +33,11 @@ func New(settings *config.ErrorLintSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - "errorlint is a linter for that can be used to find code "+ - "that will cause problems with the error wrapping scheme introduced in Go 1.13.", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(errorlint.NewAnalyzer(opts...)). + WithDesc("Find code that can cause problems with the error wrapping scheme introduced in Go 1.13."). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func toAllowPairs(data []config.ErrorLintAllowPair) []errorlint.AllowPair { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustive/exhaustive.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustive/exhaustive.go index be77e54a4..ec240739d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustive/exhaustive.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustive/exhaustive.go @@ -2,37 +2,31 @@ package exhaustive import ( "github.com/nishanths/exhaustive" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ExhaustiveSettings) *goanalysis.Linter { - a := exhaustive.Analyzer + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - exhaustive.CheckFlag: settings.Check, - exhaustive.DefaultSignifiesExhaustiveFlag: settings.DefaultSignifiesExhaustive, - exhaustive.IgnoreEnumMembersFlag: settings.IgnoreEnumMembers, - exhaustive.IgnoreEnumTypesFlag: settings.IgnoreEnumTypes, - exhaustive.PackageScopeOnlyFlag: settings.PackageScopeOnly, - exhaustive.ExplicitExhaustiveMapFlag: settings.ExplicitExhaustiveMap, - exhaustive.ExplicitExhaustiveSwitchFlag: settings.ExplicitExhaustiveSwitch, - exhaustive.DefaultCaseRequiredFlag: settings.DefaultCaseRequired, - // Should be managed with `linters.exclusions.generated`. - exhaustive.CheckGeneratedFlag: true, - }, + cfg = map[string]any{ + exhaustive.CheckFlag: settings.Check, + exhaustive.DefaultSignifiesExhaustiveFlag: settings.DefaultSignifiesExhaustive, + exhaustive.IgnoreEnumMembersFlag: settings.IgnoreEnumMembers, + exhaustive.IgnoreEnumTypesFlag: settings.IgnoreEnumTypes, + exhaustive.PackageScopeOnlyFlag: settings.PackageScopeOnly, + exhaustive.ExplicitExhaustiveMapFlag: settings.ExplicitExhaustiveMap, + exhaustive.ExplicitExhaustiveSwitchFlag: settings.ExplicitExhaustiveSwitch, + exhaustive.DefaultCaseRequiredFlag: settings.DefaultCaseRequired, + // Should be managed with `linters.exclusions.generated`. + exhaustive.CheckGeneratedFlag: true, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(exhaustive.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct.go index 9b7421299..01136aadc 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct.go @@ -1,8 +1,7 @@ package exhaustruct import ( - "github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer" - "golang.org/x/tools/go/analysis" + exhaustruct "dev.gaijin.team/go/exhaustruct/v4/analyzer" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,21 +9,22 @@ import ( ) func New(settings *config.ExhaustructSettings) *goanalysis.Linter { - var include, exclude []string + cfg := exhaustruct.Config{} if settings != nil { - include = settings.Include - exclude = settings.Exclude + cfg.IncludeRx = settings.Include + cfg.ExcludeRx = settings.Exclude + cfg.AllowEmpty = settings.AllowEmpty + cfg.AllowEmptyRx = settings.AllowEmptyRx + cfg.AllowEmptyReturns = settings.AllowEmptyReturns + cfg.AllowEmptyDeclarations = settings.AllowEmptyDeclarations } - a, err := analyzer.NewAnalyzer(include, exclude) + analyzer, err := exhaustruct.NewAnalyzer(cfg) if err != nil { internal.LinterLogger.Fatalf("exhaustruct configuration: %v", err) } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exptostd/exptostd.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exptostd/exptostd.go index 731a4a0cc..dbd78dce9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exptostd/exptostd.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exptostd/exptostd.go @@ -2,18 +2,12 @@ package exptostd import ( "github.com/ldez/exptostd" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := exptostd.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(exptostd.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go index e0506259b..58933c660 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go @@ -2,27 +2,22 @@ package fatcontext import ( "go.augendre.info/fatcontext/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.FatcontextSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ analyzer.FlagCheckStructPointers: settings.CheckStructPointers, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forbidigo/forbidigo.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forbidigo/forbidigo.go index 45f9088fa..1473b4d6e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forbidigo/forbidigo.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forbidigo/forbidigo.go @@ -3,9 +3,9 @@ package forbidigo import ( "fmt" - "github.com/ashanbrown/forbidigo/forbidigo" + "github.com/ashanbrown/forbidigo/v2/forbidigo" + "go.yaml.in/yaml/v3" "golang.org/x/tools/go/analysis" - "gopkg.in/yaml.v3" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -15,28 +15,23 @@ import ( const linterName = "forbidigo" func New(settings *config.ForbidigoSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runForbidigo(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - // Without AnalyzeTypes, LoadModeSyntax is enough. // But we cannot make this depend on the settings and have to mirror the mode chosen in GetAllSupportedLinterConfigs, - // therefore we have to use LoadModeTypesInfo in all cases. - return goanalysis.NewLinter( - linterName, - "Forbids identifiers", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + // therefore, we have to use LoadModeTypesInfo in all cases. + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Forbids identifiers", + Run: func(pass *analysis.Pass) (any, error) { + err := runForbidigo(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runForbidigo(pass *analysis.Pass, settings *config.ForbidigoSettings) error { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forcetypeassert/forcetypeassert.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forcetypeassert/forcetypeassert.go index e82355380..19a0e3450 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forcetypeassert/forcetypeassert.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/forcetypeassert/forcetypeassert.go @@ -2,18 +2,13 @@ package forcetypeassert import ( "github.com/gostaticanalysis/forcetypeassert" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := forcetypeassert.Analyzer - - return goanalysis.NewLinter( - a.Name, - "finds forced type assertions", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(forcetypeassert.Analyzer). + WithDesc("Find forced type assertions"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go index 7b8e9689e..06400753e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go @@ -2,28 +2,24 @@ package funcorder import ( "github.com/manuelarte/funcorder/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.FuncOrderSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ analyzer.ConstructorCheckName: settings.Constructor, analyzer.StructMethodCheckName: settings.StructMethod, + analyzer.AlphabeticalCheckName: settings.Alphabetical, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funlen/funlen.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funlen/funlen.go index 541d4fd36..6e0f93b51 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funlen/funlen.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funlen/funlen.go @@ -2,7 +2,6 @@ package funlen import ( "github.com/ultraware/funlen" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -22,12 +21,7 @@ func New(settings *config.FunlenSettings) *goanalysis.Linter { cfg.ignoreComments = settings.IgnoreComments } - a := funlen.NewAnalyzer(cfg.lineLimit, cfg.stmtLimit, cfg.ignoreComments) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(funlen.NewAnalyzer(cfg.lineLimit, cfg.stmtLimit, cfg.ignoreComments)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gci/gci.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gci/gci.go index 627a4e684..4357a3b15 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gci/gci.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gci/gci.go @@ -1,8 +1,6 @@ package gci import ( - "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/goformatters" @@ -18,16 +16,13 @@ func New(settings *config.GciSettings) *goanalysis.Linter { internal.LinterLogger.Fatalf("%s: create analyzer: %v", linterName, err) } - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if code and import statements are formatted, with additional rules.", - formatter, - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(linterName), + "Check if code and import statements are formatted, with additional rules.", + formatter, + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ginkgolinter/ginkgolinter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ginkgolinter/ginkgolinter.go index f4521cdaf..99b9eb474 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ginkgolinter/ginkgolinter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ginkgolinter/ginkgolinter.go @@ -2,39 +2,36 @@ package ginkgolinter import ( "github.com/nunnatsa/ginkgolinter" - "github.com/nunnatsa/ginkgolinter/types" - "golang.org/x/tools/go/analysis" + glconfig "github.com/nunnatsa/ginkgolinter/config" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.GinkgoLinterSettings) *goanalysis.Linter { - cfg := &types.Config{} + cfg := &glconfig.Config{} if settings != nil { - cfg = &types.Config{ - SuppressLen: settings.SuppressLenAssertion, - SuppressNil: settings.SuppressNilAssertion, - SuppressErr: settings.SuppressErrAssertion, - SuppressCompare: settings.SuppressCompareAssertion, - SuppressAsync: settings.SuppressAsyncAssertion, - ForbidFocus: settings.ForbidFocusContainer, - SuppressTypeCompare: settings.SuppressTypeCompareWarning, - AllowHaveLen0: settings.AllowHaveLenZero, - ForceExpectTo: settings.ForceExpectTo, - ValidateAsyncIntervals: settings.ValidateAsyncIntervals, - ForbidSpecPollution: settings.ForbidSpecPollution, - ForceSucceedForFuncs: settings.ForceSucceedForFuncs, + cfg = &glconfig.Config{ + SuppressLen: settings.SuppressLenAssertion, + SuppressNil: settings.SuppressNilAssertion, + SuppressErr: settings.SuppressErrAssertion, + SuppressCompare: settings.SuppressCompareAssertion, + SuppressAsync: settings.SuppressAsyncAssertion, + ForbidFocus: settings.ForbidFocusContainer, + SuppressTypeCompare: settings.SuppressTypeCompareWarning, + AllowHaveLen0: settings.AllowHaveLenZero, + ForceExpectTo: settings.ForceExpectTo, + ValidateAsyncIntervals: settings.ValidateAsyncIntervals, + ForbidSpecPollution: settings.ForbidSpecPollution, + ForceSucceedForFuncs: settings.ForceSucceedForFuncs, + ForceAssertionDescription: settings.ForceAssertionDescription, + ForeToNot: settings.ForeToNot, } } - a := ginkgolinter.NewAnalyzerWithConfig(cfg) - - return goanalysis.NewLinter( - a.Name, - "enforces standards of using ginkgo and gomega", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(ginkgolinter.NewAnalyzerWithConfig(cfg)). + WithDesc("enforces standards of using ginkgo and gomega"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go index 97534848d..71f4be8c4 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go @@ -2,18 +2,12 @@ package gocheckcompilerdirectives import ( "4d63.com/gocheckcompilerdirectives/checkcompilerdirectives" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := checkcompilerdirectives.Analyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(checkcompilerdirectives.Analyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoglobals/gochecknoglobals.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoglobals/gochecknoglobals.go index 8d850a2de..2fd3f3c3b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoglobals/gochecknoglobals.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoglobals/gochecknoglobals.go @@ -2,18 +2,13 @@ package gochecknoglobals import ( "4d63.com/gochecknoglobals/checknoglobals" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := checknoglobals.Analyzer() - - return goanalysis.NewLinter( - a.Name, - "Check that no global variables exist.", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(checknoglobals.Analyzer()). + WithDesc("Check that no global variables exist."). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoinits/gochecknoinits.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoinits/gochecknoinits.go index b5fa6f0d4..161db84ee 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoinits/gochecknoinits.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecknoinits/gochecknoinits.go @@ -11,22 +11,15 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "gochecknoinits" - func New() *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: run, - Requires: []*analysis.Analyzer{inspect.Analyzer}, - } - - return goanalysis.NewLinter( - linterName, - "Checks that no init functions are present in Go code", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "gochecknoinits", + Doc: "Checks that no init functions are present in Go code", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func run(pass *analysis.Pass) (any, error) { @@ -35,21 +28,17 @@ func run(pass *analysis.Pass) (any, error) { return nil, nil } - nodeFilter := []ast.Node{ - (*ast.FuncDecl)(nil), - } - - insp.Preorder(nodeFilter, func(decl ast.Node) { - funcDecl, ok := decl.(*ast.FuncDecl) + for node := range insp.PreorderSeq((*ast.FuncDecl)(nil)) { + funcDecl, ok := node.(*ast.FuncDecl) if !ok { - return + continue } fnName := funcDecl.Name.Name if fnName == "init" && funcDecl.Recv.NumFields() == 0 { - pass.Reportf(funcDecl.Pos(), "don't use %s function", internal.FormatCode(fnName, nil)) + pass.Reportf(funcDecl.Pos(), "don't use %s function", internal.FormatCode(fnName)) } - }) + } return nil, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecksumtype/gochecksumtype.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecksumtype/gochecksumtype.go index 78cbd574d..825975f14 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecksumtype/gochecksumtype.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gochecksumtype/gochecksumtype.go @@ -18,41 +18,37 @@ const linterName = "gochecksumtype" func New(settings *config.GoChecksumTypeSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue + + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: `Run exhaustiveness checks on Go "sum types"`, + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runGoCheckSumType(pass, settings) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := runGoCheckSumType(pass, settings) - if err != nil { - return nil, err - } - - if len(issues) == 0 { return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - `Run exhaustiveness checks on Go "sum types"`, - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + }, + }). + WithIssuesReporter(func(_ *linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoCheckSumType(pass *analysis.Pass, settings *config.GoChecksumTypeSettings) ([]goanalysis.Issue, error) { - var resIssues []goanalysis.Issue +func runGoCheckSumType(pass *analysis.Pass, settings *config.GoChecksumTypeSettings) ([]*goanalysis.Issue, error) { + var resIssues []*goanalysis.Issue pkg := &packages.Package{ Fset: pass.Fset, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocognit/gocognit.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocognit/gocognit.go index 689a70a12..b17912c0a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocognit/gocognit.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocognit/gocognit.go @@ -19,37 +19,33 @@ const linterName = "gocognit" func New(settings *config.GocognitSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runGocognit(pass, settings) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Computes and checks the cognitive complexity of functions", + Run: func(pass *analysis.Pass) (any, error) { + issues := runGocognit(pass, settings) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Computes and checks the cognitive complexity of functions", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } -func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goanalysis.Issue { +func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []*goanalysis.Issue { var stats []gocognit.Stat for _, f := range pass.Files { stats = gocognit.ComplexityStats(f, pass.Fset, stats) @@ -62,7 +58,7 @@ func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goana return stats[i].Complexity > stats[j].Complexity }) - issues := make([]goanalysis.Issue, 0, len(stats)) + issues := make([]*goanalysis.Issue, 0, len(stats)) for _, s := range stats { if s.Complexity <= settings.MinComplexity { break // Break as the stats is already sorted from greatest to least @@ -71,7 +67,7 @@ func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goana issues = append(issues, goanalysis.NewIssue(&result.Issue{ Pos: s.Pos, Text: fmt.Sprintf("cognitive complexity %d of func %s is high (> %d)", - s.Complexity, internal.FormatCode(s.FuncName, nil), settings.MinComplexity), + s.Complexity, internal.FormatCode(s.FuncName), settings.MinComplexity), FromLinter: linterName, }, pass)) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go index f3af64625..b58d860c6 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go @@ -18,40 +18,36 @@ const linterName = "goconst" func New(settings *config.GoConstSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := runGoconst(pass, settings) - if err != nil { - return nil, err - } + var resIssues []*goanalysis.Issue + + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Finds repeated strings that could be replaced by a constant", + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runGoconst(pass, settings) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - if len(issues) == 0 { return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Finds repeated strings that could be replaced by a constant", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanalysis.Issue, error) { +func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goanalysis.Issue, error) { cfg := goconstAPI.Config{ IgnoreStrings: settings.IgnoreStringValues, MatchWithConstants: settings.MatchWithConstants, @@ -81,7 +77,7 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanal return nil, nil } - res := make([]goanalysis.Issue, 0, len(lintIssues)) + res := make([]*goanalysis.Issue, 0, len(lintIssues)) for i := range lintIssues { issue := &lintIssues[i] @@ -89,17 +85,17 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanal switch { case issue.OccurrencesCount > 0: - text = fmt.Sprintf("string %s has %d occurrences", internal.FormatCode(issue.Str, nil), issue.OccurrencesCount) + text = fmt.Sprintf("string %s has %d occurrences", internal.FormatCode(issue.Str), issue.OccurrencesCount) if issue.MatchingConst == "" { text += ", make it a constant" } else { - text += fmt.Sprintf(", but such constant %s already exists", internal.FormatCode(issue.MatchingConst, nil)) + text += fmt.Sprintf(", but such constant %s already exists", internal.FormatCode(issue.MatchingConst)) } case issue.DuplicateConst != "": text = fmt.Sprintf("This constant is a duplicate of %s at %s", - internal.FormatCode(issue.DuplicateConst, nil), + internal.FormatCode(issue.DuplicateConst), issue.DuplicatePos.String()) default: diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocritic/gocritic.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocritic/gocritic.go index 486303dab..cd7337590 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocritic/gocritic.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocritic/gocritic.go @@ -33,27 +33,21 @@ func New(settings *config.GoCriticSettings, replacer *strings.Replacer) *goanaly sizes: types.SizesFor("gc", runtime.GOARCH), } - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := wrapper.run(pass) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - `Provides diagnostics that check for bugs, performance and style issues. + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: `Provides diagnostics that check for bugs, performance and style issues. Extensible without recompilation through dynamic rules. Dynamic rules are written declaratively with AST patterns, filters, report message and optional suggestion.`, - []*analysis.Analyzer{analyzer}, - nil, - ). + Run: func(pass *analysis.Pass) (any, error) { + err := wrapper.run(pass) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). WithContextSetter(func(context *linter.Context) { wrapper.init(context.Log, settings, replacer) }). diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocyclo/gocyclo.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocyclo/gocyclo.go index 05691695d..de0374607 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocyclo/gocyclo.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gocyclo/gocyclo.go @@ -18,37 +18,33 @@ const linterName = "gocyclo" func New(settings *config.GoCycloSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runGoCyclo(pass, settings) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Computes and checks the cyclomatic complexity of functions", + Run: func(pass *analysis.Pass) (any, error) { + issues := runGoCyclo(pass, settings) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Computes and checks the cyclomatic complexity of functions", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } -func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanalysis.Issue { +func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []*goanalysis.Issue { var stats gocyclo.Stats for _, f := range pass.Files { stats = gocyclo.AnalyzeASTFile(f, pass.Fset, stats) @@ -59,11 +55,11 @@ func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanaly stats = stats.SortAndFilter(-1, settings.MinComplexity) - issues := make([]goanalysis.Issue, 0, len(stats)) + issues := make([]*goanalysis.Issue, 0, len(stats)) for _, s := range stats { text := fmt.Sprintf("cyclomatic complexity %d of func %s is high (> %d)", - s.Complexity, internal.FormatCode(s.FuncName, nil), settings.MinComplexity) + s.Complexity, internal.FormatCode(s.FuncName), settings.MinComplexity) issues = append(issues, goanalysis.NewIssue(&result.Issue{ Pos: s.Pos, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go new file mode 100644 index 000000000..235909217 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go @@ -0,0 +1,109 @@ +package godoclint + +import ( + "errors" + "fmt" + "slices" + + glcompose "github.com/godoc-lint/godoc-lint/pkg/compose" + glconfig "github.com/godoc-lint/godoc-lint/pkg/config" + "github.com/godoc-lint/godoc-lint/pkg/model" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" +) + +func New(settings *config.GodoclintSettings) *goanalysis.Linter { + var pcfg glconfig.PlainConfig + + if settings != nil { + err := checkSettings(settings) + if err != nil { + internal.LinterLogger.Fatalf("godoclint: %v", err) + } + + // The following options are explicitly ignored: they must be handled globally with exclusions or nolint directives. + // - Include + // - Exclude + + // The following options are explicitly ignored: these options cannot work as expected because the global configuration about tests. + // - Options.MaxLenIncludeTests + // - Options.PkgDocIncludeTests + // - Options.SinglePkgDocIncludeTests + // - Options.RequirePkgDocIncludeTests + // - Options.RequireDocIncludeTests + // - Options.StartWithNameIncludeTests + // - Options.NoUnusedLinkIncludeTests + + pcfg = glconfig.PlainConfig{ + Default: settings.Default, + Enable: settings.Enable, + Disable: settings.Disable, + Options: &glconfig.PlainRuleOptions{ + MaxLenLength: settings.Options.MaxLen.Length, + MaxLenIncludeTests: pointer(true), + PkgDocIncludeTests: pointer(false), + SinglePkgDocIncludeTests: pointer(true), + RequirePkgDocIncludeTests: pointer(false), + RequireDocIncludeTests: pointer(true), + RequireDocIgnoreExported: settings.Options.RequireDoc.IgnoreExported, + RequireDocIgnoreUnexported: settings.Options.RequireDoc.IgnoreUnexported, + StartWithNameIncludeTests: pointer(false), + StartWithNameIncludeUnexported: settings.Options.StartWithName.IncludeUnexported, + NoUnusedLinkIncludeTests: pointer(true), + }, + } + } + + composition := glcompose.Compose(glcompose.CompositionConfig{ + BaseDirPlainConfig: &pcfg, + ExitFunc: func(_ int, err error) { + internal.LinterLogger.Errorf("godoclint: %v", err) + }, + }) + + return goanalysis. + NewLinterFromAnalyzer(composition.Analyzer.GetAnalyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) +} + +func checkSettings(settings *config.GodoclintSettings) error { + switch deref(settings.Default) { + case string(model.DefaultSetAll): + if len(settings.Enable) > 0 { + return errors.New("cannot use 'enable' with 'default=all'") + } + + case string(model.DefaultSetNone): + if len(settings.Disable) > 0 { + return errors.New("cannot use 'disable' with 'default=none'") + } + + default: + for _, rule := range settings.Enable { + if slices.Contains(settings.Disable, rule) { + return fmt.Errorf("a rule cannot be enabled and disabled at the same time: '%s'", rule) + } + } + + for _, rule := range settings.Disable { + if slices.Contains(settings.Enable, rule) { + return fmt.Errorf("a rule cannot be enabled and disabled at the same time: '%s'", rule) + } + } + } + + return nil +} + +func pointer[T any](v T) *T { return &v } + +func deref[T any](v *T) T { + if v == nil { + var zero T + return zero + } + + return *v +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godot/godot.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godot/godot.go index 04e86211d..e83495128 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godot/godot.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godot/godot.go @@ -10,8 +10,6 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "godot" - func New(settings *config.GodotSettings) *goanalysis.Linter { var dotSettings godot.Settings @@ -26,25 +24,20 @@ func New(settings *config.GodotSettings) *goanalysis.Linter { dotSettings.Scope = cmp.Or(dotSettings.Scope, godot.DeclScope) - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runGodot(pass, dotSettings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Check if comments end in a period", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "godot", + Doc: "Check if comments end in a period", + Run: func(pass *analysis.Pass) (any, error) { + err := runGodot(pass, dotSettings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runGodot(pass *analysis.Pass, settings godot.Settings) error { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godox/godox.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godox/godox.go index e734c691b..e05fc123a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godox/godox.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godox/godox.go @@ -11,23 +11,16 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "godox" - func New(settings *config.GodoxSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - return run(pass, settings), nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Detects usage of FIXME, TODO and other keywords inside comments", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "godox", + Doc: "Detects usage of FIXME, TODO and other keywords inside comments", + Run: func(pass *analysis.Pass) (any, error) { + return run(pass, settings), nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func run(pass *analysis.Pass, settings *config.GodoxSettings) error { @@ -51,9 +44,14 @@ func run(pass *analysis.Pass, settings *config.GodoxSettings) error { ft := pass.Fset.File(file.Pos()) for _, i := range messages { + msg := strings.TrimRight(i.Message, "\n") + + // https://github.com/matoous/godox/blob/1d6ac9d899726279072e1c4d2b10f1eb52f22878/godox.go#L56 + index := strings.Index(msg, "Line contains") + pass.Report(analysis.Diagnostic{ Pos: ft.LineStart(goanalysis.AdjustPos(i.Pos.Line, nonAdjPosition.Line, position.Line)) + token.Pos(i.Pos.Column), - Message: strings.TrimRight(i.Message, "\n"), + Message: msg[index:], }) } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofmt/gofmt.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofmt/gofmt.go index 63b690018..04de51efc 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofmt/gofmt.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofmt/gofmt.go @@ -1,8 +1,6 @@ package gofmt import ( - "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/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "gofmt" - func New(settings *config.GoFmtSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if the code is formatted according to 'gofmt' command.", - gofmtbase.New(settings), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(gofmtbase.Name), + "Check if the code is formatted according to 'gofmt' command.", + gofmtbase.New(settings), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go index d799be7a3..1ee7c833a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go @@ -1,8 +1,6 @@ package gofumpt import ( - "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/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "gofumpt" - func New(settings *config.GoFumptSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if code and import statements are formatted, with additional rules.", - gofumptbase.New(settings, settings.LangVersion), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(gofumptbase.Name), + "Check if code and import statements are formatted, with additional rules.", + gofumptbase.New(settings, settings.LangVersion), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goheader/goheader.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goheader/goheader.go index e03d3277d..0634dbd42 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goheader/goheader.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goheader/goheader.go @@ -23,25 +23,20 @@ func New(settings *config.GoHeaderSettings, replacer *strings.Replacer) *goanaly } } - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runGoHeader(pass, conf) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Checks if file header matches to pattern", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Check if file header matches to pattern", + Run: func(pass *analysis.Pass) (any, error) { + err := runGoHeader(pass, conf) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runGoHeader(pass *analysis.Pass, conf *goheader.Configuration) error { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goimports/goimports.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goimports/goimports.go index 3aa8cde56..b3b9b5800 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goimports/goimports.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goimports/goimports.go @@ -1,8 +1,6 @@ package goimports import ( - "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/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "goimports" - func New(settings *config.GoImportsSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if the code and import statements are formatted according to the 'goimports' command.", - goimportsbase.New(settings), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(goimportsbase.Name), + "Checks if the code and import statements are formatted according to the 'goimports' command.", + goimportsbase.New(settings), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/golines/golines.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/golines/golines.go index 0b3acc53b..0a32971de 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/golines/golines.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/golines/golines.go @@ -1,8 +1,6 @@ package golines import ( - "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/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "golines" - func New(settings *config.GoLinesSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if code is formatted, and fixes long lines", - golinesbase.New(settings), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(golinesbase.Name), + "Checks if code is formatted, and fixes long lines", + golinesbase.New(settings), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go index 86f94e256..dd6656fb6 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go @@ -17,7 +17,7 @@ import ( const linterName = "gomoddirectives" func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter { - var issues []goanalysis.Issue + var issues []*goanalysis.Issue var once sync.Once var opts gomoddirectives.Options @@ -50,38 +50,37 @@ func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter { } analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, + Name: linterName, + Doc: "Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.", Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (any, error) { - once.Do(func() { - results, err := gomoddirectives.AnalyzePass(pass, opts) - if err != nil { - lintCtx.Log.Warnf("running %s failed: %s: "+ - "if you are not using go modules it is suggested to disable this linter", linterName, err) - return - } + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { + once.Do(func() { + results, err := gomoddirectives.AnalyzePass(pass, opts) + if err != nil { + lintCtx.Log.Warnf("running %s failed: %s: "+ + "if you are not using go modules it is suggested to disable this linter", linterName, err) + return + } - for _, p := range results { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - FromLinter: linterName, - Pos: p.Start, - Text: p.Reason, - }, pass)) - } - }) + for _, p := range results { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: linterName, + Pos: p.Start, + Text: p.Reason, + }, pass)) + } + }) - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return issues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return issues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go index e38a6c9b9..7d16f57b3 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go @@ -13,15 +13,10 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -const ( - name = "gomodguard" - desc = "Allow and block list linter for direct Go module dependencies. " + - "This is different from depguard where there are different block " + - "types for example version constraints and module recommendations." -) +const linterName = "gomodguard" func New(settings *config.GoModGuardSettings) *goanalysis.Linter { - var issues []goanalysis.Issue + var issues []*goanalysis.Issue var mu sync.Mutex processorCfg := &gomodguard.Configuration{} @@ -54,41 +49,41 @@ func New(settings *config.GoModGuardSettings) *goanalysis.Linter { } analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, + Name: linterName, + 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.NewLinter( - name, - desc, - []*analysis.Analyzer{analyzer}, - nil, - ).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 - } + 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)) + analyzer.Run = func(pass *analysis.Pass) (any, error) { + gomodguardIssues := processor.ProcessFiles(internal.GetGoFileNames(pass)) - mu.Lock() - defer mu.Unlock() + mu.Lock() + defer mu.Unlock() - for _, gomodguardIssue := range gomodguardIssues { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - FromLinter: name, - Pos: gomodguardIssue.Position, - Text: gomodguardIssue.Reason, - }, pass)) - } + for _, gomodguardIssue := range gomodguardIssues { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: linterName, + Pos: gomodguardIssue.Position, + Text: gomodguardIssue.Reason, + }, pass)) + } - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return issues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return issues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goprintffuncname/goprintffuncname.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goprintffuncname/goprintffuncname.go index b14363478..a56dce8e0 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goprintffuncname/goprintffuncname.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goprintffuncname/goprintffuncname.go @@ -2,18 +2,12 @@ package goprintffuncname import ( "github.com/golangci/go-printf-func-name/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosec/gosec.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosec/gosec.go index 95b445e87..66d229295 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosec/gosec.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosec/gosec.go @@ -26,7 +26,7 @@ const linterName = "gosec" func New(settings *config.GoSecSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue conf := gosec.NewConfig() @@ -50,37 +50,36 @@ func New(settings *config.GoSecSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, + Doc: "Inspects source code for security problems", Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "Inspects source code for security problems", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (any, error) { - // The `gosecAnalyzer` is here because of concurrency issue. - gosecAnalyzer := gosec.NewAnalyzer(conf, true, false, false, settings.Concurrency, logger) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { + // The `gosecAnalyzer` is here because of concurrency issue. + gosecAnalyzer := gosec.NewAnalyzer(conf, true, false, false, settings.Concurrency, logger) - gosecAnalyzer.LoadRules(ruleDefinitions.RulesInfo()) - gosecAnalyzer.LoadAnalyzers(analyzerDefinitions.AnalyzersInfo()) + gosecAnalyzer.LoadRules(ruleDefinitions.RulesInfo()) + gosecAnalyzer.LoadAnalyzers(analyzerDefinitions.AnalyzersInfo()) - issues := runGoSec(lintCtx, pass, settings, gosecAnalyzer) + issues := runGoSec(lintCtx, pass, settings, gosecAnalyzer) - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoSecSettings, analyzer *gosec.Analyzer) []goanalysis.Issue { +func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoSecSettings, analyzer *gosec.Analyzer) []*goanalysis.Issue { pkg := &packages.Package{ Fset: pass.Fset, Syntax: pass.Files, @@ -108,7 +107,7 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS secIssues = filterIssues(secIssues, severity, confidence) - issues := make([]goanalysis.Issue, 0, len(secIssues)) + issues := make([]*goanalysis.Issue, 0, len(secIssues)) for _, i := range secIssues { text := fmt.Sprintf("%s: %s", i.RuleID, i.What) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosmopolitan/gosmopolitan.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosmopolitan/gosmopolitan.go index 6c574403f..76261abe1 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosmopolitan/gosmopolitan.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gosmopolitan/gosmopolitan.go @@ -4,18 +4,16 @@ import ( "strings" "github.com/xen0n/gosmopolitan" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.GosmopolitanSettings) *goanalysis.Linter { - a := gosmopolitan.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "allowtimelocal": settings.AllowTimeLocal, "escapehatches": strings.Join(settings.EscapeHatches, ","), "watchforscripts": strings.Join(settings.WatchForScripts, ","), @@ -25,10 +23,8 @@ func New(settings *config.GosmopolitanSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(gosmopolitan.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go index 4f3380841..7755e4ec2 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go @@ -24,6 +24,7 @@ import ( "golang.org/x/tools/go/analysis/passes/fieldalignment" "golang.org/x/tools/go/analysis/passes/findcall" "golang.org/x/tools/go/analysis/passes/framepointer" + "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" @@ -78,6 +79,7 @@ var ( fieldalignment.Analyzer, findcall.Analyzer, framepointer.Analyzer, + hostport.Analyzer, httpmux.Analyzer, httpresponse.Analyzer, ifaceassert.Analyzer, @@ -107,7 +109,7 @@ var ( waitgroup.Analyzer, } - // https://github.com/golang/go/blob/go1.23.0/src/cmd/vet/main.go#L55-L87 + // https://github.com/golang/go/blob/go1.25.2/src/cmd/vet/main.go#L57-L91 defaultAnalyzers = []*analysis.Analyzer{ appends.Analyzer, asmdecl.Analyzer, @@ -122,6 +124,7 @@ var ( directive.Analyzer, errorsas.Analyzer, framepointer.Analyzer, + hostport.Analyzer, httpresponse.Analyzer, ifaceassert.Analyzer, loopclosure.Analyzer, @@ -142,6 +145,7 @@ var ( unreachable.Analyzer, unsafeptr.Analyzer, unusedresult.Analyzer, + waitgroup.Analyzer, } ) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/grouper/grouper.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/grouper/grouper.go index 853e2d3e7..ed3601617 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/grouper/grouper.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/grouper/grouper.go @@ -2,18 +2,16 @@ package grouper import ( grouper "github.com/leonklingele/grouper/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.GrouperSettings) *goanalysis.Linter { - a := grouper.New() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "const-require-single-const": settings.ConstRequireSingleConst, "const-require-grouping": settings.ConstRequireGrouping, "import-require-single-import": settings.ImportRequireSingleImport, @@ -24,11 +22,9 @@ func New(settings *config.GrouperSettings) *goanalysis.Linter { "var-require-grouping": settings.VarRequireGrouping, } } - - return goanalysis.NewLinter( - a.Name, - "Analyze expression groups.", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(grouper.New()). + WithDesc("Analyze expression groups."). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go index a3c2816d4..0a4a38abc 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go @@ -5,6 +5,7 @@ import ( "github.com/uudashr/iface/identical" "github.com/uudashr/iface/opaque" + "github.com/uudashr/iface/unexported" "github.com/uudashr/iface/unused" "golang.org/x/tools/go/analysis" @@ -28,9 +29,10 @@ func New(settings *config.IfaceSettings) *goanalysis.Linter { func analyzersFromSettings(settings *config.IfaceSettings) []*analysis.Analyzer { allAnalyzers := map[string]*analysis.Analyzer{ - "identical": identical.Analyzer, - "unused": unused.Analyzer, - "opaque": opaque.Analyzer, + "identical": identical.Analyzer, + "unused": unused.Analyzer, + "opaque": opaque.Analyzer, + "unexported": unexported.Analyzer, } if settings == nil || len(settings.Enable) == 0 { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/importas/importas.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/importas/importas.go index a86db68ce..fa7a54300 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/importas/importas.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/importas/importas.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/julz/importas" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -16,55 +15,53 @@ import ( func New(settings *config.ImportAsSettings) *goanalysis.Linter { analyzer := importas.Analyzer - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - if settings == nil { - return - } - if len(settings.Alias) == 0 { - lintCtx.Log.Infof("importas settings found, but no aliases listed. List aliases under alias: key.") - } - - if err := analyzer.Flags.Set("no-unaliased", strconv.FormatBool(settings.NoUnaliased)); err != nil { - lintCtx.Log.Errorf("failed to parse configuration: %v", err) - } - - if err := analyzer.Flags.Set("no-extra-aliases", strconv.FormatBool(settings.NoExtraAliases)); err != nil { - lintCtx.Log.Errorf("failed to parse configuration: %v", err) - } - - uniqPackages := make(map[string]config.ImportAsAlias) - uniqAliases := make(map[string]config.ImportAsAlias) - for _, a := range settings.Alias { - if a.Pkg == "" { - lintCtx.Log.Errorf("invalid configuration, empty package: pkg=%s alias=%s", a.Pkg, a.Alias) - continue + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + if settings == nil { + return } - - if v, ok := uniqPackages[a.Pkg]; ok { - lintCtx.Log.Errorf("invalid configuration, multiple aliases for the same package: pkg=%s aliases=[%s,%s]", a.Pkg, a.Alias, v.Alias) - } else { - uniqPackages[a.Pkg] = a + if len(settings.Alias) == 0 { + lintCtx.Log.Infof("importas settings found, but no aliases listed. List aliases under alias: key.") } - // Skips the duplication check when: - // - the alias is empty. - // - the alias is a regular expression replacement pattern (ie. contains `$`). - v, ok := uniqAliases[a.Alias] - if ok && a.Alias != "" && !strings.Contains(a.Alias, "$") { - lintCtx.Log.Errorf("invalid configuration, multiple packages with the same alias: alias=%s packages=[%s,%s]", a.Alias, a.Pkg, v.Pkg) - } else { - uniqAliases[a.Alias] = a + if err := analyzer.Flags.Set("no-unaliased", strconv.FormatBool(settings.NoUnaliased)); err != nil { + lintCtx.Log.Errorf("failed to parse configuration: %v", err) } - err := analyzer.Flags.Set("alias", fmt.Sprintf("%s:%s", a.Pkg, a.Alias)) - if err != nil { + if err := analyzer.Flags.Set("no-extra-aliases", strconv.FormatBool(settings.NoExtraAliases)); err != nil { lintCtx.Log.Errorf("failed to parse configuration: %v", err) } - } - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + + uniqPackages := make(map[string]config.ImportAsAlias) + uniqAliases := make(map[string]config.ImportAsAlias) + for _, a := range settings.Alias { + if a.Pkg == "" { + lintCtx.Log.Errorf("invalid configuration, empty package: pkg=%s alias=%s", a.Pkg, a.Alias) + continue + } + + if v, ok := uniqPackages[a.Pkg]; ok { + lintCtx.Log.Errorf("invalid configuration, multiple aliases for the same package: pkg=%s aliases=[%s,%s]", a.Pkg, a.Alias, v.Alias) + } else { + uniqPackages[a.Pkg] = a + } + + // Skips the duplication check when: + // - the alias is empty. + // - the alias is a regular expression replacement pattern (ie. contains `$`). + v, ok := uniqAliases[a.Alias] + if ok && a.Alias != "" && !strings.Contains(a.Alias, "$") { + lintCtx.Log.Errorf("invalid configuration, multiple packages with the same alias: alias=%s packages=[%s,%s]", a.Alias, a.Pkg, v.Pkg) + } else { + uniqAliases[a.Alias] = a + } + + err := analyzer.Flags.Set("alias", fmt.Sprintf("%s:%s", a.Pkg, a.Alias)) + if err != nil { + lintCtx.Log.Errorf("failed to parse configuration: %v", err) + } + } + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/inamedparam/inamedparam.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/inamedparam/inamedparam.go index 0a67c970d..ecb6f7e50 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/inamedparam/inamedparam.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/inamedparam/inamedparam.go @@ -2,29 +2,22 @@ package inamedparam import ( "github.com/macabu/inamedparam" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.INamedParamSettings) *goanalysis.Linter { - a := inamedparam.Analyzer - - var cfg map[string]map[string]any + var cfg map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - "skip-single-param": settings.SkipSingleParam, - }, + cfg = map[string]any{ + "skip-single-param": settings.SkipSingleParam, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(inamedparam.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ineffassign/ineffassign.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ineffassign/ineffassign.go index bbe01ba1f..1df737cbf 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ineffassign/ineffassign.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ineffassign/ineffassign.go @@ -2,18 +2,22 @@ package ineffassign import ( "github.com/gordonklaus/ineffassign/pkg/ineffassign" - "golang.org/x/tools/go/analysis" + "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -func New() *goanalysis.Linter { - a := ineffassign.Analyzer +func New(settings *config.IneffassignSettings) *goanalysis.Linter { + var cfg map[string]any - return goanalysis.NewLinter( - a.Name, - "Detects when assignments to existing variables are not used", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + if settings != nil { + cfg = map[string]any{ + "check-escaping-errors": settings.CheckEscapingErrors, + } + } + + return goanalysis. + NewLinterFromAnalyzer(ineffassign.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/interfacebloat/interfacebloat.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/interfacebloat/interfacebloat.go index fbafb3ac7..f2e187423 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/interfacebloat/interfacebloat.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/interfacebloat/interfacebloat.go @@ -2,28 +2,22 @@ package interfacebloat import ( "github.com/sashamelentyev/interfacebloat/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.InterfaceBloatSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - analyzer.InterfaceMaxMethodsFlag: settings.Max, - }, + cfg = map[string]any{ + analyzer.InterfaceMaxMethodsFlag: settings.Max, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/internal/util.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/internal/util.go index 2e5fb29f9..86137cf66 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/internal/util.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/internal/util.go @@ -6,11 +6,10 @@ import ( "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -func FormatCode(code string, _ *config.Config) string { +func FormatCode(code string) string { if strings.Contains(code, "`") { return code // TODO: properly escape or remove } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/intrange/intrange.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/intrange/intrange.go index c75be9b63..1ff02964c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/intrange/intrange.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/intrange/intrange.go @@ -2,18 +2,12 @@ package intrange import ( "github.com/ckaznocha/intrange" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := intrange.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(intrange.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iotamixing/iotamixing.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iotamixing/iotamixing.go new file mode 100644 index 000000000..dee0c3c77 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iotamixing/iotamixing.go @@ -0,0 +1,26 @@ +package iotamixing + +import ( + im "github.com/AdminBenni/iota-mixing/pkg/analyzer" + "github.com/AdminBenni/iota-mixing/pkg/analyzer/flags" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New(settings *config.IotaMixingSettings) *goanalysis.Linter { + cfg := map[string]any{} + + if settings != nil { + cfg[flags.ReportIndividualFlagName] = settings.ReportIndividual + } + + analyzer := im.GetIotaMixingAnalyzer() + + flags.SetupFlags(&analyzer.Flags) + + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ireturn/ireturn.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ireturn/ireturn.go index 44c28700b..b9cce0001 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ireturn/ireturn.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/ireturn/ireturn.go @@ -4,28 +4,24 @@ import ( "strings" "github.com/butuzov/ireturn/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.IreturnSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "allow": strings.Join(settings.Allow, ","), "reject": strings.Join(settings.Reject, ","), "nonolint": true, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/lll/lll.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/lll/lll.go index eb435baa7..c8e6717de 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/lll/lll.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/lll/lll.go @@ -15,30 +15,23 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "lll" - const goCommentDirectivePrefix = "//go:" func New(settings *config.LllSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runLll(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Reports long lines", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "lll", + Doc: "Reports long lines", + Run: func(pass *analysis.Pass) (any, error) { + err := runLll(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runLll(pass *analysis.Pass, settings *config.LllSettings) error { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/loggercheck/loggercheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/loggercheck/loggercheck.go index a5dd4da48..b9a6efa75 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/loggercheck/loggercheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/loggercheck/loggercheck.go @@ -2,7 +2,6 @@ package loggercheck import ( "github.com/timonwong/loggercheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -37,11 +36,7 @@ func New(settings *config.LoggerCheckSettings) *goanalysis.Linter { } } - analyzer := loggercheck.NewAnalyzer(opts...) - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(loggercheck.NewAnalyzer(opts...)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/maintidx/maintidx.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/maintidx/maintidx.go index 4e541f888..f2076c8ab 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/maintidx/maintidx.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/maintidx/maintidx.go @@ -2,29 +2,22 @@ package maintidx import ( "github.com/yagipy/maintidx" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.MaintIdxSettings) *goanalysis.Linter { - analyzer := maintidx.Analyzer - - cfg := map[string]map[string]any{ - analyzer.Name: {"under": 20}, + cfg := map[string]any{ + "under": 20, } if settings != nil { - cfg[analyzer.Name] = map[string]any{ - "under": settings.Under, - } + cfg["under"] = settings.Under } - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(maintidx.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/makezero/makezero.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/makezero/makezero.go index 04b4fe93d..5ee298d99 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/makezero/makezero.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/makezero/makezero.go @@ -3,35 +3,28 @@ package makezero import ( "fmt" - "github.com/ashanbrown/makezero/makezero" + "github.com/ashanbrown/makezero/v2/makezero" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "makezero" - func New(settings *config.MakezeroSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runMakeZero(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Finds slice declarations with non-zero initial length", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "makezero", + Doc: "Find slice declarations with non-zero initial length", + Run: func(pass *analysis.Pass) (any, error) { + err := runMakeZero(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runMakeZero(pass *analysis.Pass, settings *config.MakezeroSettings) error { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mirror/mirror.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mirror/mirror.go index 9badb0c1e..07cfe25e4 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mirror/mirror.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mirror/mirror.go @@ -2,29 +2,22 @@ package mirror import ( "github.com/butuzov/mirror" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := mirror.NewAnalyzer() - // mirror only lints test files if the `--with-tests` flag is passed, // so we pass the `with-tests` flag as true to the analyzer before running it. // This can be turned off by using the regular golangci-lint flags such as `--tests` or `--skip-files` // or can be disabled per linter via exclude rules. // (see https://github.com/golangci/golangci-lint/issues/2527#issuecomment-1023707262) - linterCfg := map[string]map[string]any{ - a.Name: { - "with-tests": true, - }, + cfg := map[string]any{ + "with-tests": true, } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - linterCfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(mirror.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/misspell/misspell.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/misspell/misspell.go index 9a170c953..cbf378505 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/misspell/misspell.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/misspell/misspell.go @@ -23,27 +23,22 @@ func New(settings *config.MisspellSettings) *goanalysis.Linter { internal.LinterLogger.Fatalf("%s: %v", linterName, err) } - a := &analysis.Analyzer{ - Name: linterName, - Doc: "Finds commonly misspelled English words", - Run: func(pass *analysis.Pass) (any, error) { - for _, file := range pass.Files { - err := runMisspellOnFile(pass, file, replacer, settings.Mode) - if err != nil { - return nil, err + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Finds commonly misspelled English words", + Run: func(pass *analysis.Pass) (any, error) { + for _, file := range pass.Files { + err := runMisspellOnFile(pass, file, replacer, settings.Mode) + if err != nil { + return nil, err + } } - } - return nil, nil - }, - } - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replacer, error) { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mnd/mnd.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mnd/mnd.go index 52521e92d..07174c899 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mnd/mnd.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/mnd/mnd.go @@ -2,18 +2,15 @@ package mnd import ( mnd "github.com/tommy-muehle/go-mnd/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.MndSettings) *goanalysis.Linter { - a := mnd.Analyzer + cfg := map[string]any{} - var linterCfg map[string]map[string]any if settings != nil { - cfg := make(map[string]any) if len(settings.Checks) > 0 { cfg["checks"] = settings.Checks } @@ -26,16 +23,11 @@ func New(settings *config.MndSettings) *goanalysis.Linter { if len(settings.IgnoredFunctions) > 0 { cfg["ignored-functions"] = settings.IgnoredFunctions } - - linterCfg = map[string]map[string]any{ - a.Name: cfg, - } } - return goanalysis.NewLinter( - a.Name, - "An analyzer to detect magic numbers.", - []*analysis.Analyzer{a}, - linterCfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(mnd.Analyzer). + WithDesc("An analyzer to detect magic numbers."). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go new file mode 100644 index 000000000..08cccdeb8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go @@ -0,0 +1,50 @@ +package modernize + +import ( + "slices" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/modernize" +) + +func New(settings *config.ModernizeSettings) *goanalysis.Linter { + var analyzers []*analysis.Analyzer + + if settings == nil { + analyzers = cleanSuite() + } else { + for _, analyzer := range cleanSuite() { + if slices.Contains(settings.Disable, analyzer.Name) { + continue + } + + analyzers = append(analyzers, analyzer) + } + } + + return goanalysis.NewLinter( + "modernize", + "A suite of analyzers that suggest simplifications to Go code, using modern language and library features.", + analyzers, + nil). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} + +func cleanSuite() []*analysis.Analyzer { + var analyzers []*analysis.Analyzer + + for _, analyzer := range modernize.Suite { + // Disabled because of false positives + // https://github.com/golang/go/issues/76687 + if analyzer.Name == "stringscut" { + continue + } + + analyzers = append(analyzers, analyzer) + } + + return analyzers +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/musttag/musttag.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/musttag/musttag.go index 030707327..d17df9c2b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/musttag/musttag.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/musttag/musttag.go @@ -2,7 +2,6 @@ package musttag import ( "go-simpler.org/musttag" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -21,9 +20,7 @@ func New(settings *config.MustTagSettings) *goanalysis.Linter { } } - a := musttag.New(funcs...) - return goanalysis. - NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + NewLinterFromAnalyzer(musttag.New(funcs...)). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nakedret/nakedret.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nakedret/nakedret.go index 1b769acd8..90053a1aa 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nakedret/nakedret.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nakedret/nakedret.go @@ -2,7 +2,6 @@ package nakedret import ( "github.com/alexkohler/nakedret/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -16,12 +15,7 @@ func New(settings *config.NakedretSettings) *goanalysis.Linter { cfg.MaxLength = settings.MaxFuncLines } - a := nakedret.NakedReturnAnalyzer(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(nakedret.NakedReturnAnalyzer(cfg)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nestif/nestif.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nestif/nestif.go index 1a6b55caf..e5823723c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nestif/nestif.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nestif/nestif.go @@ -8,25 +8,18 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "nestif" - func New(settings *config.NestifSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - runNestIf(pass, settings) - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Reports deeply nested if statements", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "nestif", + Doc: "Reports deeply nested if statements", + Run: func(pass *analysis.Pass) (any, error) { + runNestIf(pass, settings) + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runNestIf(pass *analysis.Pass, settings *config.NestifSettings) { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilerr/nilerr.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilerr/nilerr.go index 9345b945b..fa5dcdc25 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilerr/nilerr.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilerr/nilerr.go @@ -2,18 +2,13 @@ package nilerr import ( "github.com/gostaticanalysis/nilerr" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := nilerr.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Finds the code that returns nil even if it checks that the error is not nil.", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(nilerr.Analyzer). + WithDesc("Find the code that returns nil even if it checks that the error is not nil."). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnesserr/nilnesserr.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnesserr/nilnesserr.go index b54992e29..95eaf94ab 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnesserr/nilnesserr.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnesserr/nilnesserr.go @@ -2,22 +2,18 @@ package nilnesserr import ( "github.com/alingse/nilnesserr" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) func New() *goanalysis.Linter { - a, err := nilnesserr.NewAnalyzer(nilnesserr.LinterSetting{}) + analyzer, err := nilnesserr.NewAnalyzer(nilnesserr.LinterSetting{}) if err != nil { internal.LinterLogger.Fatalf("nilnesserr: create analyzer: %v", err) } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnil/nilnil.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnil/nilnil.go index 5f42e24c9..4936a6b84 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnil/nilnil.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nilnil/nilnil.go @@ -2,33 +2,28 @@ package nilnil import ( "github.com/Antonboom/nilnil/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.NilNilSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "detect-opposite": settings.DetectOpposite, } if b := settings.OnlyTwo; b != nil { - cfg[a.Name]["only-two"] = *b + cfg["only-two"] = *b } if len(settings.CheckedTypes) != 0 { - cfg[a.Name]["checked-types"] = settings.CheckedTypes + cfg["checked-types"] = settings.CheckedTypes } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ). + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nlreturn/nlreturn.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nlreturn/nlreturn.go index ce2130c52..7b7ab745a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nlreturn/nlreturn.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nlreturn/nlreturn.go @@ -2,26 +2,22 @@ package nlreturn import ( "github.com/ssgreg/nlreturn/v2/pkg/nlreturn" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.NlreturnSettings) *goanalysis.Linter { - a := nlreturn.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "block-size": settings.BlockSize, } } - - return goanalysis.NewLinter( - a.Name, - "nlreturn checks for a new line before return and branch statements to increase code clarity", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(nlreturn.NewAnalyzer()). + WithDesc("Checks for a new line before return and branch statements to increase code clarity"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noctx/noctx.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noctx/noctx.go index b0c5f9b50..c3e5be104 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noctx/noctx.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noctx/noctx.go @@ -2,18 +2,13 @@ package noctx import ( "github.com/sonatard/noctx" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := noctx.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Finds sending http request without context.Context", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(noctx.Analyzer). + WithDesc("Detects function and method with missing usage of context.Context"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noinlineerr/noinlineerr.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noinlineerr/noinlineerr.go new file mode 100644 index 000000000..4f9f82eb4 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/noinlineerr/noinlineerr.go @@ -0,0 +1,13 @@ +package noinlineerr + +import ( + "github.com/AlwxSin/noinlineerr" + + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New() *goanalysis.Linter { + return goanalysis. + NewLinterFromAnalyzer(noinlineerr.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/internal/nolintlint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/internal/nolintlint.go index 2be7c5c14..a20161405 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/internal/nolintlint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/internal/nolintlint.go @@ -55,8 +55,8 @@ var ( ) //nolint:funlen,gocyclo // the function is going to be refactored in the future -func (l Linter) Run(pass *analysis.Pass) ([]goanalysis.Issue, error) { - var issues []goanalysis.Issue +func (l Linter) Run(pass *analysis.Pass) ([]*goanalysis.Issue, error) { + var issues []*goanalysis.Issue for _, file := range pass.Files { for _, c := range file.Comments { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/nolintlint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/nolintlint.go index f19b8324c..6f3d37306 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/nolintlint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint/nolintlint.go @@ -17,7 +17,7 @@ const LinterName = nolintlint.LinterName func New(settings *config.NoLintLintSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue var needs nolintlint.Needs if settings.RequireExplanation { @@ -35,33 +35,29 @@ func New(settings *config.NoLintLintSettings) *goanalysis.Linter { internal.LinterLogger.Fatalf("%s: create analyzer: %v", nolintlint.LinterName, err) } - analyzer := &analysis.Analyzer{ - Name: nolintlint.LinterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := lnt.Run(pass) - if err != nil { - return nil, fmt.Errorf("linter failed to run: %w", err) - } + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: nolintlint.LinterName, + Doc: "Reports ill-formed or insufficient nolint directives", + Run: func(pass *analysis.Pass) (any, error) { + issues, err := lnt.Run(pass) + if err != nil { + return nil, fmt.Errorf("linter failed to run: %w", err) + } - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - nolintlint.LinterName, - "Reports ill-formed or insufficient nolint directives", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go index 91354f6a4..4149ef818 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go @@ -2,28 +2,22 @@ package nonamedreturns import ( "github.com/firefart/nonamedreturns/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.NoNamedReturnsSettings) *goanalysis.Linter { - a := analyzer.Analyzer + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer, - }, + cfg = map[string]any{ + analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nosprintfhostport/nosprintfhostport.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nosprintfhostport/nosprintfhostport.go index cca70680c..f8ca26b73 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nosprintfhostport/nosprintfhostport.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nosprintfhostport/nosprintfhostport.go @@ -2,18 +2,12 @@ package nosprintfhostport import ( "github.com/stbenjam/no-sprintf-host-port/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go index 8c811ca51..f3eac2e05 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go @@ -2,33 +2,28 @@ package paralleltest import ( "github.com/kunwardeep/paralleltest/pkg/paralleltest" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ParallelTestSettings) *goanalysis.Linter { - a := paralleltest.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - d := map[string]any{ + cfg = map[string]any{ "i": settings.IgnoreMissing, "ignoremissingsubtests": settings.IgnoreMissingSubtests, } if config.IsGoGreaterThanOrEqual(settings.Go, "1.22") { - d["ignoreloopVar"] = true + cfg["ignoreloopVar"] = true } - - cfg = map[string]map[string]any{a.Name: d} } - return goanalysis.NewLinter( - a.Name, - "Detects missing usage of t.Parallel() method in your Go test", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(paralleltest.NewAnalyzer()). + WithDesc("Detects missing usage of t.Parallel() method in your Go test"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/perfsprint/perfsprint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/perfsprint/perfsprint.go index f870ee001..e06b5c2a9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/perfsprint/perfsprint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/perfsprint/perfsprint.go @@ -2,41 +2,39 @@ package perfsprint import ( "github.com/catenacyber/perfsprint/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.PerfSprintSettings) *goanalysis.Linter { - a := analyzer.New() - - cfg := map[string]map[string]any{ - a.Name: {"fiximports": false}, + cfg := map[string]any{ + "fiximports": false, } if settings != nil { // NOTE: The option `ignore-tests` is not handled because it should be managed with `linters.exclusions.rules` - cfg[a.Name]["integer-format"] = settings.IntegerFormat - cfg[a.Name]["int-conversion"] = settings.IntConversion + cfg["integer-format"] = settings.IntegerFormat + cfg["int-conversion"] = settings.IntConversion + + cfg["error-format"] = settings.ErrorFormat + cfg["err-error"] = settings.ErrError + cfg["errorf"] = settings.ErrorF - cfg[a.Name]["error-format"] = settings.ErrorFormat - cfg[a.Name]["err-error"] = settings.ErrError - cfg[a.Name]["errorf"] = settings.ErrorF + cfg["string-format"] = settings.StringFormat + cfg["sprintf1"] = settings.SprintF1 + cfg["strconcat"] = settings.StrConcat - cfg[a.Name]["string-format"] = settings.StringFormat - cfg[a.Name]["sprintf1"] = settings.SprintF1 - cfg[a.Name]["strconcat"] = settings.StrConcat + cfg["bool-format"] = settings.BoolFormat + cfg["hex-format"] = settings.HexFormat - cfg[a.Name]["bool-format"] = settings.BoolFormat - cfg[a.Name]["hex-format"] = settings.HexFormat + cfg["concat-loop"] = settings.ConcatLoop + cfg["loop-other-ops"] = settings.LoopOtherOps } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go index 1ceba6007..c750df990 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go @@ -11,25 +11,18 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "prealloc" - func New(settings *config.PreallocSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - runPreAlloc(pass, settings) - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Finds slice declarations that could potentially be pre-allocated", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "prealloc", + Doc: "Find slice declarations that could potentially be pre-allocated", + Run: func(pass *analysis.Pass) (any, error) { + runPreAlloc(pass, settings) + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runPreAlloc(pass *analysis.Pass, settings *config.PreallocSettings) { @@ -38,7 +31,7 @@ func runPreAlloc(pass *analysis.Pass, settings *config.PreallocSettings) { for _, hint := range hints { pass.Report(analysis.Diagnostic{ Pos: hint.Pos, - Message: fmt.Sprintf("Consider pre-allocating %s", internal.FormatCode(hint.DeclaredSliceName, nil)), + Message: fmt.Sprintf("Consider pre-allocating %s", internal.FormatCode(hint.DeclaredSliceName)), }) } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/predeclared/predeclared.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/predeclared/predeclared.go index 9bde9d2f3..8f2be53c4 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/predeclared/predeclared.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/predeclared/predeclared.go @@ -4,25 +4,23 @@ import ( "strings" "github.com/nishanths/predeclared/passes/predeclared" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.PredeclaredSettings) *goanalysis.Linter { - a := predeclared.Analyzer + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - predeclared.IgnoreFlag: strings.Join(settings.Ignore, ","), - predeclared.QualifiedFlag: settings.Qualified, - }, + cfg = map[string]any{ + predeclared.IgnoreFlag: strings.Join(settings.Ignore, ","), + predeclared.QualifiedFlag: settings.Qualified, } } - return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, cfg). + return goanalysis. + NewLinterFromAnalyzer(predeclared.Analyzer). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/promlinter/promlinter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/promlinter/promlinter.go index ab2c9c569..491409f4e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/promlinter/promlinter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/promlinter/promlinter.go @@ -17,7 +17,7 @@ const linterName = "promlinter" func New(settings *config.PromlinterSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue var promSettings promlinter.Setting if settings != nil { @@ -27,42 +27,38 @@ func New(settings *config.PromlinterSettings) *goanalysis.Linter { } } - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runPromLinter(pass, promSettings) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Check Prometheus metrics naming via promlint", + Run: func(pass *analysis.Pass) (any, error) { + issues := runPromLinter(pass, promSettings) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Check Prometheus metrics naming via promlint", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } -func runPromLinter(pass *analysis.Pass, promSettings promlinter.Setting) []goanalysis.Issue { +func runPromLinter(pass *analysis.Pass, promSettings promlinter.Setting) []*goanalysis.Issue { lintIssues := promlinter.RunLint(pass.Fset, pass.Files, promSettings) if len(lintIssues) == 0 { return nil } - issues := make([]goanalysis.Issue, len(lintIssues)) + issues := make([]*goanalysis.Issue, len(lintIssues)) for k, i := range lintIssues { issue := result.Issue{ Pos: i.Pos, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/protogetter/protogetter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/protogetter/protogetter.go index c13c98af5..bee5da263 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/protogetter/protogetter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/protogetter/protogetter.go @@ -2,7 +2,6 @@ package protogetter import ( "github.com/ghostiam/protogetter" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,6 +9,7 @@ import ( func New(settings *config.ProtoGetterSettings) *goanalysis.Linter { var cfg protogetter.Config + if settings != nil { cfg = protogetter.Config{ SkipGeneratedBy: settings.SkipGeneratedBy, @@ -19,12 +19,7 @@ func New(settings *config.ProtoGetterSettings) *goanalysis.Linter { } } - a := protogetter.NewAnalyzer(&cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(protogetter.NewAnalyzer(&cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/reassign/reassign.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/reassign/reassign.go index 7d9f84285..35e661cae 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/reassign/reassign.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/reassign/reassign.go @@ -5,28 +5,22 @@ import ( "strings" "github.com/curioswitch/go-reassign" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ReassignSettings) *goanalysis.Linter { - a := reassign.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil && len(settings.Patterns) > 0 { - cfg = map[string]map[string]any{ - a.Name: { - reassign.FlagPattern: fmt.Sprintf("^(%s)$", strings.Join(settings.Patterns, "|")), - }, + cfg = map[string]any{ + reassign.FlagPattern: fmt.Sprintf("^(%s)$", strings.Join(settings.Patterns, "|")), } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(reassign.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/recvcheck/recvcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/recvcheck/recvcheck.go index ed1eb0b78..76db48f93 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/recvcheck/recvcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/recvcheck/recvcheck.go @@ -2,7 +2,6 @@ package recvcheck import ( "github.com/raeperd/recvcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -16,12 +15,7 @@ func New(settings *config.RecvcheckSettings) *goanalysis.Linter { cfg.Exclusions = settings.Exclusions } - a := recvcheck.NewAnalyzer(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(recvcheck.NewAnalyzer(cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go index 5f9b3a90a..6799e1a42 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go @@ -35,45 +35,44 @@ var ( func New(settings *config.ReviveSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, + Name: linterName, + Doc: "Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.", Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - w, err := newWrapper(settings) - if err != nil { - lintCtx.Log.Errorf("setup revive: %v", err) - return - } - - analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues, err := w.run(pass) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + w, err := newWrapper(settings) if err != nil { - return nil, err + lintCtx.Log.Errorf("setup revive: %v", err) + return } - if len(issues) == 0 { - return nil, nil - } + analyzer.Run = func(pass *analysis.Pass) (any, error) { + issues, err := w.run(pass) + if err != nil { + return nil, err + } - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } type wrapper struct { @@ -107,7 +106,7 @@ func newWrapper(settings *config.ReviveSettings) (*wrapper, error) { }, nil } -func (w *wrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { +func (w *wrapper) run(pass *analysis.Pass) ([]*goanalysis.Issue, error) { packages := [][]string{internal.GetGoFileNames(pass)} failures, err := w.revive.Lint(packages, w.lintingRules, *w.conf) @@ -115,7 +114,7 @@ func (w *wrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { return nil, err } - var issues []goanalysis.Issue + var issues []*goanalysis.Issue for failure := range failures { if failure.Confidence < w.conf.Confidence { continue @@ -127,7 +126,7 @@ func (w *wrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { return issues, nil } -func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) goanalysis.Issue { +func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) *goanalysis.Issue { lineRangeTo := failure.Position.End.Line if failure.RuleName == (&rule.ExportedRule{}).Name() { lineRangeTo = failure.Position.Start.Line @@ -153,7 +152,7 @@ func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) goanalysis f := pass.Fset.File(token.Pos(failure.Position.Start.Offset)) // Skip cgo files because the positions are wrong. - if failure.GetFilename() == f.Name() { + if failure.Filename() == f.Name() { issue.SuggestedFixes = []analysis.SuggestedFix{{ TextEdits: []analysis.TextEdit{{ Pos: f.LineStart(failure.Position.Start.Line), @@ -170,8 +169,8 @@ func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) goanalysis // This function mimics the GetConfig function of revive. // This allows to get default values and right types. // https://github.com/golangci/golangci-lint/issues/1745 -// https://github.com/mgechev/revive/blob/v1.6.0/config/config.go#L230 -// https://github.com/mgechev/revive/blob/v1.6.0/config/config.go#L182-L188 +// https://github.com/mgechev/revive/blob/v1.13.0/config/config.go#L249 +// https://github.com/mgechev/revive/blob/v1.13.0/config/config.go#L198-L204 func getConfig(cfg *config.ReviveSettings) (*lint.Config, error) { conf := defaultConfig() @@ -270,7 +269,7 @@ func safeTomlSlice(r []any) []any { } // This element is not exported by revive, so we need copy the code. -// Extracted from https://github.com/mgechev/revive/blob/v1.6.0/config/config.go#L16 +// Extracted from https://github.com/mgechev/revive/blob/v1.13.0/config/config.go#L16 var defaultRules = []lint.Rule{ &rule.VarDeclarationsRule{}, &rule.PackageCommentsRule{}, @@ -298,72 +297,88 @@ var defaultRules = []lint.Rule{ } var allRules = append([]lint.Rule{ + &rule.AddConstantRule{}, &rule.ArgumentsLimitRule{}, - &rule.CyclomaticRule{}, - &rule.FileHeaderRule{}, + &rule.AtomicRule{}, + &rule.BannedCharsRule{}, + &rule.BareReturnRule{}, + &rule.BoolLiteralRule{}, + &rule.CallToGCRule{}, + &rule.CognitiveComplexityRule{}, + &rule.CommentsDensityRule{}, + &rule.CommentSpacingsRule{}, &rule.ConfusingNamingRule{}, - &rule.GetReturnRule{}, - &rule.ModifiesParamRule{}, &rule.ConfusingResultsRule{}, - &rule.DeepExitRule{}, - &rule.AddConstantRule{}, - &rule.FlagParamRule{}, - &rule.UnnecessaryStmtRule{}, - &rule.StructTagRule{}, - &rule.ModifiesValRecRule{}, &rule.ConstantLogicalExprRule{}, - &rule.BoolLiteralRule{}, - &rule.ImportsBlocklistRule{}, - &rule.FunctionResultsLimitRule{}, - &rule.MaxPublicStructsRule{}, - &rule.RangeValInClosureRule{}, - &rule.RangeValAddress{}, - &rule.WaitGroupByValueRule{}, - &rule.AtomicRule{}, - &rule.EmptyLinesRule{}, - &rule.LineLengthLimitRule{}, - &rule.CallToGCRule{}, + &rule.CyclomaticRule{}, + &rule.DataRaceRule{}, + &rule.DeepExitRule{}, + &rule.DeferRule{}, &rule.DuplicatedImportsRule{}, - &rule.ImportShadowingRule{}, - &rule.BareReturnRule{}, - &rule.UnusedReceiverRule{}, - &rule.UnhandledErrorRule{}, - &rule.CognitiveComplexityRule{}, - &rule.StringOfIntRule{}, - &rule.StringFormatRule{}, &rule.EarlyReturnRule{}, - &rule.UnconditionalRecursionRule{}, - &rule.IdenticalBranchesRule{}, - &rule.DeferRule{}, - &rule.UnexportedNamingRule{}, - &rule.FunctionLength{}, - &rule.NestedStructs{}, - &rule.UselessBreak{}, - &rule.UncheckedTypeAssertionRule{}, - &rule.TimeEqualRule{}, - &rule.BannedCharsRule{}, - &rule.OptimizeOperandsOrderRule{}, - &rule.UseAnyRule{}, - &rule.DataRaceRule{}, - &rule.CommentSpacingsRule{}, - &rule.IfReturnRule{}, - &rule.RedundantImportAlias{}, - &rule.ImportAliasNamingRule{}, + &rule.EmptyLinesRule{}, &rule.EnforceMapStyleRule{}, &rule.EnforceRepeatedArgTypeStyleRule{}, &rule.EnforceSliceStyleRule{}, - &rule.MaxControlNestingRule{}, - &rule.CommentsDensityRule{}, + &rule.EnforceSwitchStyleRule{}, + &rule.FileHeaderRule{}, &rule.FileLengthLimitRule{}, &rule.FilenameFormatRule{}, + &rule.FlagParamRule{}, + &rule.ForbiddenCallInWgGoRule{}, + &rule.FunctionLength{}, + &rule.FunctionResultsLimitRule{}, + &rule.GetReturnRule{}, + &rule.IdenticalBranchesRule{}, + &rule.IdenticalIfElseIfBranchesRule{}, + &rule.IdenticalIfElseIfConditionsRule{}, + &rule.IdenticalSwitchBranchesRule{}, + &rule.IdenticalSwitchConditionsRule{}, + &rule.IfReturnRule{}, + &rule.ImportAliasNamingRule{}, + &rule.ImportsBlocklistRule{}, + &rule.ImportShadowingRule{}, + &rule.InefficientMapLookupRule{}, + &rule.LineLengthLimitRule{}, + &rule.MaxControlNestingRule{}, + &rule.MaxPublicStructsRule{}, + &rule.ModifiesParamRule{}, + &rule.ModifiesValRecRule{}, + &rule.NestedStructs{}, + &rule.OptimizeOperandsOrderRule{}, + &rule.PackageDirectoryMismatchRule{}, + &rule.RangeValAddress{}, + &rule.RangeValInClosureRule{}, &rule.RedundantBuildTagRule{}, + &rule.RedundantImportAlias{}, + &rule.RedundantTestMainExitRule{}, + &rule.StringFormatRule{}, + &rule.StringOfIntRule{}, + &rule.StructTagRule{}, + &rule.TimeDateRule{}, + &rule.TimeEqualRule{}, + &rule.UncheckedTypeAssertionRule{}, + &rule.UnconditionalRecursionRule{}, + &rule.UnexportedNamingRule{}, + &rule.UnhandledErrorRule{}, + &rule.UnnecessaryFormatRule{}, + &rule.UnnecessaryIfRule{}, + &rule.UnnecessaryStmtRule{}, + &rule.UnsecureURLSchemeRule{}, + &rule.UnusedReceiverRule{}, + &rule.UseAnyRule{}, &rule.UseErrorsNewRule{}, + &rule.UseFmtPrintRule{}, + &rule.UselessBreak{}, + &rule.UselessFallthroughRule{}, + &rule.UseWaitGroupGoRule{}, + &rule.WaitGroupByValueRule{}, }, defaultRules...) const defaultConfidence = 0.8 // This element is not exported by revive, so we need copy the code. -// Extracted from https://github.com/mgechev/revive/blob/v1.5.0/config/config.go#L183 +// Extracted from https://github.com/mgechev/revive/blob/v1.13.0/config/config.go#L209 func normalizeConfig(cfg *lint.Config) { // NOTE(ldez): this custom section for golangci-lint should be kept. // --- @@ -374,19 +389,22 @@ func normalizeConfig(cfg *lint.Config) { if len(cfg.Rules) == 0 { cfg.Rules = map[string]lint.RuleConfig{} } - if cfg.EnableAllRules { - // Add to the configuration all rules not yet present in it - for _, r := range allRules { + + addRules := func(config *lint.Config, rules []lint.Rule) { + for _, r := range rules { ruleName := r.Name() - _, alreadyInConf := cfg.Rules[ruleName] - if alreadyInConf { - continue + if _, ok := config.Rules[ruleName]; !ok { + config.Rules[ruleName] = lint.RuleConfig{} } - // Add the rule with an empty conf for - cfg.Rules[ruleName] = lint.RuleConfig{} } } + if cfg.EnableAllRules { + addRules(cfg, allRules) + } else if cfg.EnableDefaultRules { + addRules(cfg, defaultRules) + } + severity := cfg.Severity if severity != "" { for k, v := range cfg.Rules { @@ -405,7 +423,7 @@ func normalizeConfig(cfg *lint.Config) { } // This element is not exported by revive, so we need copy the code. -// Extracted from https://github.com/mgechev/revive/blob/v1.5.0/config/config.go#L252 +// Extracted from https://github.com/mgechev/revive/blob/v1.13.0/config/config.go#L280 func defaultConfig() *lint.Config { defaultConfig := lint.Config{ Confidence: defaultConfidence, @@ -433,7 +451,7 @@ func displayRules(conf *lint.Config) { slices.Sort(enabledRules) debugf("All available rules (%d): %s.", len(allRules), strings.Join(extractRulesName(allRules), ", ")) - debugf("Default rules (%d): %s.", len(allRules), strings.Join(extractRulesName(allRules), ", ")) + debugf("Default rules (%d): %s.", len(defaultRules), strings.Join(extractRulesName(defaultRules), ", ")) debugf("Enabled by config rules (%d): %s.", len(enabledRules), strings.Join(enabledRules, ", ")) debugf("revive configuration: %#v", conf) @@ -451,7 +469,7 @@ func extractRulesName(rules []lint.Rule) []string { return names } -// Extracted from https://github.com/mgechev/revive/blob/v1.7.0/formatter/severity.go +// Extracted from https://github.com/mgechev/revive/blob/v1.13.0/formatter/severity.go // Modified to use pointers (related to hugeParam rule). func severity(cfg *lint.Config, failure *lint.Failure) lint.Severity { if cfg, ok := cfg.Rules[failure.RuleName]; ok && cfg.Severity == lint.SeverityError { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go index 2bd975ddf..de0fe4da9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go @@ -2,7 +2,6 @@ package rowserrcheck import ( "github.com/jingyugao/rowserrcheck/passes/rowserr" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,16 +9,13 @@ import ( func New(settings *config.RowsErrCheckSettings) *goanalysis.Linter { var pkgs []string + if settings != nil { pkgs = settings.Packages } - a := rowserr.NewAnalyzer(pkgs...) - - return goanalysis.NewLinter( - a.Name, - "checks whether Rows.Err of rows is checked successfully", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(rowserr.NewAnalyzer(pkgs...)). + WithDesc("checks whether Rows.Err of rows is checked successfully"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go index 021157dd6..891f1fcfd 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go @@ -2,7 +2,6 @@ package sloglint import ( "go-simpler.org/sloglint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,6 +9,7 @@ import ( func New(settings *config.SlogLintSettings) *goanalysis.Linter { var opts *sloglint.Options + if settings != nil { opts = &sloglint.Options{ NoMixedArgs: settings.NoMixedArgs, @@ -26,9 +26,7 @@ func New(settings *config.SlogLintSettings) *goanalysis.Linter { } } - a := sloglint.New(opts) - return goanalysis. - NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + NewLinterFromAnalyzer(sloglint.New(opts)). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/spancheck/spancheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/spancheck/spancheck.go index 264623058..345c36277 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/spancheck/spancheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/spancheck/spancheck.go @@ -2,7 +2,6 @@ package spancheck import ( "github.com/jjti/go-spancheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -25,9 +24,7 @@ func New(settings *config.SpancheckSettings) *goanalysis.Linter { } } - a := spancheck.NewAnalyzerWithConfig(cfg) - return goanalysis. - NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + NewLinterFromAnalyzer(spancheck.NewAnalyzerWithConfig(cfg)). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sqlclosecheck/sqlclosecheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sqlclosecheck/sqlclosecheck.go index 7f7e70c71..4c970cc52 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sqlclosecheck/sqlclosecheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sqlclosecheck/sqlclosecheck.go @@ -2,18 +2,12 @@ package sqlclosecheck import ( "github.com/ryanrolds/sqlclosecheck/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/staticcheck/staticcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/staticcheck/staticcheck.go index 1ec39244c..0f529a58e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/staticcheck/staticcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/staticcheck/staticcheck.go @@ -15,6 +15,12 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/logutils" +) + +var ( + debugf = logutils.Debug(logutils.DebugKeyStaticcheck) + isDebug = logutils.HaveDebugTag(logutils.DebugKeyStaticcheck) ) func New(settings *config.StaticCheckSettings) *goanalysis.Linter { @@ -29,6 +35,21 @@ func New(settings *config.StaticCheckSettings) *goanalysis.Linter { analyzers := setupAnalyzers(allAnalyzers, cfg.Checks) + if isDebug { + allAnalyzerNames := extractAnalyzerNames(allAnalyzers) + slices.Sort(allAnalyzerNames) + debugf("All available checks (%d): %s", len(allAnalyzers), strings.Join(allAnalyzerNames, ",")) + + var cfgAnalyzerNames []string + for _, a := range analyzers { + cfgAnalyzerNames = append(cfgAnalyzerNames, a.Name) + } + slices.Sort(cfgAnalyzerNames) + debugf("Enabled by config checks (%d): %s", len(analyzers), strings.Join(cfgAnalyzerNames, ",")) + + debugf("staticcheck configuration: %#v", cfg) + } + return goanalysis.NewLinter( "staticcheck", "It's the set of rules from staticcheck.", @@ -58,19 +79,19 @@ func createConfig(settings *config.StaticCheckSettings) *scconfig.Config { HTTPStatusCodeWhitelist: settings.HTTPStatusCodeWhitelist, } - if len(cfg.Checks) == 0 { + if cfg.Checks == nil { cfg.Checks = defaultChecks } - if len(cfg.Initialisms) == 0 { + if cfg.Initialisms == nil { cfg.Initialisms = append(cfg.Initialisms, scconfig.DefaultConfig.Initialisms...) } - if len(cfg.DotImportWhitelist) == 0 { + if cfg.DotImportWhitelist == nil { cfg.DotImportWhitelist = append(cfg.DotImportWhitelist, scconfig.DefaultConfig.DotImportWhitelist...) } - if len(cfg.HTTPStatusCodeWhitelist) == 0 { + if cfg.HTTPStatusCodeWhitelist == nil { cfg.HTTPStatusCodeWhitelist = append(cfg.HTTPStatusCodeWhitelist, scconfig.DefaultConfig.HTTPStatusCodeWhitelist...) } @@ -107,12 +128,7 @@ func normalizeList(list []string) []string { } func setupAnalyzers(src []*lint.Analyzer, checks []string) []*analysis.Analyzer { - var names []string - for _, a := range src { - names = append(names, a.Analyzer.Name) - } - - filter := filterAnalyzerNames(names, checks) + filter := filterAnalyzerNames(extractAnalyzerNames(src), checks) var ret []*analysis.Analyzer for _, a := range src { @@ -124,6 +140,14 @@ func setupAnalyzers(src []*lint.Analyzer, checks []string) []*analysis.Analyzer return ret } +func extractAnalyzerNames(analyzers []*lint.Analyzer) []string { + var names []string + for _, a := range analyzers { + names = append(names, a.Analyzer.Name) + } + return names +} + // https://github.com/dominikh/go-tools/blob/9bf17c0388a65710524ba04c2d821469e639fdc2/lintcmd/lint.go#L437-L477 // //nolint:gocritic // Keep the original source code. diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/swaggo/swaggo.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/swaggo/swaggo.go new file mode 100644 index 000000000..98f7a6bef --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/swaggo/swaggo.go @@ -0,0 +1,20 @@ +package swaggo + +import ( + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/goformatters" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" + "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" +) + +func New() *goanalysis.Linter { + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(swaggo.Name), + "Check if swaggo comments are formatted", + swaggo.New(), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagalign/tagalign.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagalign/tagalign.go index 412d69b93..eba51311c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagalign/tagalign.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagalign/tagalign.go @@ -2,7 +2,6 @@ package tagalign import ( "github.com/4meepo/tagalign" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -24,12 +23,7 @@ func New(settings *config.TagAlignSettings) *goanalysis.Linter { } } - analyzer := tagalign.NewAnalyzer(options...) - - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(tagalign.NewAnalyzer(options...)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagliatelle/tagliatelle.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagliatelle/tagliatelle.go index f6357e0e3..d0268d11f 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagliatelle/tagliatelle.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tagliatelle/tagliatelle.go @@ -1,8 +1,10 @@ package tagliatelle import ( + "maps" + "strings" + "github.com/ldez/tagliatelle" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -20,9 +22,7 @@ func New(settings *config.TagliatelleSettings) *goanalysis.Linter { } if settings != nil { - for k, v := range settings.Case.Rules { - cfg.Rules[k] = v - } + maps.Copy(cfg.Rules, settings.Case.Rules) cfg.ExtendedRules = toExtendedRules(settings.Case.ExtendedRules) cfg.UseFieldName = settings.Case.UseFieldName @@ -42,24 +42,24 @@ func New(settings *config.TagliatelleSettings) *goanalysis.Linter { } } - a := tagliatelle.New(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(tagliatelle.New(cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func toExtendedRules(src map[string]config.TagliatelleExtendedRule) map[string]tagliatelle.ExtendedRule { result := make(map[string]tagliatelle.ExtendedRule, len(src)) for k, v := range src { + initialismOverrides := make(map[string]bool, len(v.InitialismOverrides)) + for ki, vi := range v.InitialismOverrides { + initialismOverrides[strings.ToUpper(ki)] = vi + } + result[k] = tagliatelle.ExtendedRule{ Case: v.Case, ExtraInitialisms: v.ExtraInitialisms, - InitialismOverrides: v.InitialismOverrides, + InitialismOverrides: initialismOverrides, } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testableexamples/testableexamples.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testableexamples/testableexamples.go index 38334a096..45fdc900e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testableexamples/testableexamples.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testableexamples/testableexamples.go @@ -2,18 +2,12 @@ package testableexamples import ( "github.com/maratori/testableexamples/pkg/testableexamples" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := testableexamples.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(testableexamples.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testifylint/testifylint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testifylint/testifylint.go index b19471c1e..bb5eac0e4 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testifylint/testifylint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testifylint/testifylint.go @@ -2,18 +2,16 @@ package testifylint import ( "github.com/Antonboom/testifylint/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.TestifylintSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "enable-all": settings.EnableAll, "disable-all": settings.DisableAll, @@ -23,30 +21,28 @@ func New(settings *config.TestifylintSettings) *goanalysis.Linter { "go-require.ignore-http-handlers": settings.GoRequire.IgnoreHTTPHandlers, } if len(settings.EnabledCheckers) > 0 { - cfg[a.Name]["enable"] = settings.EnabledCheckers + cfg["enable"] = settings.EnabledCheckers } if len(settings.DisabledCheckers) > 0 { - cfg[a.Name]["disable"] = settings.DisabledCheckers + cfg["disable"] = settings.DisabledCheckers } if b := settings.Formatter.CheckFormatString; b != nil { - cfg[a.Name]["formatter.check-format-string"] = *b + cfg["formatter.check-format-string"] = *b } if p := settings.ExpectedActual.ExpVarPattern; p != "" { - cfg[a.Name]["expected-actual.pattern"] = p + cfg["expected-actual.pattern"] = p } if p := settings.RequireError.FnPattern; p != "" { - cfg[a.Name]["require-error.fn-pattern"] = p + cfg["require-error.fn-pattern"] = p } if m := settings.SuiteExtraAssertCall.Mode; m != "" { - cfg[a.Name]["suite-extra-assert-call.mode"] = m + cfg["suite-extra-assert-call.mode"] = m } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testpackage/testpackage.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testpackage/testpackage.go index ddd5ce95c..39c333f1b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testpackage/testpackage.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/testpackage/testpackage.go @@ -4,25 +4,23 @@ import ( "strings" "github.com/maratori/testpackage/pkg/testpackage" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.TestpackageSettings) *goanalysis.Linter { - a := testpackage.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - testpackage.SkipRegexpFlagName: settings.SkipRegexp, - testpackage.AllowPackagesFlagName: strings.Join(settings.AllowPackages, ","), - }, + cfg = map[string]any{ + testpackage.SkipRegexpFlagName: settings.SkipRegexp, + testpackage.AllowPackagesFlagName: strings.Join(settings.AllowPackages, ","), } } - return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, cfg). + return goanalysis. + NewLinterFromAnalyzer(testpackage.NewAnalyzer()). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/thelper/thelper.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/thelper/thelper.go index d9058582d..77090c5f8 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/thelper/thelper.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/thelper/thelper.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/kulti/thelper/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -14,8 +13,6 @@ import ( ) func New(settings *config.ThelperSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() - opts := map[string]struct{}{ "t_name": {}, "t_begin": {}, @@ -47,18 +44,14 @@ func New(settings *config.ThelperSettings) *goanalysis.Linter { args := slices.Collect(maps.Keys(opts)) - cfg := map[string]map[string]any{ - a.Name: { - "checks": strings.Join(args, ","), - }, + cfg := map[string]any{ + "checks": strings.Join(args, ","), } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func applyTHelperOptions(o config.ThelperOptions, prefix string, opts map[string]struct{}) { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tparallel/tparallel.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tparallel/tparallel.go index f3ce2fcf7..480ef3b1e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tparallel/tparallel.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/tparallel/tparallel.go @@ -2,17 +2,12 @@ package tparallel import ( "github.com/moricho/tparallel" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := tparallel.Analyzer - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(tparallel.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/typecheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/typecheck.go index ad51e8d00..db29f7c18 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/typecheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/typecheck.go @@ -7,18 +7,11 @@ import ( ) func NewTypecheck() *goanalysis.Linter { - const linterName = "typecheck" - - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, - } - - return goanalysis.NewLinter( - linterName, - "Like the front-end of a Go compiler, parses and type-checks Go code", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeNone) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "typecheck", + Doc: "Like the front-end of a Go compiler, parses and type-checks Go code", + Run: goanalysis.DummyRun, + }). + WithLoadMode(goanalysis.LoadModeNone) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unconvert/unconvert.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unconvert/unconvert.go index d48cf5175..593dfbe96 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unconvert/unconvert.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unconvert/unconvert.go @@ -16,43 +16,39 @@ const linterName = "unconvert" func New(settings *config.UnconvertSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue unconvert.SetFastMath(settings.FastMath) unconvert.SetSafe(settings.Safe) - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runUnconvert(pass) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Remove unnecessary type conversions", + Run: func(pass *analysis.Pass) (any, error) { + issues := runUnconvert(pass) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Remove unnecessary type conversions", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnconvert(pass *analysis.Pass) []goanalysis.Issue { +func runUnconvert(pass *analysis.Pass) []*goanalysis.Issue { positions := unconvert.Run(pass) - var issues []goanalysis.Issue + var issues []*goanalysis.Issue for _, position := range positions { issues = append(issues, goanalysis.NewIssue(&result.Issue{ Pos: position, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unparam/unparam.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unparam/unparam.go index 5a9bc8a5e..b6cb2668b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unparam/unparam.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unparam/unparam.go @@ -10,29 +10,22 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "unparam" - func New(settings *config.UnparamSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Requires: []*analysis.Analyzer{buildssa.Analyzer}, - Run: func(pass *analysis.Pass) (any, error) { - err := runUnparam(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Reports unused function parameters", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "unparam", + Doc: "Reports unused function parameters", + Requires: []*analysis.Analyzer{buildssa.Analyzer}, + Run: func(pass *analysis.Pass) (any, error) { + err := runUnparam(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runUnparam(pass *analysis.Pass, settings *config.UnparamSettings) error { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go new file mode 100644 index 000000000..db4a4d752 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go @@ -0,0 +1,24 @@ +package unqueryvet + +import ( + "github.com/MirrexOne/unqueryvet" + pkgconfig "github.com/MirrexOne/unqueryvet/pkg/config" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New(settings *config.UnqueryvetSettings) *goanalysis.Linter { + cfg := pkgconfig.DefaultSettings() + + if settings != nil { + cfg.CheckSQLBuilders = settings.CheckSQLBuilders + if len(settings.AllowedPatterns) > 0 { + cfg.AllowedPatterns = settings.AllowedPatterns + } + } + + return goanalysis. + NewLinterFromAnalyzer(unqueryvet.NewWithConfig(&cfg)). + WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unused/unused.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unused/unused.go index 375962259..c0f4657dc 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unused/unused.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unused/unused.go @@ -20,7 +20,7 @@ const linterName = "unused" func New(settings *config.UnusedSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue analyzer := &analysis.Analyzer{ Name: linterName, @@ -45,12 +45,12 @@ func New(settings *config.UnusedSettings) *goanalysis.Linter { "Checks Go code for unused constants, variables, functions and types", []*analysis.Analyzer{analyzer}, nil, - ).WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { + ).WithIssuesReporter(func(_ *linter.Context) []*goanalysis.Issue { return resIssues }).WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []goanalysis.Issue { +func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []*goanalysis.Issue { res := getUnusedResults(pass, cfg) used := make(map[string]bool) @@ -58,7 +58,7 @@ func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []goanalysis.Iss used[fmt.Sprintf("%s %d %s", obj.Position.Filename, obj.Position.Line, obj.Name)] = true } - var issues []goanalysis.Issue + var issues []*goanalysis.Issue // Inspired by https://github.com/dominikh/go-tools/blob/d694aadcb1f50c2d8ac0a1dd06217ebb9f654764/lintcmd/lint.go#L177-L197 for _, object := range res.Unused { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usestdlibvars/usestdlibvars.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usestdlibvars/usestdlibvars.go index f0b5f5420..e4a900ff6 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usestdlibvars/usestdlibvars.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usestdlibvars/usestdlibvars.go @@ -2,18 +2,16 @@ package usestdlibvars import ( "github.com/sashamelentyev/usestdlibvars/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.UseStdlibVarsSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ analyzer.ConstantKindFlag: settings.ConstantKind, analyzer.CryptoHashFlag: settings.CryptoHash, analyzer.HTTPMethodFlag: settings.HTTPMethod, @@ -26,13 +24,12 @@ func New(settings *config.UseStdlibVarsSettings) *goanalysis.Linter { analyzer.TimeMonthFlag: settings.TimeMonth, analyzer.TimeWeekdayFlag: settings.TimeWeekday, analyzer.TLSSignatureSchemeFlag: settings.TLSSignatureScheme, + analyzer.TimeDateMonthFlag: settings.TimeDateMonth, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usetesting/usetesting.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usetesting/usetesting.go index 5dfa9f11a..7371cc28e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usetesting/usetesting.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/usetesting/usetesting.go @@ -2,18 +2,16 @@ package usetesting import ( "github.com/ldez/usetesting" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.UseTestingSettings) *goanalysis.Linter { - a := usetesting.NewAnalyzer() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "contextbackground": settings.ContextBackground, "contexttodo": settings.ContextTodo, "oschdir": settings.OSChdir, @@ -24,10 +22,8 @@ func New(settings *config.UseTestingSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(usetesting.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/varnamelen/varnamelen.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/varnamelen/varnamelen.go index dbd8005ee..349feefa0 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/varnamelen/varnamelen.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/varnamelen/varnamelen.go @@ -5,18 +5,16 @@ import ( "strings" "github.com/blizzy78/varnamelen" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.VarnamelenSettings) *goanalysis.Linter { - analyzer := varnamelen.NewAnalyzer() - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - vnlCfg := map[string]any{ + cfg = map[string]any{ "checkReceiver": strconv.FormatBool(settings.CheckReceiver), "checkReturn": strconv.FormatBool(settings.CheckReturn), "checkTypeParam": strconv.FormatBool(settings.CheckTypeParam), @@ -28,19 +26,17 @@ func New(settings *config.VarnamelenSettings) *goanalysis.Linter { } if settings.MaxDistance > 0 { - vnlCfg["maxDistance"] = strconv.Itoa(settings.MaxDistance) + cfg["maxDistance"] = strconv.Itoa(settings.MaxDistance) } + if settings.MinNameLength > 0 { - vnlCfg["minNameLength"] = strconv.Itoa(settings.MinNameLength) + cfg["minNameLength"] = strconv.Itoa(settings.MinNameLength) } - - cfg[analyzer.Name] = vnlCfg } - return goanalysis.NewLinter( - analyzer.Name, - "checks that the length of a variable's name matches its scope", - []*analysis.Analyzer{analyzer}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(varnamelen.NewAnalyzer()). + WithDesc("checks that the length of a variable's name matches its scope"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wastedassign/wastedassign.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wastedassign/wastedassign.go index 6599f7d4d..d103a8d5a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wastedassign/wastedassign.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wastedassign/wastedassign.go @@ -2,18 +2,13 @@ package wastedassign import ( "github.com/sanposhiho/wastedassign/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := wastedassign.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Finds wasted assignment statements", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(wastedassign.Analyzer). + WithDesc("Finds wasted assignment statements"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/whitespace/whitespace.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/whitespace/whitespace.go index cd7fda1ce..bf03e1d80 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/whitespace/whitespace.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/whitespace/whitespace.go @@ -2,7 +2,6 @@ package whitespace import ( "github.com/ultraware/whitespace" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -17,12 +16,7 @@ func New(settings *config.WhitespaceSettings) *goanalysis.Linter { } } - a := whitespace.NewAnalyzer(&wsSettings) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(whitespace.NewAnalyzer(&wsSettings)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wrapcheck/wrapcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wrapcheck/wrapcheck.go index 8a4427f7d..c29c509a8 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wrapcheck/wrapcheck.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wrapcheck/wrapcheck.go @@ -2,7 +2,6 @@ package wrapcheck import ( "github.com/tomarrell/wrapcheck/v2/wrapcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -29,12 +28,7 @@ func New(settings *config.WrapcheckSettings) *goanalysis.Linter { } } - a := wrapcheck.NewAnalyzer(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(wrapcheck.NewAnalyzer(cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl.go index 12148627e..4a5c6e19b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl.go @@ -1,17 +1,22 @@ package wsl import ( - "github.com/bombsimon/wsl/v4" - "golang.org/x/tools/go/analysis" + "slices" + + wslv4 "github.com/bombsimon/wsl/v4" + wslv5 "github.com/bombsimon/wsl/v5" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -func New(settings *config.WSLSettings) *goanalysis.Linter { - var conf *wsl.Configuration +// Deprecated: use NewV5 instead. +func NewV4(settings *config.WSLv4Settings) *goanalysis.Linter { + var conf *wslv4.Configuration + if settings != nil { - conf = &wsl.Configuration{ + conf = &wslv4.Configuration{ StrictAppend: settings.StrictAppend, AllowAssignAndCallCuddle: settings.AllowAssignAndCallCuddle, AllowAssignAndAnythingCuddle: settings.AllowAssignAndAnythingCuddle, @@ -30,12 +35,71 @@ func New(settings *config.WSLSettings) *goanalysis.Linter { } } - a := wsl.NewAnalyzer(conf) + return goanalysis. + NewLinterFromAnalyzer(wslv4.NewAnalyzer(conf)). + WithLoadMode(goanalysis.LoadModeSyntax) +} + +// Only used the set YAML struct tags. +type v5YAML struct { + AllowFirstInBlock bool `yaml:"allow-first-in-block"` + AllowWholeBlock bool `yaml:"allow-whole-block"` + BranchMaxLines int `yaml:"branch-max-lines,omitempty"` + CaseMaxLines int `yaml:"case-max-lines,omitempty"` + Enable []string `yaml:"enable,omitempty"` + Disable []string `yaml:"disable,omitempty"` +} + +func Migration(old *config.WSLv4Settings) any { + if old == nil { + return nil + } + + cfg := v5YAML{ + AllowFirstInBlock: true, + AllowWholeBlock: false, + BranchMaxLines: 2, + CaseMaxLines: old.ForceCaseTrailingWhitespaceLimit, + } + + if !old.StrictAppend { + cfg.Disable = append(cfg.Disable, wslv5.CheckAppend.String()) + } + + if old.AllowAssignAndAnythingCuddle { + cfg.Disable = append(cfg.Disable, wslv5.CheckAssign.String()) + } + + if old.AllowMultiLineAssignCuddle { + internal.LinterLogger.Warnf("`allow-multiline-assign` is deprecated and always allowed in wsl >= v5") + } + + if old.AllowTrailingComment { + internal.LinterLogger.Warnf("`allow-trailing-comment` is deprecated and always allowed in wsl >= v5") + } + + if old.AllowSeparatedLeadingComment { + internal.LinterLogger.Warnf("`allow-separated-leading-comment` is deprecated and always allowed in wsl >= v5") + } + + if old.AllowCuddleDeclaration { + cfg.Disable = append(cfg.Disable, wslv5.CheckDecl.String()) + } + + if old.ForceCuddleErrCheckAndAssign { + cfg.Enable = append(cfg.Enable, wslv5.CheckErr.String()) + } + + if old.ForceExclusiveShortDeclarations { + cfg.Enable = append(cfg.Enable, wslv5.CheckAssignExclusive.String()) + } + + if !old.AllowAssignAndCallCuddle { + cfg.Enable = append(cfg.Enable, wslv5.CheckAssignExpr.String()) + } + + slices.Sort(cfg.Enable) + slices.Sort(cfg.Disable) - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return cfg } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go new file mode 100644 index 000000000..cb7b25628 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go @@ -0,0 +1,34 @@ +package wsl + +import ( + "github.com/bombsimon/wsl/v5" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" +) + +func NewV5(settings *config.WSLv5Settings) *goanalysis.Linter { + var conf *wsl.Configuration + + if settings != nil { + checkSet, err := wsl.NewCheckSet(settings.Default, settings.Enable, settings.Disable) + if err != nil { + internal.LinterLogger.Fatalf("wsl: invalid check: %v", err) + } + + 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, + } + } + + return goanalysis. + NewLinterFromAnalyzer(wsl.NewAnalyzer(conf)). + WithVersion(5). //nolint:mnd // It's the linter version. + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/zerologlint/zerologlint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/zerologlint/zerologlint.go index 0daf0d48a..46832da96 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/zerologlint/zerologlint.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/zerologlint/zerologlint.go @@ -2,18 +2,12 @@ package zerologlint import ( "github.com/ykadowak/zerologlint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := zerologlint.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(zerologlint.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goutil/version.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goutil/version.go index 4f42ebd1b..77e5b0f35 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goutil/version.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goutil/version.go @@ -60,9 +60,7 @@ func CleanRuntimeVersion() (string, error) { } func cleanRuntimeVersion(rv string) (string, error) { - parts := strings.Fields(rv) - - for _, part := range parts { + for part := range strings.FieldsSeq(rv) { // Allow to handle: // - GOEXPERIMENT -> "go1.23.0 X:boringcrypto" // - devel -> "devel go1.24-e705a2d Wed Aug 7 01:16:42 2024 +0000 linux/amd64" diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go index a7a9a68d9..a5b98413d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go @@ -1,8 +1,10 @@ package linter import ( + "bytes" "fmt" + "go.yaml.in/yaml/v3" "golang.org/x/tools/go/packages" "github.com/golangci/golangci-lint/v2/pkg/config" @@ -20,10 +22,11 @@ const ( ) type Deprecation struct { - Since string - Message string - Replacement string - Level DeprecationLevel + Since string + Message string + Replacement string + Level DeprecationLevel + ConfigSuggestion func() (string, error) } type Config struct { @@ -119,22 +122,26 @@ func (lc *Config) WithSince(version string) *Config { return lc } -func (lc *Config) Deprecated(message, version, replacement string, level DeprecationLevel) *Config { +func (lc *Config) Deprecated(message, version string, level DeprecationLevel, opts ...func(*Deprecation)) *Config { lc.Deprecation = &Deprecation{ - Since: version, - Message: message, - Replacement: replacement, - Level: level, + Since: version, + Message: message, + Level: level, + } + + for _, opt := range opts { + opt(lc.Deprecation) } + return lc } -func (lc *Config) DeprecatedWarning(message, version, replacement string) *Config { - return lc.Deprecated(message, version, replacement, DeprecationWarning) +func (lc *Config) DeprecatedWarning(message, version string, opts ...func(*Deprecation)) *Config { + return lc.Deprecated(message, version, DeprecationWarning, opts...) } -func (lc *Config) DeprecatedError(message, version, replacement string) *Config { - return lc.Deprecated(message, version, replacement, DeprecationError) +func (lc *Config) DeprecatedError(message, version string, opts ...func(*Deprecation)) *Config { + return lc.Deprecated(message, version, DeprecationError, opts...) } func (lc *Config) IsDeprecated() bool { @@ -160,6 +167,45 @@ func (lc *Config) WithNoopFallback(cfg *config.Config, cond func(cfg *config.Con return lc } +func Replacement[T any](replacement string, mgr func(T) any, data T) func(*Deprecation) { + return func(d *Deprecation) { + if replacement == "" { + return + } + + d.Replacement = replacement + + if mgr == nil { + return + } + + d.ConfigSuggestion = func() (string, error) { + buf := bytes.NewBuffer([]byte{}) + + encoder := yaml.NewEncoder(buf) + encoder.SetIndent(2) + + suggestion := map[string]any{ + "linters": map[string]any{ + "enable": []string{ + d.Replacement, + }, + "settings": map[string]any{ + d.Replacement: mgr(data), + }, + }, + } + + err := encoder.Encode(suggestion) + if err != nil { + return "", fmt.Errorf("%s: invalid configuration: %w", d.Replacement, err) + } + + return buf.String(), nil + } + } +} + func IsGoLowerThanGo122() func(cfg *config.Config) error { return isGoLowerThanGo("1.22") } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/linter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/linter.go index 7f68545cf..e6b484efb 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/linter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/linter.go @@ -8,7 +8,7 @@ import ( ) type Linter interface { - Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) + Run(ctx context.Context, lintCtx *Context) ([]*result.Issue, error) Name() string Desc() string } @@ -43,7 +43,7 @@ func NewNoopDeprecated(name string, cfg *config.Config, level DeprecationLevel) return noop } -func (n Noop) Run(_ context.Context, lintCtx *Context) ([]result.Issue, error) { +func (n Noop) Run(_ context.Context, lintCtx *Context) ([]*result.Issue, error) { if n.reason == "" { return nil, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go index 5ac3e5ba2..6e9cef1d1 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go @@ -3,6 +3,7 @@ package lintersdb import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/golinters" + "github.com/golangci/golangci-lint/v2/pkg/golinters/arangolint" "github.com/golangci/golangci-lint/v2/pkg/golinters/asasalint" "github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk" @@ -18,6 +19,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/dupl" "github.com/golangci/golangci-lint/v2/pkg/golinters/dupword" "github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck" + "github.com/golangci/golangci-lint/v2/pkg/golinters/embeddedstructfieldcheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/err113" "github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson" @@ -41,6 +43,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/goconst" "github.com/golangci/golangci-lint/v2/pkg/golinters/gocritic" "github.com/golangci/golangci-lint/v2/pkg/golinters/gocyclo" + "github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint" "github.com/golangci/golangci-lint/v2/pkg/golinters/godot" "github.com/golangci/golangci-lint/v2/pkg/golinters/godox" "github.com/golangci/golangci-lint/v2/pkg/golinters/gofmt" @@ -61,6 +64,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/ineffassign" "github.com/golangci/golangci-lint/v2/pkg/golinters/interfacebloat" "github.com/golangci/golangci-lint/v2/pkg/golinters/intrange" + "github.com/golangci/golangci-lint/v2/pkg/golinters/iotamixing" "github.com/golangci/golangci-lint/v2/pkg/golinters/ireturn" "github.com/golangci/golangci-lint/v2/pkg/golinters/lll" "github.com/golangci/golangci-lint/v2/pkg/golinters/loggercheck" @@ -69,6 +73,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/mirror" "github.com/golangci/golangci-lint/v2/pkg/golinters/misspell" "github.com/golangci/golangci-lint/v2/pkg/golinters/mnd" + "github.com/golangci/golangci-lint/v2/pkg/golinters/modernize" "github.com/golangci/golangci-lint/v2/pkg/golinters/musttag" "github.com/golangci/golangci-lint/v2/pkg/golinters/nakedret" "github.com/golangci/golangci-lint/v2/pkg/golinters/nestif" @@ -77,6 +82,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/nilnil" "github.com/golangci/golangci-lint/v2/pkg/golinters/nlreturn" "github.com/golangci/golangci-lint/v2/pkg/golinters/noctx" + "github.com/golangci/golangci-lint/v2/pkg/golinters/noinlineerr" "github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint" "github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns" "github.com/golangci/golangci-lint/v2/pkg/golinters/nosprintfhostport" @@ -94,6 +100,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/spancheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/sqlclosecheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/staticcheck" + "github.com/golangci/golangci-lint/v2/pkg/golinters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/golinters/tagalign" "github.com/golangci/golangci-lint/v2/pkg/golinters/tagliatelle" "github.com/golangci/golangci-lint/v2/pkg/golinters/testableexamples" @@ -103,6 +110,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/tparallel" "github.com/golangci/golangci-lint/v2/pkg/golinters/unconvert" "github.com/golangci/golangci-lint/v2/pkg/golinters/unparam" + "github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet" "github.com/golangci/golangci-lint/v2/pkg/golinters/unused" "github.com/golangci/golangci-lint/v2/pkg/golinters/usestdlibvars" "github.com/golangci/golangci-lint/v2/pkg/golinters/usetesting" @@ -135,6 +143,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { // The linters are sorted in the alphabetical order (case-insensitive). // When a new linter is added the version in `WithSince(...)` must be the next minor version of golangci-lint. return []*linter.Config{ + linter.NewConfig(arangolint.New()). + WithSince("v2.2.0"). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Crocmagnon/arangolint"), + linter.NewConfig(asasalint.New(&cfg.Linters.Settings.Asasalint)). WithSince("v1.47.0"). WithLoadForGoAnalysis(). @@ -142,7 +155,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { linter.NewConfig(asciicheck.New()). WithSince("v1.26.0"). - WithURL("https://github.com/tdakkota/asciicheck"), + WithURL("https://github.com/golangci/asciicheck"), linter.NewConfig(bidichk.New(&cfg.Linters.Settings.BiDiChk)). WithSince("v1.43.0"). @@ -205,6 +218,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/charithe/durationcheck"), + linter.NewConfig(embeddedstructfieldcheck.New(&cfg.Linters.Settings.EmbeddedStructFieldCheck)). + WithSince("v2.2.0"). + WithURL("https://github.com/manuelarte/embeddedstructfieldcheck"), + linter.NewConfig(errcheck.New(&cfg.Linters.Settings.Errcheck)). WithGroups(config.GroupStandard). WithSince("v1.0.0"). @@ -228,7 +245,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithURL("https://github.com/polyfloyd/go-errorlint"), linter.NewConfig(exhaustive.New(&cfg.Linters.Settings.Exhaustive)). - WithSince(" v1.28.0"). + WithSince("v1.28.0"). WithLoadForGoAnalysis(). WithURL("https://github.com/nishanths/exhaustive"), @@ -318,6 +335,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.0.0"). WithURL("https://github.com/fzipp/gocyclo"), + linter.NewConfig(godoclint.New(&cfg.Linters.Settings.Godoclint)). + WithSince("v2.5.0"). + WithURL("https://github.com/godoc-lint/godoc-lint"), + linter.NewConfig(godot.New(&cfg.Linters.Settings.Godot)). WithSince("v1.25.0"). WithAutoFix(). @@ -362,6 +383,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.22.0"). WithURL("https://github.com/tommy-muehle/go-mnd"), + linter.NewConfig(modernize.New(&cfg.Linters.Settings.Modernize)). + WithSince("v2.6.0"). + WithLoadForGoAnalysis(). + WithURL("https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize"), + linter.NewConfig(gomoddirectives.New(&cfg.Linters.Settings.GoModDirectives)). WithSince("v1.39.0"). WithURL("https://github.com/ldez/gomoddirectives"), @@ -411,7 +437,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.55.0"). WithURL("https://github.com/macabu/inamedparam"), - linter.NewConfig(ineffassign.New()). + linter.NewConfig(ineffassign.New(&cfg.Linters.Settings.Ineffassign)). WithGroups(config.GroupStandard). WithSince("v1.0.0"). WithURL("https://github.com/gordonklaus/ineffassign"), @@ -427,6 +453,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithURL("https://github.com/ckaznocha/intrange"). WithNoopFallback(cfg, linter.IsGoLowerThanGo122()), + linter.NewConfig(iotamixing.New(&cfg.Linters.Settings.IotaMixing)). + WithSince("v2.5.0"). + WithURL("https://github.com/AdminBenni/iota-mixing"), + linter.NewConfig(ireturn.New(&cfg.Linters.Settings.Ireturn)). WithSince("v1.43.0"). WithLoadForGoAnalysis(). @@ -499,6 +529,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/sonatard/noctx"), + linter.NewConfig(noinlineerr.New()). + WithSince("v2.2.0"). + WithLoadForGoAnalysis(). + WithURL("https://github.com/AlwxSin/noinlineerr"), + linter.NewConfig(nonamedreturns.New(&cfg.Linters.Settings.NoNamedReturns)). WithSince("v1.46.0"). WithLoadForGoAnalysis(). @@ -579,7 +614,12 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.0.0"). WithLoadForGoAnalysis(). WithAutoFix(). - WithURL("https://staticcheck.dev/"), + WithURL("https://github.com/dominikh/go-tools"), + + linter.NewConfig(swaggo.New()). + WithSince("v2.2.0"). + WithAutoFix(). + WithURL("https://github.com/swaggo/swaggo"), linter.NewConfig(tagalign.New(&cfg.Linters.Settings.TagAlign)). WithSince("v1.53.0"). @@ -629,6 +669,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/mvdan/unparam"), + linter.NewConfig(unqueryvet.New(&cfg.Linters.Settings.Unqueryvet)). + WithSince("v2.5.0"). + WithURL("https://github.com/MirrexOne/unqueryvet"), + linter.NewConfig(unused.New(&cfg.Linters.Settings.Unused)). WithGroups(config.GroupStandard). WithSince("v1.20.0"). @@ -668,11 +712,19 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/tomarrell/wrapcheck"), - linter.NewConfig(wsl.New(&cfg.Linters.Settings.WSL)). + linter.NewConfig(wsl.NewV4(&cfg.Linters.Settings.WSL)). + DeprecatedWarning("new major version.", "v2.2.0", + linter.Replacement("wsl_v5", wsl.Migration, &cfg.Linters.Settings.WSL)). WithSince("v1.20.0"). WithAutoFix(). WithURL("https://github.com/bombsimon/wsl"), + linter.NewConfig(wsl.NewV5(&cfg.Linters.Settings.WSLv5)). + WithSince("v2.2.0"). + WithLoadForGoAnalysis(). + WithAutoFix(). + WithURL("https://github.com/bombsimon/wsl"), + linter.NewConfig(zerologlint.New()). WithSince("v1.53.0"). WithLoadForGoAnalysis(). diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go index 00a801ad6..005ca6169 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go @@ -132,7 +132,7 @@ func (b *PluginGoBuilder) lookupAnalyzerPlugin(plug *plugin.Plugin) ([]*analysis } b.log.Warnf("plugin: 'AnalyzerPlugin' plugins are deprecated, please use the new plugin signature: " + - "https://golangci-lint.run/plugins/go-plugins#create-a-plugin") + "https://golangci-lint.run/docs/plugins/go-plugins#create-a-plugin") analyzerPlugin, ok := symbol.(AnalyzerPlugin) if !ok { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/validator.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/validator.go index 912748250..34a6c63f9 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/validator.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/validator.go @@ -55,7 +55,7 @@ func (v Validator) validateLintersNames(cfg *config.Linters) error { if lc.IsDeprecated() && lc.Deprecation.Level > linter.DeprecationWarning { v.m.log.Warnf("The linter %q is deprecated (step 2) and deactivated. "+ "It should be removed from the list of disabled linters. "+ - "https://golangci-lint.run/product/roadmap/#linter-deprecation-cycle", lc.Name()) + "https://golangci-lint.run/docs/product/roadmap/#linter-deprecation-cycle", lc.Name()) } } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/runner.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/runner.go index 5ede9b24d..ba7750f28 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/runner.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/runner.go @@ -118,17 +118,17 @@ func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env, }, nil } -func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]result.Issue, error) { +func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]*result.Issue, error) { sw := timeutils.NewStopwatch("linters", r.Log) defer sw.Print() var ( lintErrors error - issues []result.Issue + issues []*result.Issue ) for _, lc := range linters { - linterIssues, err := timeutils.TrackStage(sw, lc.Name(), func() ([]result.Issue, error) { + linterIssues, err := timeutils.TrackStage(sw, lc.Name(), func() ([]*result.Issue, error) { return r.runLinterSafe(ctx, r.lintCtx, lc) }) if err != nil { @@ -146,7 +146,7 @@ func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]result.Is func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, lc *linter.Config, -) (ret []result.Issue, err error) { +) (ret []*result.Issue, err error) { defer func() { if panicData := recover(); panicData != nil { if pe, ok := panicData.(*errorutil.PanicError); ok { @@ -185,13 +185,13 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, return issues, nil } -func (r *Runner) processLintResults(inIssues []result.Issue) []result.Issue { +func (r *Runner) processLintResults(inIssues []*result.Issue) []*result.Issue { sw := timeutils.NewStopwatch("processing", r.Log) var issuesBefore, issuesAfter int statPerProcessor := map[string]processorStat{} - var outIssues []result.Issue + var outIssues []*result.Issue if len(inIssues) != 0 { issuesBefore += len(inIssues) outIssues = r.processIssues(inIssues, sw, statPerProcessor) @@ -225,14 +225,14 @@ func (r *Runner) printPerProcessorStat(stat map[string]processorStat) { } } -func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue { +func (r *Runner) processIssues(issues []*result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []*result.Issue { for _, p := range r.Processors { - newIssues, err := timeutils.TrackStage(sw, p.Name(), func() ([]result.Issue, error) { + newIssues, err := timeutils.TrackStage(sw, p.Name(), func() ([]*result.Issue, error) { return p.Process(issues) }) if err != nil { - r.Log.Warnf("Can't process result by %s processor: %s", p.Name(), err) + r.Log.Warnf("Can't process results by %s processor: %s", p.Name(), err) } else { stat := statPerProcessor[p.Name()] stat.inCount += len(issues) @@ -243,7 +243,7 @@ func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, s // This is required by JSON serialization if issues == nil { - issues = []result.Issue{} + issues = []*result.Issue{} } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/logutils.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/logutils.go index 0ee48a366..50b8fa3f3 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/logutils.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/logutils.go @@ -16,23 +16,20 @@ const EnvTestRun = "GL_TEST_RUN" const envDebug = "GL_DEBUG" const ( - DebugKeyBinSalt = "bin_salt" - DebugKeyGoModSalt = "gomod_salt" - DebugKeyConfigReader = "config_reader" - DebugKeyEmpty = "" - DebugKeyEnabledLinters = "enabled_linters" - DebugKeyExec = "exec" - DebugKeyFormatter = "formatter" - DebugKeyFormattersOutput = "formatters_output" - DebugKeyGoEnv = "goenv" - DebugKeyLintersContext = "linters_context" - DebugKeyLintersDB = "lintersdb" - DebugKeyLintersOutput = "linters_output" - DebugKeyLoader = "loader" // Debugs packages loading (including `go/packages` internal debugging). - DebugKeyPkgCache = "pkgcache" - DebugKeyRunner = "runner" - DebugKeyStopwatch = "stopwatch" - DebugKeyTest = "test" + DebugKeyBinSalt = "bin_salt" // Forces the usage of constant as salt (only for maintainers). + DebugKeyGoModSalt = "gomod_salt" // Display logs related to the salt computation from the go.mod file. + DebugKeyConfigReader = "config_reader" // Display logs related to configuration loading. + DebugKeyEmpty = "" + DebugKeyEnabledLinters = "enabled_linters" // Display logs related to the enabled linters inside the [lintersdb.Manager]. + DebugKeyExec = "exec" // Display logs related to the lock file. + DebugKeyGoEnv = "goenv" // Display logs related to [goenv.Env]. + DebugKeyLintersContext = "linters_context" // Display logs related to the package analysis context (not related to [context.Context]). + DebugKeyLintersDB = "lintersdb" // Display logs related to the linters/formatters loading. + DebugKeyLoader = "loader" // Display logs related to package loading (including `go/packages` internal debugging). + DebugKeyPkgCache = "pkgcache" // Display logs related to cache. + DebugKeyRunner = "runner" // Display logs related to the linter runner. + DebugKeyStopwatch = "stopwatch" // Display logs related to the stopwatch of the cache. + DebugKeyTest = "test" // Display debug logs during integration tests. ) // Printers. @@ -59,7 +56,6 @@ const ( DebugKeyPathPrettifier = "path_prettifier" DebugKeyPathRelativity = "path_relativity" DebugKeySeverityRules = "severity_rules" - DebugKeySkipDirs = "skip_dirs" DebugKeySourceCode = "source_code" ) @@ -77,13 +73,18 @@ const ( DebugKeyGoAnalysisFactsInherit = DebugKeyGoAnalysisFacts + "/inherit" ) -// Linters. +// Linters and Formatters. const ( - DebugKeyForbidigo = "forbidigo" // Debugs `forbidigo` linter. - DebugKeyGoCritic = "gocritic" // Debugs `gocritic` linter. - DebugKeyGovet = "govet" // Debugs `govet` linter. - DebugKeyLinter = "linter" - DebugKeyRevive = "revive" // Debugs `revive` linter. + DebugKeyFormatter = "formatter" // Display logs from the shared logger for formatters. + DebugKeyFormattersOutput = "formatters_output" // Display logs from formatters themselves. + DebugKeyLinter = "linter" // Display logs from the shared logger for linters. + DebugKeyLintersOutput = "linters_output" // Display logs from linters themselves. + + DebugKeyForbidigo = "forbidigo" // Debugs `forbidigo` linter. + DebugKeyGoCritic = "gocritic" // Debugs `gocritic` linter. + DebugKeyGovet = "govet" // Debugs `govet` linter. + DebugKeyRevive = "revive" // Debugs `revive` linter. + DebugKeyStaticcheck = "staticcheck" // Debugs `staticcheck` linter. ) func getEnabledDebugs() map[string]bool { @@ -93,7 +94,7 @@ func getEnabledDebugs() map[string]bool { return ret } - for _, tag := range strings.Split(debugVar, ",") { + for tag := range strings.SplitSeq(debugVar, ",") { ret[tag] = true } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/stderr_log.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/stderr_log.go index b47c65eac..af4296429 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/stderr_log.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/logutils/stderr_log.go @@ -17,14 +17,14 @@ const ( envLogTimestamp = "LOG_TIMESTAMP" ) +var _ Log = NewStderrLog(DebugKeyEmpty) + type StderrLog struct { name string logger *logrus.Logger level LogLevel } -var _ Log = NewStderrLog(DebugKeyEmpty) - func NewStderrLog(name string) *StderrLog { sl := &StderrLog{ name: name, @@ -44,16 +44,7 @@ func NewStderrLog(name string) *StderrLog { } sl.logger.Out = StdErr - formatter := &logrus.TextFormatter{ - DisableTimestamp: true, // `INFO[0007] msg` -> `INFO msg` - EnvironmentOverrideColors: true, - } - if os.Getenv(envLogTimestamp) == "1" { - formatter.DisableTimestamp = false - formatter.FullTimestamp = true - formatter.TimestampFormat = time.StampMilli - } - sl.logger.Formatter = formatter + sl.logger.Formatter = logFormatter return sl } @@ -127,3 +118,24 @@ func (sl StderrLog) Child(name string) Log { func (sl *StderrLog) SetLevel(level LogLevel) { sl.level = level } + +var logFormatter = newLogFormatter() + +func DisableColors(disable bool) { + logFormatter.DisableColors = disable +} + +func newLogFormatter() *logrus.TextFormatter { + formatter := &logrus.TextFormatter{ + DisableTimestamp: true, // `INFO[0007] msg` -> `INFO msg` + EnvironmentOverrideColors: true, + } + + if os.Getenv(envLogTimestamp) == "1" { + formatter.DisableTimestamp = false + formatter.FullTimestamp = true + formatter.TimestampFormat = time.StampMilli + } + + return formatter +} diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/checkstyle.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/checkstyle.go index 5a60554bd..c3869bd39 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/checkstyle.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/checkstyle.go @@ -37,15 +37,14 @@ func NewCheckstyle(log logutils.Log, w io.Writer) *Checkstyle { } } -func (p *Checkstyle) Print(issues []result.Issue) error { +func (p *Checkstyle) Print(issues []*result.Issue) error { out := checkstyleOutput{ Version: "5.0", } files := map[string]*checkstyleFile{} - for i := range issues { - issue := &issues[i] + for _, issue := range issues { file, ok := files[issue.FilePath()] if !ok { file = &checkstyleFile{ diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/codeclimate.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/codeclimate.go index 872d860d3..e2eded608 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/codeclimate.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/codeclimate.go @@ -30,12 +30,10 @@ func NewCodeClimate(log logutils.Log, w io.Writer) *CodeClimate { } } -func (p *CodeClimate) Print(issues []result.Issue) error { +func (p *CodeClimate) Print(issues []*result.Issue) error { ccIssues := make([]codeClimateIssue, 0, len(issues)) - for i := range issues { - issue := issues[i] - + for _, issue := range issues { ccIssue := codeClimateIssue{ Description: issue.Description(), CheckName: issue.FromLinter, diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/html.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/html.go index 0f99bb7ff..1f6ed1834 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/html.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/html.go @@ -132,20 +132,20 @@ func NewHTML(w io.Writer) *HTML { return &HTML{w: w} } -func (p HTML) Print(issues []result.Issue) error { +func (p HTML) Print(issues []*result.Issue) error { var htmlIssues []htmlIssue - for i := range issues { - pos := fmt.Sprintf("%s:%d", issues[i].FilePath(), issues[i].Line()) - if issues[i].Pos.Column != 0 { - pos += fmt.Sprintf(":%d", issues[i].Pos.Column) + for _, issue := range issues { + pos := fmt.Sprintf("%s:%d", issue.FilePath(), issue.Line()) + if issue.Pos.Column != 0 { + pos += fmt.Sprintf(":%d", issue.Pos.Column) } htmlIssues = append(htmlIssues, htmlIssue{ - Title: strings.TrimSpace(issues[i].Text), + Title: strings.TrimSpace(issue.Text), Pos: pos, - Linter: issues[i].FromLinter, - Code: strings.Join(issues[i].SourceLines, "\n"), + Linter: issue.FromLinter, + Code: strings.Join(issue.SourceLines, "\n"), }) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/json.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/json.go index 64fd33c7b..97354081c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/json.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/json.go @@ -22,17 +22,17 @@ func NewJSON(w io.Writer, rd *report.Data) *JSON { } type JSONResult struct { - Issues []result.Issue + Issues []*result.Issue Report *report.Data } -func (p JSON) Print(issues []result.Issue) error { +func (p JSON) Print(issues []*result.Issue) error { res := JSONResult{ Issues: issues, Report: p.rd, } if res.Issues == nil { - res.Issues = []result.Issue{} + res.Issues = []*result.Issue{} } return json.NewEncoder(p.w).Encode(res) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/junitxml.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/junitxml.go index 708f83e5a..b040e7467 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/junitxml.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/junitxml.go @@ -27,31 +27,30 @@ func NewJUnitXML(w io.Writer, extended bool) *JUnitXML { } } -func (p JUnitXML) Print(issues []result.Issue) error { +func (p JUnitXML) Print(issues []*result.Issue) error { suites := make(map[string]testSuiteXML) // use a map to group by file - for ind := range issues { - i := &issues[ind] - suiteName := i.FilePath() + for _, issue := range issues { + suiteName := issue.FilePath() testSuite := suites[suiteName] - testSuite.Suite = i.FilePath() + testSuite.Suite = issue.FilePath() testSuite.Tests++ testSuite.Failures++ tc := testCaseXML{ - Name: i.FromLinter, - ClassName: i.Pos.String(), + Name: issue.FromLinter, + ClassName: issue.Pos.String(), Failure: failureXML{ - Type: i.Severity, - Message: i.Pos.String() + ": " + i.Text, + Type: issue.Severity, + Message: issue.Pos.String() + ": " + issue.Text, Content: fmt.Sprintf("%s: %s\nCategory: %s\nFile: %s\nLine: %d\nDetails: %s", - i.Severity, i.Text, i.FromLinter, i.Pos.Filename, i.Pos.Line, strings.Join(i.SourceLines, "\n")), + issue.Severity, issue.Text, issue.FromLinter, issue.Pos.Filename, issue.Pos.Line, strings.Join(issue.SourceLines, "\n")), }, } if p.extended { - tc.File = i.Pos.Filename - tc.Line = i.Pos.Line + tc.File = issue.Pos.Filename + tc.Line = issue.Pos.Line } testSuite.TestCases = append(testSuite.TestCases, tc) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/printer.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/printer.go index 575bba75f..bb3eab620 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/printer.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/printer.go @@ -23,7 +23,7 @@ const ( const defaultFileMode = 0o644 type issuePrinter interface { - Print(issues []result.Issue) error + Print(issues []*result.Issue) error } // Printer prints issues. @@ -63,7 +63,7 @@ func NewPrinter(log logutils.Log, cfg *config.Formats, reportData *report.Data, // Print prints issues based on the formats defined. // //nolint:gocyclo,funlen // the complexity is related to the number of formats. -func (c *Printer) Print(issues []result.Issue) error { +func (c *Printer) Print(issues []*result.Issue) error { if c.cfg.IsEmpty() { c.cfg.Text.Path = outputStdOut } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/sarif.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/sarif.go index e8d8c64f7..e1caf179a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/sarif.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/sarif.go @@ -36,14 +36,12 @@ func NewSarif(log logutils.Log, w io.Writer) *Sarif { } } -func (p *Sarif) Print(issues []result.Issue) error { +func (p *Sarif) Print(issues []*result.Issue) error { run := sarifRun{} run.Tool.Driver.Name = "golangci-lint" run.Results = make([]sarifResult, 0) - for i := range issues { - issue := issues[i] - + for _, issue := range issues { sr := sarifResult{ RuleID: issue.FromLinter, Level: p.sanitizer.Sanitize(issue.Severity), diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/tab.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/tab.go index 0d14593e5..8edbb05e1 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/tab.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/tab.go @@ -40,11 +40,11 @@ func (p *Tab) SprintfColored(ca color.Attribute, format string, args ...any) str return c.Sprintf(format, args...) } -func (p *Tab) Print(issues []result.Issue) error { +func (p *Tab) Print(issues []*result.Issue) error { w := tabwriter.NewWriter(p.w, 0, 0, 2, ' ', 0) - for i := range issues { - p.printIssue(&issues[i], w) + for _, issue := range issues { + p.printIssue(issue, w) } if err := w.Flush(); err != nil { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/teamcity.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/teamcity.go index a85307729..36114fedf 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/teamcity.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/teamcity.go @@ -48,12 +48,10 @@ func NewTeamCity(log logutils.Log, w io.Writer) *TeamCity { } } -func (p *TeamCity) Print(issues []result.Issue) error { +func (p *TeamCity) Print(issues []*result.Issue) error { uniqLinters := map[string]struct{}{} - for i := range issues { - issue := issues[i] - + for _, issue := range issues { _, ok := uniqLinters[issue.FromLinter] if !ok { inspectionType := InspectionType{ diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/text.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/text.go index 545679fb7..eb9297615 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/text.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/printers/text.go @@ -42,16 +42,16 @@ func (p *Text) SprintfColored(ca color.Attribute, format string, args ...any) st return c.Sprintf(format, args...) } -func (p *Text) Print(issues []result.Issue) error { - for i := range issues { - p.printIssue(&issues[i]) +func (p *Text) Print(issues []*result.Issue) error { + for _, issue := range issues { + p.printIssue(issue) if !p.printIssuedLine { continue } - p.printSourceCode(&issues[i]) - p.printUnderLinePointer(&issues[i]) + p.printSourceCode(issue) + p.printUnderLinePointer(issue) } return nil diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/report/log.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/report/log.go index ad0964151..c964af559 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/report/log.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/report/log.go @@ -2,6 +2,7 @@ package report import ( "fmt" + "slices" "strings" "github.com/golangci/golangci-lint/v2/pkg/logutils" @@ -50,7 +51,7 @@ func (lw LogWrapper) Infof(format string, args ...any) { func (lw LogWrapper) Child(name string) logutils.Log { c := lw c.origLog = lw.origLog.Child(name) - c.tags = append([]string{}, lw.tags...) + c.tags = slices.Clone(lw.tags) c.tags = append(c.tags, name) return c } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/issue.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/issue.go index 86a4ef3b7..2587ffff2 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/issue.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/issue.go @@ -32,7 +32,7 @@ type Issue struct { // HunkPos is used only when golangci-lint is run over a diff HunkPos int `json:",omitempty"` - // If we know how to fix the issue we can provide replacement lines + // If we know how to fix the issue, we can provide replacement lines SuggestedFixes []analysis.SuggestedFix `json:",omitempty"` // If we are expecting a nolint (because this is from nolintlint), record the expected linter @@ -42,7 +42,7 @@ type Issue struct { // Only for Diff processor needs. WorkingDirectoryRelativePath string `json:"-"` - // Only for processor that need relative paths evaluation. + // Only for processors that need relative paths evaluation. RelativePath string `json:"-"` } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/base_rule.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/base_rule.go index 607886ef1..468866248 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/base_rule.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/base_rule.go @@ -2,6 +2,7 @@ package processors import ( "regexp" + "slices" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/fsutils" @@ -73,13 +74,7 @@ func (r *baseRule) match(issue *result.Issue, lines *fsutils.LineCache, log logu } func (r *baseRule) matchLinter(issue *result.Issue) bool { - for _, linter := range r.linters { - if linter == issue.FromLinter { - return true - } - } - - return false + return slices.Contains(r.linters, issue.FromLinter) } func (r *baseRule) matchSource(issue *result.Issue, lineCache *fsutils.LineCache, log logutils.Log) bool { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/cgo.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/cgo.go index dea3801e2..4cc7b57db 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/cgo.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/cgo.go @@ -31,7 +31,7 @@ func (*Cgo) Name() string { return "cgo" } -func (p *Cgo) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *Cgo) Process(issues []*result.Issue) ([]*result.Issue, error) { return filterIssuesErr(issues, p.shouldPassIssue) } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/diff.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/diff.go index a84caf7b6..15574ff0d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/diff.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/diff.go @@ -48,7 +48,7 @@ func (*Diff) Name() string { return "diff" } -func (p *Diff) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *Diff) Process(issues []*result.Issue) ([]*result.Issue, error) { if !p.onlyNew && p.fromRev == "" && p.fromMergeBase == "" && p.patchFilePath == "" && p.patch == "" { return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_generated_file_filter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_generated_file_filter.go index 6cbde3aed..d76ec3184 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_generated_file_filter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_generated_file_filter.go @@ -40,7 +40,7 @@ func (*GeneratedFileFilter) Name() string { return "generated_file_filter" } -func (p *GeneratedFileFilter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *GeneratedFileFilter) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.mode == config.GeneratedModeDisable { return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_paths.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_paths.go index 104c33eef..acf13edd0 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_paths.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_paths.go @@ -68,7 +68,7 @@ func (*ExclusionPaths) Name() string { return "exclusion_paths" } -func (p *ExclusionPaths) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *ExclusionPaths) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.pathPatterns) == 0 && len(p.pathExceptPatterns) == 0 { return issues, nil } @@ -114,5 +114,5 @@ func (p *ExclusionPaths) shouldPassIssue(issue *result.Issue) bool { matched = true } - return !matched + return matched } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_rules.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_rules.go index 064921ae6..2b5221a89 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_rules.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/exclusion_rules.go @@ -49,7 +49,7 @@ func (*ExclusionRules) Name() string { return "exclusion_rules" } -func (p *ExclusionRules) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *ExclusionRules) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.rules) == 0 { return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/filename_unadjuster.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/filename_unadjuster.go index a3cdd8e6e..e39601d5a 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/filename_unadjuster.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/filename_unadjuster.go @@ -66,7 +66,7 @@ func (*FilenameUnadjuster) Name() string { return "filename_unadjuster" } -func (p *FilenameUnadjuster) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *FilenameUnadjuster) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { mapper := p.m[issue.FilePath()] if mapper == nil { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/fixer.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/fixer.go index 14dd3454e..ce33b27fb 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/fixer.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/fixer.go @@ -22,6 +22,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt" "github.com/golangci/golangci-lint/v2/pkg/goformatters/goimports" "github.com/golangci/golangci-lint/v2/pkg/goformatters/golines" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/logutils" "github.com/golangci/golangci-lint/v2/pkg/result" "github.com/golangci/golangci-lint/v2/pkg/timeutils" @@ -55,14 +56,14 @@ func (Fixer) Name() string { return "fixer" } -func (p Fixer) Process(issues []result.Issue) ([]result.Issue, error) { +func (p Fixer) Process(issues []*result.Issue) ([]*result.Issue, error) { if !p.cfg.Issues.NeedFix { return issues, nil } p.log.Infof("Applying suggested fixes") - notFixableIssues, err := timeutils.TrackStage(p.sw, "all", func() ([]result.Issue, error) { + notFixableIssues, err := timeutils.TrackStage(p.sw, "all", func() ([]*result.Issue, error) { return p.process(issues) }) if err != nil { @@ -75,13 +76,13 @@ func (p Fixer) Process(issues []result.Issue) ([]result.Issue, error) { } //nolint:funlen,gocyclo // This function should not be split. -func (p Fixer) process(issues []result.Issue) ([]result.Issue, error) { +func (p Fixer) process(issues []*result.Issue) ([]*result.Issue, error) { // filenames / linters / edits editsByLinter := make(map[string]map[string][]diff.Edit) - formatters := []string{gofumpt.Name, goimports.Name, gofmt.Name, gci.Name, golines.Name} + formatters := []string{gofumpt.Name, goimports.Name, gofmt.Name, gci.Name, golines.Name, swaggo.Name} - var notFixableIssues []result.Issue + var notFixableIssues []*result.Issue toBeFormattedFiles := make(map[string]struct{}) @@ -93,7 +94,7 @@ func (p Fixer) process(issues []result.Issue) ([]result.Issue, error) { continue } - if issue.SuggestedFixes == nil || skipNoTextEdit(&issue) { + if issue.SuggestedFixes == nil || skipNoTextEdit(issue) { notFixableIssues = append(notFixableIssues, issue) continue } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/invalid_issue.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/invalid_issue.go index a7f45d408..fa1b19e82 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/invalid_issue.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/invalid_issue.go @@ -24,7 +24,7 @@ func (InvalidIssue) Name() string { return "invalid_issue" } -func (p InvalidIssue) Process(issues []result.Issue) ([]result.Issue, error) { +func (p InvalidIssue) Process(issues []*result.Issue) ([]*result.Issue, error) { tcIssues := filterIssuesUnsafe(issues, func(issue *result.Issue) bool { return issue.FromLinter == typeCheckName }) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/issues.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/issues.go index 1e76291c7..cc4deeb52 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/issues.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/issues.go @@ -6,62 +6,62 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -func filterIssues(issues []result.Issue, filter func(issue *result.Issue) bool) []result.Issue { - retIssues := make([]result.Issue, 0, len(issues)) - for i := range issues { - if issues[i].FromLinter == typeCheckName { +func filterIssues(issues []*result.Issue, filter func(issue *result.Issue) bool) []*result.Issue { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + if issue.FromLinter == typeCheckName { // don't hide typechecking errors in generated files: users expect to see why the project isn't compiling - retIssues = append(retIssues, issues[i]) + retIssues = append(retIssues, issue) continue } - if filter(&issues[i]) { - retIssues = append(retIssues, issues[i]) + if filter(issue) { + retIssues = append(retIssues, issue) } } return retIssues } -func filterIssuesUnsafe(issues []result.Issue, filter func(issue *result.Issue) bool) []result.Issue { - retIssues := make([]result.Issue, 0, len(issues)) - for i := range issues { - if filter(&issues[i]) { - retIssues = append(retIssues, issues[i]) +func filterIssuesUnsafe(issues []*result.Issue, filter func(issue *result.Issue) bool) []*result.Issue { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + if filter(issue) { + retIssues = append(retIssues, issue) } } return retIssues } -func filterIssuesErr(issues []result.Issue, filter func(issue *result.Issue) (bool, error)) ([]result.Issue, error) { - retIssues := make([]result.Issue, 0, len(issues)) - for i := range issues { - if issues[i].FromLinter == typeCheckName { +func filterIssuesErr(issues []*result.Issue, filter func(issue *result.Issue) (bool, error)) ([]*result.Issue, error) { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + if issue.FromLinter == typeCheckName { // don't hide typechecking errors in generated files: users expect to see why the project isn't compiling - retIssues = append(retIssues, issues[i]) + retIssues = append(retIssues, issue) continue } - ok, err := filter(&issues[i]) + ok, err := filter(issue) if err != nil { - return nil, fmt.Errorf("can't filter issue %#v: %w", issues[i], err) + return nil, fmt.Errorf("can't filter issue %#v: %w", issue, err) } if ok { - retIssues = append(retIssues, issues[i]) + retIssues = append(retIssues, issue) } } return retIssues, nil } -func transformIssues(issues []result.Issue, transform func(issue *result.Issue) *result.Issue) []result.Issue { - retIssues := make([]result.Issue, 0, len(issues)) - for i := range issues { - newIssue := transform(&issues[i]) +func transformIssues(issues []*result.Issue, transform func(issue *result.Issue) *result.Issue) []*result.Issue { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + newIssue := transform(issue) if newIssue != nil { - retIssues = append(retIssues, *newIssue) + retIssues = append(retIssues, newIssue) } } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_from_linter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_from_linter.go index dec9f3e7f..bc7572f2c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_from_linter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_from_linter.go @@ -29,7 +29,7 @@ func (*MaxFromLinter) Name() string { return "max_from_linter" } -func (p *MaxFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *MaxFromLinter) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.limit <= 0 { // no limit return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_per_file_from_linter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_per_file_from_linter.go index fdb6bb027..b04b92ea7 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_per_file_from_linter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_per_file_from_linter.go @@ -7,6 +7,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt" "github.com/golangci/golangci-lint/v2/pkg/goformatters/goimports" "github.com/golangci/golangci-lint/v2/pkg/goformatters/golines" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/result" ) @@ -24,7 +25,7 @@ func NewMaxPerFileFromLinter(cfg *config.Config) *MaxPerFileFromLinter { if !cfg.Issues.NeedFix { // if we don't fix we do this limiting to not annoy user; // otherwise we need to fix all issues in the file at once - for _, f := range []string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name} { + for _, f := range []string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name, swaggo.Name} { maxPerFileFromLinterConfig[f] = 1 } } @@ -39,7 +40,7 @@ func (*MaxPerFileFromLinter) Name() string { return "max_per_file_from_linter" } -func (p *MaxPerFileFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *MaxPerFileFromLinter) Process(issues []*result.Issue) ([]*result.Issue, error) { return filterIssuesUnsafe(issues, func(issue *result.Issue) bool { limit := p.maxPerFileFromLinterConfig[issue.FromLinter] if limit == 0 { diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_same_issues.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_same_issues.go index 06e87586e..ba22cf31f 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_same_issues.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/max_same_issues.go @@ -31,7 +31,7 @@ func (*MaxSameIssues) Name() string { return "max_same_issues" } -func (p *MaxSameIssues) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *MaxSameIssues) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.limit <= 0 { // no limit return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/nolint_filter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/nolint_filter.go index 96fd6403e..b1ba3be1e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/nolint_filter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/nolint_filter.go @@ -91,7 +91,7 @@ func (*NolintFilter) Name() string { return "nolint_filter" } -func (p *NolintFilter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *NolintFilter) Process(issues []*result.Issue) ([]*result.Issue, error) { // put nolintlint issues last because we process other issues first to determine which nolint directives are unused sort.Stable(sortWithNolintlintLast(issues)) return filterIssuesErr(issues, p.shouldPassIssue) @@ -185,8 +185,7 @@ func (p *NolintFilter) buildIgnoredRangesForFile(f *ast.File, fset *token.FileSe ast.Walk(&e, f) // TODO: merge all ranges: there are repeated ranges - allRanges := append([]ignoredRange{}, inlineRanges...) - allRanges = append(allRanges, e.expandedRanges...) + allRanges := slices.Concat(inlineRanges, e.expandedRanges) return allRanges } @@ -228,11 +227,12 @@ func (p *NolintFilter) extractInlineRangeFromComment(text string, g ast.Node, fs return buildRange(nil) // ignore all linters } + text, _, _ = strings.Cut(text, "//") // allow another comment after this comment + // ignore specific linters var linters []string - text = strings.Split(text, "//")[0] // allow another comment after this comment - linterItems := strings.Split(strings.TrimPrefix(text, "nolint:"), ",") - for _, item := range linterItems { + + for item := range strings.SplitSeq(strings.TrimPrefix(text, "nolint:"), ",") { linterName := strings.ToLower(strings.TrimSpace(item)) if linterName == "all" { p.unknownLintersSet = map[string]bool{} @@ -300,7 +300,7 @@ func (e *rangeExpander) Visit(node ast.Node) ast.Visitor { } // put nolintlint last -type sortWithNolintlintLast []result.Issue +type sortWithNolintlintLast []*result.Issue func (issues sortWithNolintlintLast) Len() int { return len(issues) diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_absoluter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_absoluter.go index 99f3de42a..240cedf8e 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_absoluter.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_absoluter.go @@ -22,7 +22,7 @@ func (*PathAbsoluter) Name() string { return "path_absoluter" } -func (p *PathAbsoluter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *PathAbsoluter) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { if filepath.IsAbs(issue.FilePath()) { return issue diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_prettifier.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_prettifier.go index cb6ef8ebc..94dfbab37 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_prettifier.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_prettifier.go @@ -30,7 +30,7 @@ func (*PathPrettifier) Name() string { return "path_prettifier" } -func (p *PathPrettifier) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *PathPrettifier) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.cfg.PathMode == fsutils.OutputPathModeAbsolute { return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_relativity.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_relativity.go index 8b2958a4a..c68662c7b 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_relativity.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_relativity.go @@ -36,7 +36,7 @@ func (*PathRelativity) Name() string { return "path_relativity" } -func (p *PathRelativity) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *PathRelativity) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { newIssue := *issue diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_shortener.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_shortener.go index 7a14c39c9..23df4f02c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_shortener.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/path_shortener.go @@ -29,7 +29,7 @@ func (PathShortener) Name() string { return "path_shortener" } -func (p PathShortener) Process(issues []result.Issue) ([]result.Issue, error) { +func (p PathShortener) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { newIssue := issue newIssue.Text = strings.ReplaceAll(newIssue.Text, p.wd+"/", "") diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/processor.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/processor.go index 1976d6e44..f5603c94d 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/processor.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/processor.go @@ -7,7 +7,7 @@ import ( const typeCheckName = "typecheck" type Processor interface { - Process(issues []result.Issue) ([]result.Issue, error) + Process(issues []*result.Issue) ([]*result.Issue, error) Name() string Finish() } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/severity.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/severity.go index 035ca80c4..33c3997f8 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/severity.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/severity.go @@ -43,7 +43,7 @@ func NewSeverity(log logutils.Log, lines *fsutils.LineCache, cfg *config.Severit func (p *Severity) Name() string { return p.name } -func (p *Severity) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *Severity) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.rules) == 0 && p.defaultSeverity == "" { return issues, nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/sort_results.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/sort_results.go index 033eca9a4..8ba06bccf 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/sort_results.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/sort_results.go @@ -54,7 +54,7 @@ func NewSortResults(cfg *config.Output) *SortResults { func (SortResults) Name() string { return "sort_results" } // Process is performing sorting of the result issues. -func (p SortResults) Process(issues []result.Issue) ([]result.Issue, error) { +func (p SortResults) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.cfg.SortOrder) == 0 { p.cfg.SortOrder = []string{orderNameLinter, orderNameFile} } @@ -72,8 +72,8 @@ func (p SortResults) Process(issues []result.Issue) ([]result.Issue, error) { comp := mergeComparators(cmps...) - slices.SortFunc(issues, func(a, b result.Issue) int { - return comp(&a, &b) + slices.SortFunc(issues, func(a, b *result.Issue) int { + return comp(a, b) }) return issues, nil diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/source_code.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/source_code.go index 1096269c8..d4e82643c 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/source_code.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/source_code.go @@ -31,7 +31,7 @@ func (SourceCode) Name() string { return "source_code" } -func (p SourceCode) Process(issues []result.Issue) ([]result.Issue, error) { +func (p SourceCode) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, p.transform), nil } diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/uniq_by_line.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/uniq_by_line.go index 113b5814a..953496355 100644 --- a/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/uniq_by_line.go +++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/result/processors/uniq_by_line.go @@ -25,7 +25,7 @@ func (*UniqByLine) Name() string { return "uniq_by_line" } -func (p *UniqByLine) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *UniqByLine) Process(issues []*result.Issue) ([]*result.Issue, error) { if !p.enabled { return issues, nil } diff --git a/vendor/github.com/golangci/misspell/.golangci.yml b/vendor/github.com/golangci/misspell/.golangci.yml index 2cfed442f..1811db3a0 100644 --- a/vendor/github.com/golangci/misspell/.golangci.yml +++ b/vendor/github.com/golangci/misspell/.golangci.yml @@ -1,107 +1,102 @@ -run: - timeout: 2m +version: "2" -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment - gocyclo: - min-complexity: 16 - goconst: - min-len: 3 - min-occurrences: 3 - misspell: - locale: US - funlen: - lines: -1 - statements: 40 - gofumpt: - extra-rules: true - depguard: - rules: - main: - deny: - - pkg: "github.com/instana/testify" - desc: not allowed - - pkg: "github.com/pkg/errors" - desc: Should be replaced by standard lib errors package - godox: - keywords: - - FIXME - gocritic: - enabled-tags: - - diagnostic - - style - - performance - disabled-checks: - - sloppyReassign - - rangeValCopy - - octalLiteral - - paramTypeCombine # already handle by gofumpt.extra-rules - - exitAfterDefer # FIXME(ldez) must be fixed - - ifElseChain # FIXME(ldez) must be fixed - settings: - hugeParam: - sizeThreshold: 100 - forbidigo: - forbid: - - '^print(ln)?$' - - '^panic$' - - '^spew\.Print(f|ln)?$' - - '^spew\.Dump$' +formatters: + enable: + - gci + - gofumpt + settings: + gofumpt: + extra-rules: true linters: - enable-all: true + default: all disable: - - deadcode # deprecated - - exhaustivestruct # deprecated - - golint # deprecated - - ifshort # deprecated - - interfacer # deprecated - - maligned # deprecated - - nosnakecase # deprecated - - scopelint # deprecated - - scopelint # deprecated - - structcheck # deprecated - - varcheck # deprecated - - execinquery # not relevant (SQL) - - rowserrcheck # not relevant (SQL) - - sqlclosecheck # not relevant (SQL) - cyclop # duplicate of gocyclo - dupl + - err113 + - errcheck # FIXME(ldez) must be fixed - exhaustive - exhaustruct - forbidigo - gochecknoglobals - gochecknoinits - - goerr113 - - gomnd + - gosmopolitan + - gosec # FIXME(ldez) must be fixed - lll + - misspell + - mnd + - nakedret # FIXME(ldez) must be fixed - nilnil - nlreturn + - nonamedreturns # FIXME(ldez) must be fixed - paralleltest - prealloc + - rowserrcheck # not relevant (SQL) + - sqlclosecheck # not relevant (SQL) - testpackage - tparallel - varnamelen - wrapcheck - - wsl - - misspell - - gosec # FIXME(ldez) must be fixed - - errcheck # FIXME(ldez) must be fixed - - nonamedreturns # FIXME(ldez) must be fixed - - nakedret # FIXME(ldez) must be fixed + - wsl # FIXME(ldez) must be fixed + + settings: + depguard: + rules: + main: + deny: + - pkg: github.com/instana/testify + desc: not allowed + - pkg: github.com/pkg/errors + desc: Should be replaced by standard lib errors package + forbidigo: + forbid: + - pattern: ^print(ln)?$ + - pattern: ^panic$ + - pattern: ^spew\.Print(f|ln)?$ + - pattern: ^spew\.Dump$ + funlen: + lines: -1 + statements: 40 + goconst: + min-len: 3 + min-occurrences: 3 + gocritic: + disabled-checks: + - sloppyReassign + - rangeValCopy + - octalLiteral + - paramTypeCombine # already handle by gofumpt.extra-rules + - exitAfterDefer # FIXME(ldez) must be fixed + - ifElseChain # FIXME(ldez) must be fixed + enabled-tags: + - diagnostic + - style + - performance + settings: + hugeParam: + sizeThreshold: 100 + gocyclo: + min-complexity: 16 + godox: + keywords: + - FIXME + govet: + disable: + - fieldalignment + enable-all: true + misspell: + locale: US + + exclusions: + warn-unused: true + presets: + - comments + rules: + - linters: + - funlen + - goconst + path: .*_test.go issues: - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 - exclude: - - 'ST1000: at least one file in a package should have a package comment' - - 'package-comments: should have a package comment' - exclude-rules: - - path: .*_test.go - linters: - - funlen - - goconst diff --git a/vendor/github.com/golangci/misspell/CONTRIBUTING.md b/vendor/github.com/golangci/misspell/CONTRIBUTING.md new file mode 100644 index 000000000..1efa9fde6 --- /dev/null +++ b/vendor/github.com/golangci/misspell/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# Contributing + +The files `words.go`, `works_uk.go`, and `works_us.go` must never be edited by hand. + +## Adding a word + +Misspell is neither a complete spell-checking program nor a grammar checker. +It is a tool to correct commonly misspelled English words. + +The list of words must contain only common mistakes. + +Before adding a word, you should have information about the misspelling frequency. + +- [ ] more than 15k inside GitHub (this limit is arbitrary and can involve) +- [ ] don't exist inside the [Wiktionary](https://en.wiktionary.org/wiki/) (as a modern form) +- [ ] don't exist inside the [Cambridge Dictionary](https://dictionary.cambridge.org) (as a modern form) +- [ ] don't exist inside the [Oxford Dictionary](https://www.oed.com/search/dictionary/) (as a modern form) + +If all criteria are met, a word can be added to the list of misspellings. + +The word should be added to one of the following files. + +- `internal/gen/sources/main.json`: common words. +- `internal/gen/sources/uk.json`: UK only words. +- `internal/gen/sources/us.json`: US only words. + +The target `make generate` will generate the Go files. + +The PR description must provide all the information (links) about the misspelling frequency. diff --git a/vendor/github.com/golangci/misspell/Makefile b/vendor/github.com/golangci/misspell/Makefile index fcda870ce..a5275d9fd 100644 --- a/vendor/github.com/golangci/misspell/Makefile +++ b/vendor/github.com/golangci/misspell/Makefile @@ -1,6 +1,6 @@ CONTAINER=golangci/misspell -default: lint test build +default: generate lint test build install: ## install misspell into GOPATH/bin go install ./cmd/misspell @@ -14,6 +14,9 @@ test: ## run all tests lint: ## run linter golangci-lint run +generate: + go run ./internal/gen/ + # the grep in line 2 is to remove misspellings in the spelling dictionary # that trigger false positives!! falsepositives: /scowl-wl diff --git a/vendor/github.com/golangci/misspell/README.md b/vendor/github.com/golangci/misspell/README.md index d2c3e7527..7a6abbe5f 100644 --- a/vendor/github.com/golangci/misspell/README.md +++ b/vendor/github.com/golangci/misspell/README.md @@ -1,7 +1,7 @@ [![Main](https://github.com/golangci/misspell/actions/workflows/ci.yml/badge.svg)](https://github.com/golangci/misspell/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/golangci/misspell)](https://goreportcard.com/report/github.com/golangci/misspell) [![Go Reference](https://pkg.go.dev/badge/github.com/golangci/misspell.svg)](https://pkg.go.dev/github.com/golangci/misspell) -[![license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.golangci.com/golangci/misspell/master/LICENSE) +[![license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.golangci.com/golangci/misspell/head/LICENSE) Correct commonly misspelled English words... quickly. @@ -10,7 +10,7 @@ Correct commonly misspelled English words... quickly. If you just want a binary and to start using `misspell`: ```bash -curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | sh -s -- -b ./bin ${MISSPELL_VERSION} +curl -sfL https://raw.githubusercontent.com/golangci/misspell/head/install-misspell.sh | sh -s -- -b ./bin ${MISSPELL_VERSION} ``` Both will install as `./bin/misspell`. @@ -27,7 +27,7 @@ go install github.com/golangci/misspell/cmd/misspell@latest Also, if you like to live dangerously, one could do ```bash -curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | sh -s -- -b $(go env GOPATH)/bin ${MISSPELL_VERSION} +curl -sfL https://raw.githubusercontent.com/golangci/misspell/head/install-misspell.sh | sh -s -- -b $(go env GOPATH)/bin ${MISSPELL_VERSION} ``` ### Usage @@ -49,7 +49,7 @@ Usage of misspell: -error Exit with 2 if misspelling found -f string - 'csv', 'sqlite3' or custom Golang template for output + 'csv', 'sqlite3' or custom Go template for output -i string ignore the following corrections, comma-separated -j int @@ -89,7 +89,7 @@ To use misspell with [pre-commit](https://pre-commit.com/), add the following to * [Automatic Corrections](#correct) * [Converting UK spellings to US](#locale) * [Using pipes and stdin](#stdin) -* [Golang special support](#golang) +* [Go special support](#golang) * [CSV Output](#csv) * [Using SQLite3](#sqlite) * [Changing output format](#output) @@ -192,10 +192,10 @@ zebra ``` -### Are there special rules for golang source files? +### Are there special rules for Go source files? -yes, if you want to force a file to be checked as a golang source, use `-source=go` on the command line. -Conversely, you can check a golang source as if it were pure text by using `-source=text`. +Yes, if you want to force a file to be checked as a Go source, use `-source=go` on the command line. +Conversely, you can check a Go source as if it was pure text by using `-source=text`. You might want to do this since many variable names have misspellings in them! ### Can I check only-comments in other programming languages? @@ -207,7 +207,7 @@ It doesn't work well for Python and Bash. ### How Can I Get CSV Output? -Using `-f csv`, the output is standard comma-seprated values with headers in the first row. +Using `-f csv`, the output is standard comma-separated values with headers in the first row. ```console $ misspell -f csv * @@ -244,7 +244,7 @@ $ sqlite3 -init /tmp/misspell.sql :memory: 'select count(*) from misspell' 1 ``` -With some tricks you can directly pipe output to sqlite3 by using `-init /dev/stdin`: +With some tricks you can directly pipe output to `sqlite3` by using `-init /dev/stdin`: ``` misspell -f sqlite * | sqlite3 -init /dev/stdin -column -cmd '.width 60 15' ':memory' \ @@ -252,7 +252,7 @@ misspell -f sqlite * | sqlite3 -init /dev/stdin -column -cmd '.width 60 15' ':me ``` -### How can I ignore rules? +### How can I ignore the rules? Using the `-i "comma,separated,rules"` flag you can specify corrections to ignore. @@ -266,7 +266,7 @@ With debug mode on, you can see it print the corrections, but it will no longer ### How can I change the output format? -Using the `-f template` flag you can pass in a [golang text template](https://golang.org/pkg/text/template/) to format the output. +Using the `-f template` flag you can pass in a [Go text template](https://golang.org/pkg/text/template/) to format the output. One can use `printf "%q" VALUE` to safely quote a value. @@ -290,7 +290,7 @@ This corrects commonly misspelled English words in computer source code, and oth It is designed to run quickly, so it can be used as a [pre-commit hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) with minimal burden on the developer. -It does not work with binary formats (e.g. Word, etc.). +It does not work with binary formats (e.g., Word, etc.). It is not a complete spell-checking program nor a grammar checker. @@ -303,11 +303,11 @@ Some other misspelling correctors: * https://github.com/lyda/misspell-check * https://github.com/lucasdemarchi/codespell -They all work but had problems that prevented me from using them at scale: +They all work but have problems that prevented me from using them at scale: -* slow, all of the above check one misspelling at a time (i.e. linear) using regexps +* slow, all of the above check one misspelling at a time (i.e., linear) using regexps * not MIT/Apache2 licensed (or equivalent) -* have dependencies that don't work for me (python3, bash, linux sed, etc.) +* have dependencies that don't work for me (Python3, Bash, GNU sed, etc.) * don't understand American vs. British English and sometimes makes unwelcome "corrections" That said, they might be perfect for you and many have more features than this project! @@ -318,7 +318,7 @@ That said, they might be perfect for you and many have more features than this p Misspell is easily 100x to 1000x faster than other spelling correctors. You should be able to check and correct 1000 files in under 250ms. -This uses the mighty power of golang's [strings.Replacer](https://golang.org/pkg/strings/#Replacer) +This uses the mighty power of Go's [strings.Replacer](https://golang.org/pkg/strings/#Replacer) which is an implementation or variation of the [Aho–Corasick algorithm](https://en.wikipedia.org/wiki/Aho–Corasick_algorithm). This makes multiple substring matches *simultaneously*. @@ -337,7 +337,7 @@ Since it operates in parallel to make corrections, it can be non-obvious to determine exactly what word was corrected. -### It's making mistakes. How can I debug? +### It's making mistakes. How can I debug? Run using `-debug` flag on the file you want. It should then print what word it is trying to correct. @@ -345,7 +345,7 @@ Then [file a bug](https://github.com/golangci/misspell/issues) describing the pr Thanks! -### Why is it making mistakes or missing items in golang files? +### Why is it making mistakes or missing items in Go files? The matching function is *case-sensitive*, so variable names that are multiple worlds either in all-uppercase or all-lowercase case sometimes can cause false positives. @@ -358,11 +358,11 @@ You can check your code using [golint](https://github.com/golang/lint) ### What license is this? -The main code is [MIT](https://github.com/golangci/misspell/blob/master/LICENSE). +The main code is [MIT](https://github.com/golangci/misspell/blob/head/LICENSE). -Misspell also makes uses of the Golang standard library and contains a modified version of Golang's [strings.Replacer](https://golang.org/pkg/strings/#Replacer) -which is covered under a [BSD License](https://github.com/golang/go/blob/master/LICENSE). -Type `misspell -legal` for more details or see [legal.go](https://github.com/golangci/misspell/blob/master/legal.go) +Misspell also makes use of the Go standard library and contains a modified version of Go's [strings.Replacer](https://golang.org/pkg/strings/#Replacer) +which is covered under a [BSD License](https://github.com/golang/go/blob/head/LICENSE). +Type `misspell -legal` for more details or see [legal.go](https://github.com/golangci/misspell/blob/head/legal.go) ### Where do the word lists come from? @@ -371,13 +371,13 @@ It started with a word list from [Wikipedia](https://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines). Unfortunately, this list had to be highly edited as many of the words are obsolete or based on mistakes on mechanical typewriters (I'm guessing). -Additional words were added based on actually mistakes seen in the wild (meaning self-generated). +Additional words were added based on actual mistakes seen in the wild (meaning self-generated). -Variations of UK and US spellings are based on many sources including: +Variations of UK and US spellings are based on many sources, including: -* http://www.tysto.com/uk-us-spelling-list.html (with heavy editing, many are incorrect) -* http://www.oxforddictionaries.com/us/words/american-and-british-spelling-american (excellent site but incomplete) -* Diffing US and UK [scowl dictionaries](http://wordlist.aspell.net) +* [Comprehensive* list of American and British spelling differences (archive)](https://web.archive.org/web/20230326222449/http://tysto.com/uk-us-spelling-list.html) (with heavy editing, many are incorrect) +* [American and British spelling (archive)](https://web.archive.org/web/20160820231624/http://www.oxforddictionaries.com/us/words/american-and-british-spelling-american) (excellent site but incomplete) +* Diffing US and UK [SCOWL dictionaries](http://wordlist.aspell.net) American English is more accepting of spelling variations than is British English, so "what is American or not" is subject to opinion. @@ -388,14 +388,10 @@ Corrections and help welcome. Here are some ideas for enhancements: -*Capitalization of proper nouns* could be done (e.g. weekday and month names, country names, language names) - -*Opinionated US spellings* US English has a number of words with alternate spellings. +- Capitalization of proper nouns: could be done (e.g., weekday and month names, country names, language names) +- Opinionated US spellings: US English has a number of words with alternate spellings. Think [adviser vs. advisor](http://grammarist.com/spelling/adviser-advisor/). -While "advisor" is not wrong, the opinionated US locale would correct "advisor" to "adviser". - -*Versioning* Some type of versioning is needed so reporting mistakes and errors is easier. - -*Feedback* Mistakes would be sent to some server for aggregation and feedback review. - -*Contractions and Apostrophes* This would optionally correct "isnt" to "isn't", etc. +While "advisor" is not wrong, the opinionated US locale would correct "advisor" to "adviser". +- Versioning: Some type of versioning is needed, so reporting mistakes and errors is easier. +- Feedback: Mistakes would be sent to some server for aggregation and feedback review. +- Contractions and Apostrophes: This would optionally correct "isnt" to "isn't", etc. diff --git a/vendor/github.com/golangci/misspell/ascii.go b/vendor/github.com/golangci/misspell/ascii.go index d60af5a8d..74abe5141 100644 --- a/vendor/github.com/golangci/misspell/ascii.go +++ b/vendor/github.com/golangci/misspell/ascii.go @@ -32,7 +32,7 @@ func StringEqualFold(s1, s2 string) bool { if len(s1) != len(s2) { return false } - for i := 0; i < len(s1); i++ { + for i := range len(s1) { c1 := s1[i] c2 := s2[i] // c1 & c2 diff --git a/vendor/github.com/golangci/misspell/case.go b/vendor/github.com/golangci/misspell/case.go index 0b580bedb..533ce4db3 100644 --- a/vendor/github.com/golangci/misspell/case.go +++ b/vendor/github.com/golangci/misspell/case.go @@ -21,7 +21,7 @@ func CaseStyle(word string) WordCase { lowerCount := 0 // this iterates over RUNES not BYTES - for i := 0; i < len(word); i++ { + for i := range len(word) { ch := word[i] switch { case ch >= 'a' && ch <= 'z': diff --git a/vendor/github.com/golangci/misspell/install-misspell.sh b/vendor/github.com/golangci/misspell/install-misspell.sh index d6023e117..7d0655b2f 100644 --- a/vendor/github.com/golangci/misspell/install-misspell.sh +++ b/vendor/github.com/golangci/misspell/install-misspell.sh @@ -105,7 +105,7 @@ cat /dev/null < y { - return x - } - return y -} - func inArray(haystack []string, needle string) bool { return slices.ContainsFunc(haystack, func(word string) bool { return strings.EqualFold(needle, word) @@ -85,59 +78,6 @@ func (r *Replacer) Compile() { r.engine = NewStringReplacer(r.Replacements...) } -/* -line1 and line2 are different -extract words from each line1 - -replace word -> newword -if word == new-word - - continue - -if new-word in list of replacements - - continue - -new word not original, and not in list of replacements some substring got mixed up. UNdo. -*/ -func (r *Replacer) recheckLine(s string, lineNum int, buf io.Writer, next func(Diff)) { - first := 0 - redacted := RemoveNotWords(s) - - idx := wordRegexp.FindAllStringIndex(redacted, -1) - for _, ab := range idx { - word := s[ab[0]:ab[1]] - newword := r.engine.Replace(word) - if newword == word { - // no replacement done - continue - } - - // ignore camelCase words - // https://github.com/client9/misspell/issues/113 - if CaseStyle(word) == CaseUnknown { - continue - } - - if StringEqualFold(r.corrected[strings.ToLower(word)], newword) { - // word got corrected into something we know - io.WriteString(buf, s[first:ab[0]]) - io.WriteString(buf, newword) - first = ab[1] - next(Diff{ - FullLine: s, - Line: lineNum, - Original: word, - Corrected: newword, - Column: ab[0], - }) - continue - } - // Word got corrected into something unknown. Ignore it - } - io.WriteString(buf, s[first:]) -} - // ReplaceGo is a specialized routine for correcting Golang source files. // Currently only checks comments, not identifiers for spelling. func (r *Replacer) ReplaceGo(input string) (string, []Diff) { @@ -177,7 +117,7 @@ Loop: // faster that making a bytes.Buffer and bufio.ReadString outlines := strings.SplitAfter(output, "\n") inlines := strings.SplitAfter(input, "\n") - for i := 0; i < len(inlines); i++ { + for i := range inlines { if inlines[i] == outlines[i] { buf.WriteString(outlines[i]) continue @@ -201,7 +141,7 @@ func (r *Replacer) Replace(input string) (string, []Diff) { // faster that making a bytes.Buffer and bufio.ReadString outlines := strings.SplitAfter(output, "\n") inlines := strings.SplitAfter(input, "\n") - for i := 0; i < len(inlines); i++ { + for i := range inlines { if inlines[i] == outlines[i] { buf.WriteString(outlines[i]) continue @@ -243,3 +183,56 @@ func (r *Replacer) ReplaceReader(raw io.Reader, w io.Writer, next func(Diff)) er } return nil } + +/* +line1 and line2 are different +extract words from each line1 + +replace word -> newword +if word == new-word + + continue + +if new-word in list of replacements + + continue + +new word not original, and not in list of replacements some substring got mixed up. UNdo. +*/ +func (r *Replacer) recheckLine(s string, lineNum int, buf io.Writer, next func(Diff)) { + first := 0 + redacted := RemoveNotWords(s) + + idx := wordRegexp.FindAllStringIndex(redacted, -1) + for _, ab := range idx { + word := s[ab[0]:ab[1]] + newword := r.engine.Replace(word) + if newword == word { + // no replacement done + continue + } + + // ignore camelCase words + // https://github.com/client9/misspell/issues/113 + if CaseStyle(word) == CaseUnknown { + continue + } + + if StringEqualFold(r.corrected[strings.ToLower(word)], newword) { + // word got corrected into something we know + io.WriteString(buf, s[first:ab[0]]) + io.WriteString(buf, newword) + first = ab[1] + next(Diff{ + FullLine: s, + Line: lineNum, + Original: word, + Corrected: newword, + Column: ab[0], + }) + continue + } + // Word got corrected into something unknown. Ignore it + } + io.WriteString(buf, s[first:]) +} diff --git a/vendor/github.com/golangci/misspell/stringreplacer.go b/vendor/github.com/golangci/misspell/stringreplacer.go index 46cb6c4b6..a03716849 100644 --- a/vendor/github.com/golangci/misspell/stringreplacer.go +++ b/vendor/github.com/golangci/misspell/stringreplacer.go @@ -177,7 +177,7 @@ func makeGenericReplacer(oldnew []string) *genericReplacer { // Find each byte used, then assign them each an index. for i := 0; i < len(oldnew); i += 2 { key := strings.ToLower(oldnew[i]) - for j := 0; j < len(key); j++ { + for j := range len(key) { r.mapping[key[j]] = 1 } } @@ -204,42 +204,6 @@ func makeGenericReplacer(oldnew []string) *genericReplacer { return r } -func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) { - // Iterate down the trie to the end, and grab the value and keylen with - // the highest priority. - bestPriority := 0 - node := &r.root - n := 0 - for node != nil { - if node.priority > bestPriority && !(ignoreRoot && node == &r.root) { - bestPriority = node.priority - val = node.value - keylen = n - found = true - } - - if s == "" { - break - } - if node.table != nil { - index := r.mapping[ByteToLower(s[0])] - if int(index) == r.tableSize { - break - } - node = node.table[index] - s = s[1:] - n++ - } else if node.prefix != "" && StringHasPrefixFold(s, node.prefix) { - n += len(node.prefix) - s = s[len(node.prefix):] - node = node.next - } else { - break - } - } - return -} - func (r *genericReplacer) Replace(s string) string { buf := make(appendSliceWriter, 0, len(s)) r.WriteString(&buf, s) @@ -305,6 +269,42 @@ func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) return } +func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) { + // Iterate down the trie to the end, and grab the value and keylen with + // the highest priority. + bestPriority := 0 + node := &r.root + n := 0 + for node != nil { + if node.priority > bestPriority && (!ignoreRoot || node != &r.root) { + bestPriority = node.priority + val = node.value + keylen = n + found = true + } + + if s == "" { + break + } + if node.table != nil { + index := r.mapping[ByteToLower(s[0])] + if int(index) == r.tableSize { + break + } + node = node.table[index] + s = s[1:] + n++ + } else if node.prefix != "" && StringHasPrefixFold(s, node.prefix) { + n += len(node.prefix) + s = s[len(node.prefix):] + node = node.next + } else { + break + } + } + return +} + type appendSliceWriter []byte // Write writes to the buffer to satisfy io.Writer. diff --git a/vendor/github.com/golangci/misspell/words.go b/vendor/github.com/golangci/misspell/words.go index 1603d87e6..64bfd88e5 100644 --- a/vendor/github.com/golangci/misspell/words.go +++ b/vendor/github.com/golangci/misspell/words.go @@ -1,6 +1,6 @@ -package misspell +// Code generated by 'internal/gen'. DO NOT EDIT. -// Code generated automatically. DO NOT EDIT. +package misspell // DictMain is the main rule set, not including locale-specific spellings var DictMain = []string{ @@ -2554,7 +2554,7 @@ var DictMain = []string{ "acceleraptor", "accelerator", "accelorating", "accelerating", "accessibilty", "accessibility", - "accidentlaly", "accidently", + "accidentlaly", "accidentally", "accomadating", "accommodating", "accomadation", "accommodation", "accomodating", "accommodating", @@ -2580,12 +2580,12 @@ var DictMain = []string{ "acquaintaces", "acquaintances", "acquaintence", "acquaintance", "acquantaince", "acquaintance", - "acquantiance", "acquaintances", - "acquiantance", "acquaintances", + "acquantiance", "acquaintance", + "acquiantance", "acquaintance", "acquiantence", "acquaintance", "adknowledged", "acknowledged", "adknowledges", "acknowledges", - "administored", "administer", + "administored", "administered", "adminsitered", "administered", "adminstrator", "administrator", "advantagious", "advantageous", @@ -3042,6 +3042,7 @@ var DictMain = []string{ "confidentaly", "confidently", "confidentely", "confidently", "confidentiel", "confidential", + "configration", "configuration", "configuratin", "configurations", "configuraton", "configuration", "confirmacion", "confirmation", @@ -3555,7 +3556,7 @@ var DictMain = []string{ "elektrolytes", "electrolytes", "eloctrolytes", "electrolytes", "embarassment", "embarrassment", - "embarasssing", "embarassing", + "embarasssing", "embarrassing", "embarrasment", "embarrassment", "embarressing", "embarrassing", "embarrissing", "embarrassing", @@ -4031,7 +4032,7 @@ var DictMain = []string{ "intelligient", "intelligent", "intenational", "international", "intentionnal", "intentional", - "intepretator", "interpretor", + "intepretator", "interpreter", "interatellar", "interstellar", "interational", "international", "intercection", "interception", @@ -5582,14 +5583,14 @@ var DictMain = []string{ "accessibile", "accessible", "accessibily", "accessibility", "accessoires", "accessories", - "accidantely", "accidently", + "accidantely", "accidentally", "accidentaly", "accidentally", - "accidentely", "accidently", + "accidentely", "accidentally", "accidential", "accidental", - "accidentily", "accidently", - "accidentlay", "accidently", - "accidentley", "accidently", - "accidentlly", "accidently", + "accidentily", "accidentally", + "accidentlay", "accidentally", + "accidentley", "accidentally", + "accidentlly", "accidentally", "accomadated", "accommodated", "accomadates", "accommodates", "accommadate", "accommodate", @@ -5691,8 +5692,8 @@ var DictMain = []string{ "agnsoticism", "agnosticism", "agonsticism", "agnosticism", "agressively", "aggressively", - "agressivley", "agressive", - "agressivnes", "agressive", + "agressivley", "aggressive", + "agressivnes", "aggressive", "agricolture", "agriculture", "agriculteur", "agriculture", "agricultral", "agricultural", @@ -5751,7 +5752,7 @@ var DictMain = []string{ "anniversery", "anniversary", "annonymouse", "anonymous", "announceing", "announcing", - "announcemet", "announcements", + "announcemet", "announcement", "announcemnt", "announcement", "announcents", "announces", "annoymously", "anonymously", @@ -5840,9 +5841,10 @@ var DictMain = []string{ "archaoelogy", "archeology", "archeaology", "archaeology", "archimedian", "archimedean", - "architechts", "architect", + "architechts", "architects", "architectes", "architects", "architecure", "architecture", + "archtecture", "architecture", "argiculture", "agriculture", "argumentate", "argumentative", "aribtrarily", "arbitrarily", @@ -6750,17 +6752,17 @@ var DictMain = []string{ "deficiencey", "deficiency", "deficienies", "deficiencies", "deficientcy", "deficiency", - "definantley", "definately", - "definatedly", "definately", - "definateley", "definately", - "definatelly", "definately", - "definatelty", "definately", - "definatetly", "definately", + "definantley", "definitely", + "definatedly", "definitely", + "definateley", "definitely", + "definatelly", "definitely", + "definatelty", "definitely", + "definatetly", "definitely", "definations", "definitions", - "definatlely", "definately", - "definetally", "definately", - "definetlely", "definetly", - "definitaley", "definately", + "definatlely", "definitely", + "definetally", "definitely", + "definetlely", "definitely", + "definitaley", "definitely", "definitelly", "definitely", "definitevly", "definitively", "definitiely", "definitively", @@ -6769,8 +6771,8 @@ var DictMain = []string{ "definitivly", "definitively", "definitivno", "definition", "definitivos", "definitions", - "definitlely", "definitly", - "definitlety", "definitly", + "definitlely", "definitely", + "definitlety", "definitely", "deflecticon", "deflection", "degenererat", "degenerate", "degradacion", "degradation", @@ -7127,16 +7129,16 @@ var DictMain = []string{ "elimintates", "eliminates", "ellipitcals", "elliptical", "eloquentely", "eloquently", - "emabrassing", "embarassing", - "embaraasing", "embarassing", - "embarasaing", "embarassing", - "embarassign", "embarassing", - "embarassimg", "embarassing", + "emabrassing", "embarrassing", + "embaraasing", "embarrassing", + "embarasaing", "embarrassing", + "embarassign", "embarrassing", + "embarassimg", "embarrassing", "embarassing", "embarrassing", - "embarissing", "embarassing", + "embarissing", "embarrassing", "embarrasing", "embarrassing", "embarressed", "embarrassed", - "embarrssing", "embarassing", + "embarrssing", "embarrassing", "emergancies", "emergencies", "emergencias", "emergencies", "emergenices", "emergencies", @@ -10314,7 +10316,7 @@ var DictMain = []string{ "academicas", "academics", "academicos", "academics", "academicus", "academics", - "accdiently", "accidently", + "accdiently", "accidentally", "accelarate", "accelerate", "accelerade", "accelerated", "accelerare", "accelerate", @@ -10333,14 +10335,14 @@ var DictMain = []string{ "accessbile", "accessible", "accessoire", "accessories", "accessoirs", "accessories", - "accicently", "accidently", - "accidantly", "accidently", - "accidebtly", "accidently", - "accidenlty", "accidently", + "accicently", "accidentally", + "accidantly", "accidentally", + "accidebtly", "accidentally", + "accidenlty", "accidentally", "accidentes", "accidents", - "accidentky", "accidently", + "accidentky", "accidentally", "accidently", "accidentally", - "accidnetly", "accidently", + "accidnetly", "accidentally", "accomadate", "accommodate", "accomodate", "accommodate", "accompined", "accompanied", @@ -10368,8 +10370,8 @@ var DictMain = []string{ "achiavable", "achievable", "achieveble", "achievable", "achievemnt", "achievement", - "achievemts", "achieves", - "achievents", "achieves", + "achievemts", "achievements", + "achievents", "achievements", "achievment", "achievement", "achilleous", "achilles", "achiveable", "achievable", @@ -10510,6 +10512,7 @@ var DictMain = []string{ "allergisch", "allergic", "alliegance", "allegiance", "alligeance", "allegiance", + "allignment", "alignment", "alocholics", "alcoholics", "alocholism", "alcoholism", "alogrithms", "algorithms", @@ -10529,7 +10532,7 @@ var DictMain = []string{ "altruisitc", "altruistic", "altrusitic", "altruistic", "alturistic", "altruistic", - "aluminimum", "aluminum", + "aluminimum", "aluminium", "amargeddon", "armageddon", "amateurest", "amateurs", "ambassabor", "ambassador", @@ -10706,7 +10709,7 @@ var DictMain = []string{ "archictect", "architect", "architechs", "architects", "architecht", "architect", - "architecte", "architecture", + "architecte", "architect", "architexts", "architects", "architypes", "archetypes", "archtiects", "architects", @@ -11355,7 +11358,7 @@ var DictMain = []string{ "comminists", "communists", "commisison", "commissions", "commissons", "commissions", - "commiteted", "commited", + "commiteted", "committed", "commodites", "commodities", "commtiment", "commitments", "communicae", "communicated", @@ -11930,7 +11933,7 @@ var DictMain = []string{ "deducitble", "deductible", "defacation", "defamation", "defamating", "defamation", - "defanitely", "definately", + "defanitely", "definitely", "defelction", "deflection", "defendeers", "defender", "defendents", "defendants", @@ -11938,56 +11941,56 @@ var DictMain = []string{ "defenesman", "defenseman", "defenselss", "defenseless", "defensivly", "defensively", - "defianetly", "definately", - "defiantely", "definately", - "defiantley", "definately", - "defibately", "definately", - "deficately", "definately", + "defianetly", "definitely", + "defiantely", "definitely", + "defiantley", "definitely", + "defibately", "definitely", + "deficately", "definitely", "deficiancy", "deficiency", "deficience", "deficiencies", "deficienct", "deficient", "deficienty", "deficiency", - "defiintely", "definately", - "definaetly", "definately", - "definaitly", "definately", - "definaltey", "definately", - "definataly", "definately", - "definateky", "definately", + "defiintely", "definitely", + "definaetly", "definitely", + "definaitly", "definitely", + "definaltey", "definitely", + "definataly", "definitely", + "definateky", "definitely", "definately", "definitely", - "definatily", "definately", + "definatily", "definitely", "defination", "definition", "definative", "definitive", - "definatlly", "definately", - "definatrly", "definately", - "definayely", "definately", - "defineatly", "definately", - "definetaly", "definately", + "definatlly", "definitely", + "definatrly", "definitely", + "definayely", "definitely", + "defineatly", "definitely", + "definetaly", "definitely", "definetely", "definitely", - "definetily", "definately", - "definetlly", "definetly", - "definettly", "definately", + "definetily", "definitely", + "definetlly", "definitely", + "definettly", "definitely", "definicion", "definition", "definietly", "definitely", "definining", "defining", - "definitaly", "definately", - "definiteyl", "definitly", + "definitaly", "definitely", + "definiteyl", "definitely", "definitivo", "definition", "definitley", "definitely", - "definitlly", "definitly", - "definitlry", "definitly", - "definitlty", "definitly", - "definjtely", "definately", - "definltely", "definately", - "definotely", "definately", - "definstely", "definately", - "defintaley", "definately", + "definitlly", "definitely", + "definitlry", "definitely", + "definitlty", "definitely", + "definjtely", "definitely", + "definltely", "definitely", + "definotely", "definitely", + "definstely", "definitely", + "defintaley", "definitely", "defintiely", "definitely", "defintiion", "definitions", - "definutely", "definately", + "definutely", "definitely", "deflaction", "deflection", "defleciton", "deflection", "deflektion", "deflection", - "defniately", "definately", + "defniately", "definitely", "degenarate", "degenerate", "degenerare", "degenerate", "degenerite", "degenerate", @@ -11995,7 +11998,7 @@ var DictMain = []string{ "degraderad", "degraded", "dehydraded", "dehydrated", "dehyrdated", "dehydrated", - "deifnately", "definately", + "deifnately", "definitely", "deisgnated", "designated", "delaership", "dealership", "delearship", "dealership", @@ -12451,7 +12454,7 @@ var DictMain = []string{ "eloquintly", "eloquently", "emapthetic", "empathetic", "embarassed", "embarrassed", - "embarassig", "embarassing", + "embarassig", "embarrassing", "embarrased", "embarrassed", "embarrases", "embarrassed", "embezelled", "embezzled", @@ -12967,7 +12970,7 @@ var DictMain = []string{ "goosepumps", "goosebumps", "gothenberg", "gothenburg", "govenrment", "government", - "govermenet", "goverment", + "govermenet", "government", "govermnent", "governments", "governemnt", "government", "governened", "governed", @@ -13274,6 +13277,7 @@ var DictMain = []string{ "impliciete", "implicit", "implicilty", "implicitly", "impliments", "implements", + "implmented", "implemented", "imporbable", "improbable", "importanly", "importantly", "importanty", "importantly", @@ -13314,7 +13318,7 @@ var DictMain = []string{ "inadiquate", "inadequate", "inagurated", "inaugurated", "inbalanced", "imbalanced", - "inbetweeen", "inbetween", + "inbetweeen", "between", "incarnaton", "incarnation", "incentivos", "incentives", "inchoerent", "incoherent", @@ -15644,7 +15648,7 @@ var DictMain = []string{ "seperation", "separation", "seperatism", "separatism", "seperatist", "separatist", - "seperatley", "seperate", + "seperatley", "separate", "sepulchure", "sepulchre", "serenitary", "serenity", "serviceble", "serviceable", @@ -16691,7 +16695,7 @@ var DictMain = []string{ "accelerar", "accelerator", "accending", "ascending", "accension", "accession", - "accidenty", "accidently", + "accidenty", "accidentally", "acclamied", "acclaimed", "accliamed", "acclaimed", "accomdate", "accommodate", @@ -16771,10 +16775,10 @@ var DictMain = []string{ "agrentina", "argentina", "agression", "aggression", "agressive", "aggressive", - "agressvie", "agressive", - "agruement", "arguement", + "agressvie", "aggressive", + "agruement", "argument", "agruments", "arguments", - "agurement", "arguement", + "agurement", "argument", "ailenated", "alienated", "airbourne", "airborne", "aircrafts", "aircraft", @@ -16902,7 +16906,7 @@ var DictMain = []string{ "appetitie", "appetite", "applaudes", "applause", "applicato", "application", - "appreciae", "appreciates", + "appreciae", "appreciate", "apprentie", "apprentice", "approachs", "approaches", "apratheid", "apartheid", @@ -16917,16 +16921,16 @@ var DictMain = []string{ "archetyps", "archetypes", "architecs", "architects", "archtypes", "archetypes", - "aregument", "arguement", + "aregument", "argument", "areospace", "aerospace", - "argessive", "agressive", - "argeument", "arguement", + "argessive", "aggressive", + "argeument", "argument", "arguabley", "arguably", "arguablly", "arguably", "arguement", "argument", - "arguemnet", "arguement", + "arguemnet", "argument", "arguemnts", "arguments", - "argumeent", "arguement", + "argumeent", "argument", "arhtritis", "arthritis", "aribtrary", "arbitrary", "ariplanes", "airplanes", @@ -16942,7 +16946,7 @@ var DictMain = []string{ "artifcats", "artifacts", "artifical", "artificial", "artillary", "artillery", - "arugement", "arguement", + "arugement", "argument", "arugments", "arguments", "asapragus", "asparagus", "asbestoes", "asbestos", @@ -17367,7 +17371,7 @@ var DictMain = []string{ "commentes", "commenters", "commercie", "commerce", "commision", "commission", - "commiteed", "commited", + "commiteed", "committed", "commiting", "committing", "commitmet", "commitments", "commments", "comments", @@ -17610,7 +17614,7 @@ var DictMain = []string{ "defaintly", "defiantly", "defaltion", "deflation", "defanitly", "defiantly", - "defeintly", "definetly", + "defeintly", "definitely", "defendent", "defendant", "defensese", "defenseless", "defianlty", "defiantly", @@ -17618,35 +17622,35 @@ var DictMain = []string{ "deficieny", "deficiency", "deficites", "deficits", "definance", "defiance", - "definatey", "definately", + "definatey", "definitely", "definatly", "definitely", "definetly", "definitely", - "definetyl", "definetly", - "definilty", "definitly", + "definetyl", "definitely", + "definilty", "definitely", "definitie", "definitive", "definitin", "definitions", "definitly", "definitely", "definiton", "definition", "definitve", "definite", - "definityl", "definitly", - "definltey", "definetly", + "definityl", "definitely", + "definltey", "definitely", "defintaly", "defiantly", - "defintily", "definitly", + "defintily", "definitely", "defintion", "definition", - "defintley", "definetly", - "defitenly", "definetly", - "defitinly", "definitly", + "defintley", "definitely", + "defitenly", "definitely", + "defitinly", "definitely", "defitnaly", "defiantly", - "defitnely", "definetly", + "defitnely", "definitely", "deflectin", "deflection", - "defnietly", "definetly", + "defnietly", "definitely", "degeneret", "degenerate", "degradato", "degradation", "degradead", "degraded", "degrassie", "degrasse", "degrassse", "degrasse", - "deifnetly", "definetly", - "deifnitly", "definitly", + "deifnetly", "definitely", + "deifnitly", "definitely", "deisgners", "designers", "delagates", "delegates", "delcaring", "declaring", @@ -17734,7 +17738,7 @@ var DictMain = []string{ "dicovered", "discovered", "dictaters", "dictates", "dictionay", "dictionary", - "difenitly", "definitly", + "difenitly", "definitely", "diferrent", "different", "differene", "differences", "differens", "differences", @@ -18034,7 +18038,7 @@ var DictMain = []string{ "existance", "existence", "existenta", "existential", "existince", "existence", - "existnace", "existance", + "existnace", "existence", "exlcuding", "excluding", "exlcusion", "exclusion", "exlcusive", "exclusive", @@ -18066,7 +18070,7 @@ var DictMain = []string{ "expolsive", "explosive", "expressie", "expressive", "expressin", "expression", - "exsitance", "existance", + "exsitance", "existence", "extention", "extension", "exteriour", "exterior", "extermely", "extremely", @@ -18226,17 +18230,17 @@ var DictMain = []string{ "goegraphy", "geography", "goldfisch", "goldfish", "goosebums", "goosebumps", - "gorvement", "goverment", - "govemrent", "goverment", + "gorvement", "government", + "govemrent", "government", "govenment", "government", "goverance", "governance", - "goveremnt", "goverment", + "goveremnt", "government", "goverment", "government", - "govermetn", "goverment", - "govermnet", "goverment", + "govermetn", "government", + "govermnet", "government", "governmet", "governments", "govorment", "government", - "govrement", "goverment", + "govrement", "government", "gracefull", "graceful", "gracefuly", "gracefully", "graduaste", "graduates", @@ -18422,9 +18426,9 @@ var DictMain = []string{ "inadquate", "inadequate", "inaugures", "inaugurates", "inbalance", "imbalance", - "inbeetwen", "inbetween", + "inbeetwen", "between", "inbetween", "between", - "inbewteen", "inbetween", + "inbewteen", "between", "incarnato", "incarnation", "incgonito", "incognito", "inclinato", "inclination", @@ -18958,14 +18962,14 @@ var DictMain = []string{ "nostlagic", "nostalgic", "nostriles", "nostrils", "nostrills", "nostrils", - "notacible", "noticable", - "notciable", "noticable", + "notacible", "noticeable", + "notciable", "noticeable", "noteboook", "notebook", "noteriety", "notoriety", "noteworty", "noteworthy", "noticable", "noticeable", "noticably", "noticeably", - "noticalbe", "noticable", + "noticalbe", "noticeable", "noticeing", "noticing", "noticible", "noticeable", "notoroius", "notorious", @@ -19559,6 +19563,7 @@ var DictMain = []string{ "redundany", "redundancy", "redundent", "redundant", "reedeming", "redeeming", + "refection", "reflection", "refelcted", "reflected", "refereces", "references", "refereees", "referees", @@ -19567,7 +19572,7 @@ var DictMain = []string{ "referencs", "references", "referense", "references", "referiang", "referring", - "referinng", "refering", + "referinng", "referring", "refernces", "references", "refernece", "reference", "refershed", "refreshed", @@ -19813,7 +19818,7 @@ var DictMain = []string{ "signapore", "singapore", "signitory", "signatory", "silhouete", "silhouette", - "similiair", "similiar", + "similiair", "similar", "simliarly", "similarly", "simluated", "simulated", "simluator", "simulator", @@ -20448,7 +20453,7 @@ var DictMain = []string{ "acccused", "accused", "acceptes", "accepts", "accidens", "accidents", - "accideny", "accidently", + "accideny", "accidentally", "accoring", "according", "accountt", "accountant", "accpeted", "accepted", @@ -20480,13 +20485,13 @@ var DictMain = []string{ "activits", "activities", "activley", "actively", "actresss", "actresses", - "actualey", "actualy", + "actualey", "actually", "actualiy", "actuality", - "actualky", "actualy", - "actualmy", "actualy", - "actualoy", "actualy", - "actualpy", "actualy", - "actualty", "actualy", + "actualky", "actually", + "actualmy", "actually", + "actualoy", "actually", + "actualpy", "actually", + "actualty", "actually", "acutally", "actually", "acutions", "auctions", "adaptare", "adapter", @@ -20542,7 +20547,7 @@ var DictMain = []string{ "agravate", "aggravate", "agreemnt", "agreement", "agregate", "aggregate", - "agressie", "agressive", + "agressie", "aggressive", "agressor", "aggressor", "agrieved", "aggrieved", "agruable", "arguable", @@ -20591,11 +20596,11 @@ var DictMain = []string{ "altrusim", "altruism", "alturism", "altruism", "aluminim", "aluminium", - "alumnium", "aluminum", - "alunimum", "aluminum", + "alumnium", "aluminium", + "alunimum", "aluminium", "amatersu", "amateurs", "amaterus", "amateurs", - "amendmet", "amendments", + "amendmet", "amendment", "amercian", "american", "amercias", "americas", "amernian", "armenian", @@ -20666,7 +20671,7 @@ var DictMain = []string{ "anythign", "anything", "anytying", "anything", "aparment", "apartment", - "apartmet", "apartments", + "apartmet", "apartment", "apenines", "apennines", "aperutre", "aperture", "aplhabet", "alphabet", @@ -20700,8 +20705,8 @@ var DictMain = []string{ "aremnian", "armenian", "argentia", "argentina", "argubaly", "arguably", - "arguemet", "arguement", - "arguemtn", "arguement", + "arguemet", "argument", + "arguemtn", "argument", "ariborne", "airborne", "aricraft", "aircraft", "ariplane", "airplane", @@ -20770,7 +20775,7 @@ var DictMain = []string{ "athenean", "athenian", "athesits", "atheists", "athetlic", "athletic", - "athients", "athiest", + "athients", "atheist", "atittude", "attitude", "atlantia", "atlanta", "atmoizer", "atomizer", @@ -20854,9 +20859,9 @@ var DictMain = []string{ "barrakcs", "barracks", "barrells", "barrels", "basicaly", "basically", - "basiclay", "basicly", - "basicley", "basicly", - "basicliy", "basicly", + "basiclay", "basically", + "basicley", "basically", + "basicliy", "basically", "batistia", "batista", "battalin", "battalion", "bayonent", "bayonet", @@ -20866,7 +20871,7 @@ var DictMain = []string{ "beastley", "beastly", "beatiful", "beautiful", "beccause", "because", - "becuasse", "becuase", + "becuasse", "because", "befirend", "befriend", "befreind", "befriend", "begginer", "beginner", @@ -21349,6 +21354,7 @@ var DictMain = []string{ "containg", "containing", "contaire", "containers", "contanti", "contacting", + "contants", "constants", "contense", "contenders", "contenst", "contents", "contexta", "contextual", @@ -21510,8 +21516,8 @@ var DictMain = []string{ "deffined", "defined", "deficiet", "deficient", "definate", "definite", - "definaty", "definately", - "definety", "definetly", + "definaty", "definitely", + "definety", "definitely", "definito", "definition", "definitv", "definitive", "deflatin", "deflation", @@ -21828,7 +21834,7 @@ var DictMain = []string{ "esctatic", "ecstatic", "esential", "essential", "esitmate", "estimate", - "esperate", "seperate", + "esperate", "separate", "esportes", "esports", "estiamte", "estimate", "estoeric", "esoteric", @@ -21881,7 +21887,7 @@ var DictMain = []string{ "exhausto", "exhaustion", "exicting", "exciting", "exisitng", "existing", - "existane", "existance", + "existane", "existence", "existant", "existent", "existend", "existed", "exlcuded", "excluded", @@ -22071,6 +22077,7 @@ var DictMain = []string{ "franlkin", "franklin", "freckels", "freckles", "freindly", "friendly", + "freqency", "frequency", "frequeny", "frequency", "friendle", "friendlies", "friendsi", "friendlies", @@ -22081,6 +22088,7 @@ var DictMain = []string{ "froniter", "frontier", "fronteir", "frontier", "frosaken", "forsaken", + "frquency", "frequency", "frutcose", "fructose", "fucntion", "function", "fufilled", "fulfilled", @@ -22183,7 +22191,7 @@ var DictMain = []string{ "gouvener", "governor", "govement", "government", "goverend", "governed", - "govermet", "goverment", + "govermet", "government", "governer", "governor", "gradualy", "gradually", "grafield", "garfield", @@ -22395,7 +22403,7 @@ var DictMain = []string{ "impusles", "impulses", "imrpoved", "improved", "imrpoves", "improves", - "inbetwen", "inbetween", + "inbetwen", "between", "inclince", "incline", "inclinde", "incline", "includng", "including", @@ -22499,6 +22507,7 @@ var DictMain = []string{ "internus", "interns", "interpet", "interpret", "interrim", "interim", + "interrut", "interrupt", "interste", "interstate", "interupt", "interrupt", "intevene", "intervene", @@ -23033,7 +23042,7 @@ var DictMain = []string{ "notablly", "notably", "noteable", "notable", "noteably", "notably", - "noticabe", "noticable", + "noticabe", "noticeable", "notorios", "notorious", "novmeber", "november", "nromandy", "normandy", @@ -23596,7 +23605,7 @@ var DictMain = []string{ "referene", "referee", "referens", "references", "referere", "referee", - "referign", "refering", + "referign", "referring", "refering", "referring", "refernce", "references", "reffered", "referred", @@ -23605,7 +23614,7 @@ var DictMain = []string{ "reflecte", "reflective", "reflecto", "reflection", "reformes", "reforms", - "refreing", "refering", + "refreing", "referring", "refrence", "reference", "refreshd", "refreshed", "refreshr", "refresher", @@ -23632,7 +23641,7 @@ var DictMain = []string{ "regulats", "regulators", "rehersal", "rehearsal", "rehtoric", "rhetoric", - "reiceved", "recieved", + "reiceved", "received", "reigment", "regiment", "reigonal", "regional", "rekenton", "renekton", @@ -23884,11 +23893,11 @@ var DictMain = []string{ "sentires", "sentries", "sentreis", "sentries", "separato", "separation", - "separete", "seperate", - "sepearte", "seperate", + "separete", "separate", + "sepearte", "separate", "seperate", "separate", "seplling", "spelling", - "sepreate", "seperate", + "sepreate", "separate", "sepulcre", "sepulchre", "serached", "searched", "seraches", "searches", @@ -23951,15 +23960,15 @@ var DictMain = []string{ "silbings", "siblings", "silicoln", "silicon", "silicoon", "silicon", - "silimiar", "similiar", - "simialir", "similiar", - "simiilar", "similiar", + "silimiar", "similar", + "simialir", "similar", + "simiilar", "similar", "similair", "similar", - "similari", "similiar", + "similari", "similar", "similart", "similarity", "similary", "similarly", "similiar", "similar", - "simliiar", "similiar", + "simliiar", "similar", "simluate", "simulate", "simmilar", "similar", "simpelst", "simplest", @@ -24227,13 +24236,13 @@ var DictMain = []string{ "superham", "superhuman", "superheo", "superhero", "superios", "superiors", - "supirsed", "suprised", + "supirsed", "surprised", "suposing", "supposing", "supporre", "supporters", "suppoted", "supported", "suprised", "surprised", "suprized", "surprised", - "suprsied", "suprised", + "suprsied", "surprised", "supsects", "suspects", "supsense", "suspense", "surbuban", "suburban", @@ -24730,15 +24739,15 @@ var DictMain = []string{ "acident", "accident", "ackward", "awkward", "acrlyic", "acrylic", - "actauly", "actualy", + "actauly", "actually", "activit", "activist", "activly", "actively", "actualy", "actually", - "actulay", "actualy", + "actulay", "actually", "acuracy", "accuracy", "acusing", "causing", "acustom", "accustom", - "acutaly", "actualy", + "acutaly", "actually", "acyrlic", "acrylic", "adaptes", "adapters", "adatper", "adapter", @@ -24772,7 +24781,7 @@ var DictMain = []string{ "agianst", "against", "agreing", "agreeing", "agruing", "arguing", - "ahtiest", "athiest", + "ahtiest", "atheist", "aicraft", "aircraft", "ailmony", "alimony", "airbore", "airborne", @@ -24909,12 +24918,12 @@ var DictMain = []string{ "assualt", "assault", "asterik", "asterisk", "asutria", "austria", - "atcualy", "actualy", + "atcualy", "actually", "atelast", "atleast", "athesim", "atheism", "athiesm", "atheism", "athiest", "atheist", - "athiets", "athiest", + "athiets", "atheist", "athlets", "athletes", "atlantc", "atlantic", "atleats", "atleast", @@ -24938,7 +24947,7 @@ var DictMain = []string{ "backsta", "backseat", "baclony", "balcony", "badnits", "bandits", - "baiscly", "basicly", + "baiscly", "basically", "bakcers", "backers", "balanse", "balances", "balcked", "blacked", @@ -24956,9 +24965,9 @@ var DictMain = []string{ "barrles", "barrels", "barsita", "barista", "barvery", "bravery", - "bascily", "basicly", + "bascily", "basically", "basicly", "basically", - "basilcy", "basicly", + "basilcy", "basically", "basiton", "bastion", "basnhee", "banshee", "bastane", "bastante", @@ -24970,7 +24979,7 @@ var DictMain = []string{ "bayblon", "babylon", "baynoet", "bayonet", "bayoent", "bayonet", - "bceuase", "becuase", + "bceuase", "because", "beacuse", "because", "bealtes", "beatles", "beaslty", "beastly", @@ -24980,9 +24989,9 @@ var DictMain = []string{ "becames", "becomes", "becasue", "because", "becouse", "because", - "becuaes", "becuase", + "becuaes", "because", "becuase", "because", - "becusae", "becuase", + "becusae", "because", "befried", "befriend", "beggins", "begins", "beglian", "belgian", @@ -25012,7 +25021,7 @@ var DictMain = []string{ "betales", "beatles", "bethesa", "bethesda", "betrayd", "betrayed", - "beucase", "becuase", + "beucase", "because", "bewteen", "between", "bicthes", "bitches", "bidrman", "birdman", @@ -25277,7 +25286,7 @@ var DictMain = []string{ "commans", "commands", "commere", "commerce", "comming", "coming", - "commitd", "commited", + "commitd", "committed", "compase", "compares", "compede", "competed", "compilr", "compiler", @@ -25550,7 +25559,7 @@ var DictMain = []string{ "earliet", "earliest", "earplus", "earplugs", "eastwod", "eastwood", - "ebcuase", "becuase", + "ebcuase", "because", "ecilpse", "eclipse", "eclipes", "eclipse", "eclispe", "eclipse", @@ -26659,7 +26668,7 @@ var DictMain = []string{ "receips", "receipts", "recided", "resided", "reciept", "receipt", - "recievd", "recieved", + "recievd", "received", "recieve", "receive", "recitfy", "rectify", "recived", "received", @@ -26673,7 +26682,7 @@ var DictMain = []string{ "refelct", "reflect", "referal", "referral", "refered", "referred", - "referig", "refering", + "referig", "referring", "referrs", "refers", "reflexs", "reflexes", "refrers", "refers", @@ -26913,7 +26922,7 @@ var DictMain = []string{ "signles", "singles", "silders", "sliders", "silenty", "silently", - "similir", "similiar", + "similir", "similar", "simliar", "similar", "simplet", "simplest", "simpley", "simply", @@ -27069,7 +27078,7 @@ var DictMain = []string{ "succesd", "succeeds", "suceeds", "succeeds", "suddeny", "suddenly", - "suefull", "usefull", + "suefull", "useful", "sufferd", "suffered", "summonr", "summoner", "summore", "summoner", @@ -27082,7 +27091,7 @@ var DictMain = []string{ "suppost", "supports", "suprass", "surpass", "supress", "suppress", - "suprisd", "suprised", + "suprisd", "surprised", "suprise", "surprise", "suprize", "surprise", "supsend", "suspend", @@ -27246,7 +27255,7 @@ var DictMain = []string{ "tyrhard", "tryhard", "tyrrany", "tyranny", "udpated", "updated", - "uesfull", "usefull", + "uesfull", "useful", "ugprade", "upgrade", "ukarine", "ukraine", "ukranie", "ukraine", @@ -27458,6 +27467,7 @@ var DictMain = []string{ "aplied", "applied", "appart", "apart", "aquire", "acquire", + "arcive", "archive", "aready", "already", "arised", "arose", "arival", "arrival", @@ -28017,6 +28027,7 @@ var DictMain = []string{ "noth", "north", "nowe", "now", "omre", "more", + "onlu", "only", "onot", "note", "onyl", "only", "owrk", "work", @@ -28088,3107 +28099,3 @@ var DictMain = []string{ "wih", "with", "yuo", "you", } - -// DictAmerican converts UK spellings to US spellings -var DictAmerican = []string{ - "institutionalisation", "institutionalization", - "internationalisation", "internationalization", - "professionalisation", "professionalization", - "compartmentalising", "compartmentalizing", - "institutionalising", "institutionalizing", - "internationalising", "internationalizing", - "compartmentalised", "compartmentalized", - "compartmentalises", "compartmentalizes", - "decriminalisation", "decriminalization", - "denationalisation", "denationalization", - "fictionalisations", "fictionalizations", - "institutionalised", "institutionalized", - "institutionalises", "institutionalizes", - "intellectualising", "intellectualizing", - "internationalised", "internationalized", - "internationalises", "internationalizes", - "pedestrianisation", "pedestrianization", - "professionalising", "professionalizing", - "archaeologically", "archeologically", - "compartmentalise", "compartmentalize", - "decentralisation", "decentralization", - "demilitarisation", "demilitarization", - "externalisations", "externalizations", - "fictionalisation", "fictionalization", - "institutionalise", "institutionalize", - "intellectualised", "intellectualized", - "intellectualises", "intellectualizes", - "internationalise", "internationalize", - "nationalisations", "nationalizations", - "palaeontologists", "paleontologists", - "professionalised", "professionalized", - "professionalises", "professionalizes", - "rationalisations", "rationalizations", - "sensationalising", "sensationalizing", - "sentimentalising", "sentimentalizing", - "acclimatisation", "acclimatization", - "bougainvillaeas", "bougainvilleas", - "commercialising", "commercializing", - "conceptualising", "conceptualizing", - "contextualising", "contextualizing", - "crystallisation", "crystallization", - "decriminalising", "decriminalizing", - "democratisation", "democratization", - "denationalising", "denationalizing", - "depersonalising", "depersonalizing", - "desensitisation", "desensitization", - "destabilisation", "destabilization", - "disorganisation", "disorganization", - "extemporisation", "extemporization", - "externalisation", "externalization", - "familiarisation", "familiarization", - "generalisations", "generalizations", - "hospitalisation", "hospitalization", - "individualising", "individualizing", - "industrialising", "industrializing", - "intellectualise", "intellectualize", - "internalisation", "internalization", - "manoeuvrability", "maneuverability", - "marginalisation", "marginalization", - "materialisation", "materialization", - "miniaturisation", "miniaturization", - "nationalisation", "nationalization", - "neighbourliness", "neighborliness", - "overemphasising", "overemphasizing", - "palaeontologist", "paleontologist", - "particularising", "particularizing", - "pedestrianising", "pedestrianizing", - "professionalise", "professionalize", - "psychoanalysing", "psychoanalyzing", - "rationalisation", "rationalization", - "reorganisations", "reorganizations", - "revolutionising", "revolutionizing", - "sensationalised", "sensationalized", - "sensationalises", "sensationalizes", - "sentimentalised", "sentimentalized", - "sentimentalises", "sentimentalizes", - "specialisations", "specializations", - "standardisation", "standardization", - "synchronisation", "synchronization", - "systematisation", "systematization", - "aggrandisement", "aggrandizement", - "anaesthetising", "anesthetizing", - "archaeological", "archeological", - "archaeologists", "archeologists", - "bougainvillaea", "bougainvillea", - "characterising", "characterizing", - "collectivising", "collectivizing", - "commercialised", "commercialized", - "commercialises", "commercializes", - "conceptualised", "conceptualized", - "conceptualises", "conceptualizes", - "contextualised", "contextualized", - "contextualises", "contextualizes", - "decentralising", "decentralizing", - "decriminalised", "decriminalized", - "decriminalises", "decriminalizes", - "dehumanisation", "dehumanization", - "demilitarising", "demilitarizing", - "demobilisation", "demobilization", - "demoralisation", "demoralization", - "denationalised", "denationalized", - "denationalises", "denationalizes", - "depersonalised", "depersonalized", - "depersonalises", "depersonalizes", - "disembowelling", "disemboweling", - "dramatisations", "dramatizations", - "editorialising", "editorializing", - "encyclopaedias", "encyclopedias", - "fictionalising", "fictionalizing", - "fraternisation", "fraternization", - "generalisation", "generalization", - "gynaecological", "gynecological", - "gynaecologists", "gynecologists", - "haematological", "hematological", - "haematologists", "hematologists", - "immobilisation", "immobilization", - "individualised", "individualized", - "individualises", "individualizes", - "industrialised", "industrialized", - "industrialises", "industrializes", - "liberalisation", "liberalization", - "monopolisation", "monopolization", - "naturalisation", "naturalization", - "neighbourhoods", "neighborhoods", - "neutralisation", "neutralization", - "organisational", "organizational", - "outmanoeuvring", "outmaneuvering", - "overemphasised", "overemphasized", - "overemphasises", "overemphasizes", - "paediatricians", "pediatricians", - "particularised", "particularized", - "particularises", "particularizes", - "pasteurisation", "pasteurization", - "pedestrianised", "pedestrianized", - "pedestrianises", "pedestrianizes", - "philosophising", "philosophizing", - "politicisation", "politicization", - "popularisation", "popularization", - "pressurisation", "pressurization", - "prioritisation", "prioritization", - "privatisations", "privatizations", - "propagandising", "propagandizing", - "psychoanalysed", "psychoanalyzed", - "psychoanalyses", "psychoanalyzes", - "regularisation", "regularization", - "reorganisation", "reorganization", - "revolutionised", "revolutionized", - "revolutionises", "revolutionizes", - "secularisation", "secularization", - "sensationalise", "sensationalize", - "sentimentalise", "sentimentalize", - "serialisations", "serializations", - "specialisation", "specialization", - "sterilisations", "sterilizations", - "stigmatisation", "stigmatization", - "transistorised", "transistorized", - "unrecognisable", "unrecognizable", - "visualisations", "visualizations", - "westernisation", "westernization", - "accessorising", "accessorizing", - "acclimatising", "acclimatizing", - "amortisations", "amortizations", - "amphitheatres", "amphitheaters", - "anaesthetised", "anesthetized", - "anaesthetises", "anesthetizes", - "anaesthetists", "anesthetists", - "archaeologist", "archeologist", - "backpedalling", "backpedaling", - "behaviourists", "behaviorists", - "breathalysers", "breathalyzers", - "breathalysing", "breathalyzing", - "callisthenics", "calisthenics", - "cannibalising", "cannibalizing", - "characterised", "characterized", - "characterises", "characterizes", - "circularising", "circularizing", - "clarinettists", "clarinetists", - "collectivised", "collectivized", - "collectivises", "collectivizes", - "commercialise", "commercialize", - "computerising", "computerizing", - "conceptualise", "conceptualize", - "contextualise", "contextualize", - "criminalising", "criminalizing", - "crystallising", "crystallizing", - "decentralised", "decentralized", - "decentralises", "decentralizes", - "decriminalise", "decriminalize", - "demilitarised", "demilitarized", - "demilitarises", "demilitarizes", - "democratising", "democratizing", - "denationalise", "denationalize", - "depersonalise", "depersonalize", - "desensitising", "desensitizing", - "destabilising", "destabilizing", - "disembowelled", "disemboweled", - "dishonourable", "dishonorable", - "dishonourably", "dishonorably", - "dramatisation", "dramatization", - "editorialised", "editorialized", - "editorialises", "editorializes", - "encyclopaedia", "encyclopedia", - "encyclopaedic", "encyclopedic", - "extemporising", "extemporizing", - "externalising", "externalizing", - "familiarising", "familiarizing", - "fertilisation", "fertilization", - "fictionalised", "fictionalized", - "fictionalises", "fictionalizes", - "formalisation", "formalization", - "fossilisation", "fossilization", - "globalisation", "globalization", - "gynaecologist", "gynecologist", - "haematologist", "hematologist", - "haemophiliacs", "hemophiliacs", - "haemorrhaging", "hemorrhaging", - "harmonisation", "harmonization", - "hospitalising", "hospitalizing", - "hypothesising", "hypothesizing", - "immortalising", "immortalizing", - "individualise", "individualize", - "industrialise", "industrialize", - "internalising", "internalizing", - "marginalising", "marginalizing", - "materialising", "materializing", - "mechanisation", "mechanization", - "memorialising", "memorializing", - "miniaturising", "miniaturizing", - "miscatalogued", "miscataloged", - "misdemeanours", "misdemeanors", - "multicoloured", "multicolored", - "nationalising", "nationalizing", - "neighbourhood", "neighborhood", - "normalisation", "normalization", - "organisations", "organizations", - "outmanoeuvred", "outmaneuvered", - "outmanoeuvres", "outmaneuvers", - "overemphasise", "overemphasize", - "paediatrician", "pediatrician", - "palaeontology", "paleontology", - "particularise", "particularize", - "passivisation", "passivization", - "patronisingly", "patronizingly", - "pedestrianise", "pedestrianize", - "personalising", "personalizing", - "philosophised", "philosophized", - "philosophises", "philosophizes", - "privatisation", "privatization", - "propagandised", "propagandized", - "propagandises", "propagandizes", - "proselytisers", "proselytizers", - "proselytising", "proselytizing", - "psychoanalyse", "psychoanalyze", - "pulverisation", "pulverization", - "rationalising", "rationalizing", - "reconnoitring", "reconnoitering", - "revolutionise", "revolutionize", - "romanticising", "romanticizing", - "serialisation", "serialization", - "socialisation", "socialization", - "stabilisation", "stabilization", - "standardising", "standardizing", - "sterilisation", "sterilization", - "subsidisation", "subsidization", - "synchronising", "synchronizing", - "systematising", "systematizing", - "tantalisingly", "tantalizingly", - "underutilised", "underutilized", - "victimisation", "victimization", - "visualisation", "visualization", - "vocalisations", "vocalizations", - "vulgarisation", "vulgarization", - "accessorised", "accessorized", - "accessorises", "accessorizes", - "acclimatised", "acclimatized", - "acclimatises", "acclimatizes", - "amortisation", "amortization", - "amphitheatre", "amphitheater", - "anaesthetics", "anesthetics", - "anaesthetise", "anesthetize", - "anaesthetist", "anesthetist", - "antagonising", "antagonizing", - "appetisingly", "appetizingly", - "backpedalled", "backpedaled", - "bastardising", "bastardizing", - "behaviourism", "behaviorism", - "behaviourist", "behaviorist", - "bowdlerising", "bowdlerizing", - "breathalysed", "breathalyzed", - "breathalyser", "breathalyzer", - "breathalyses", "breathalyzes", - "cannibalised", "cannibalized", - "cannibalises", "cannibalizes", - "capitalising", "capitalizing", - "caramelising", "caramelizing", - "categorising", "categorizing", - "centigrammes", "centigrams", - "centralising", "centralizing", - "centrepieces", "centerpieces", - "characterise", "characterize", - "circularised", "circularized", - "circularises", "circularizes", - "clarinettist", "clarinetist", - "collectivise", "collectivize", - "colonisation", "colonization", - "computerised", "computerized", - "computerises", "computerizes", - "criminalised", "criminalized", - "criminalises", "criminalizes", - "crystallised", "crystallized", - "crystallises", "crystallizes", - "decentralise", "decentralize", - "dehumanising", "dehumanizing", - "demilitarise", "demilitarize", - "demobilising", "demobilizing", - "democratised", "democratized", - "democratises", "democratizes", - "demoralising", "demoralizing", - "desensitised", "desensitized", - "desensitises", "desensitizes", - "destabilised", "destabilized", - "destabilises", "destabilizes", - "discolouring", "discoloring", - "dishonouring", "dishonoring", - "disorganised", "disorganized", - "editorialise", "editorialize", - "endeavouring", "endeavoring", - "equalisation", "equalization", - "evangelising", "evangelizing", - "extemporised", "extemporized", - "extemporises", "extemporizes", - "externalised", "externalized", - "externalises", "externalizes", - "familiarised", "familiarized", - "familiarises", "familiarizes", - "fictionalise", "fictionalize", - "finalisation", "finalization", - "fraternising", "fraternizing", - "generalising", "generalizing", - "haemophiliac", "hemophiliac", - "haemorrhaged", "hemorrhaged", - "haemorrhages", "hemorrhages", - "haemorrhoids", "hemorrhoids", - "homoeopathic", "homeopathic", - "homogenising", "homogenizing", - "hospitalised", "hospitalized", - "hospitalises", "hospitalizes", - "hypothesised", "hypothesized", - "hypothesises", "hypothesizes", - "idealisation", "idealization", - "immobilisers", "immobilizers", - "immobilising", "immobilizing", - "immortalised", "immortalized", - "immortalises", "immortalizes", - "immunisation", "immunization", - "initialising", "initializing", - "internalised", "internalized", - "internalises", "internalizes", - "jeopardising", "jeopardizing", - "legalisation", "legalization", - "legitimising", "legitimizing", - "liberalising", "liberalizing", - "manoeuvrable", "maneuverable", - "manoeuvrings", "maneuverings", - "marginalised", "marginalized", - "marginalises", "marginalizes", - "marvellously", "marvelously", - "materialised", "materialized", - "materialises", "materializes", - "maximisation", "maximization", - "memorialised", "memorialized", - "memorialises", "memorializes", - "metabolising", "metabolizing", - "militarising", "militarizing", - "milligrammes", "milligrams", - "miniaturised", "miniaturized", - "miniaturises", "miniaturizes", - "misbehaviour", "misbehavior", - "misdemeanour", "misdemeanor", - "mobilisation", "mobilization", - "moisturisers", "moisturizers", - "moisturising", "moisturizing", - "monopolising", "monopolizing", - "moustachioed", "mustachioed", - "nationalised", "nationalized", - "nationalises", "nationalizes", - "naturalising", "naturalizing", - "neighbouring", "neighboring", - "neutralising", "neutralizing", - "oesophaguses", "esophaguses", - "organisation", "organization", - "orthopaedics", "orthopedics", - "outmanoeuvre", "outmaneuver", - "palaeolithic", "paleolithic", - "pasteurising", "pasteurizing", - "personalised", "personalized", - "personalises", "personalizes", - "philosophise", "philosophize", - "plagiarising", "plagiarizing", - "ploughshares", "plowshares", - "polarisation", "polarization", - "politicising", "politicizing", - "popularising", "popularizing", - "pressurising", "pressurizing", - "prioritising", "prioritizing", - "propagandise", "propagandize", - "proselytised", "proselytized", - "proselytiser", "proselytizer", - "proselytises", "proselytizes", - "radicalising", "radicalizing", - "rationalised", "rationalized", - "rationalises", "rationalizes", - "realisations", "realizations", - "recognisable", "recognizable", - "recognisably", "recognizably", - "recognisance", "recognizance", - "reconnoitred", "reconnoitered", - "reconnoitres", "reconnoiters", - "regularising", "regularizing", - "reorganising", "reorganizing", - "revitalising", "revitalizing", - "rhapsodising", "rhapsodizing", - "romanticised", "romanticized", - "romanticises", "romanticizes", - "scandalising", "scandalizing", - "scrutinising", "scrutinizing", - "secularising", "secularizing", - "specialising", "specializing", - "squirrelling", "squirreling", - "standardised", "standardized", - "standardises", "standardizes", - "stigmatising", "stigmatizing", - "sympathisers", "sympathizers", - "sympathising", "sympathizing", - "synchronised", "synchronized", - "synchronises", "synchronizes", - "synthesisers", "synthesizers", - "synthesising", "synthesizing", - "systematised", "systematized", - "systematises", "systematizes", - "technicolour", "technicolor", - "theatregoers", "theatergoers", - "traumatising", "traumatizing", - "trivialising", "trivializing", - "unauthorised", "unauthorized", - "uncatalogued", "uncataloged", - "unfavourable", "unfavorable", - "unfavourably", "unfavorably", - "unionisation", "unionization", - "unrecognised", "unrecognized", - "untrammelled", "untrammeled", - "urbanisation", "urbanization", - "vaporisation", "vaporization", - "vocalisation", "vocalization", - "watercolours", "watercolors", - "westernising", "westernizing", - "accessorise", "accessorize", - "acclimatise", "acclimatize", - "agonisingly", "agonizingly", - "amortisable", "amortizable", - "anaesthesia", "anesthesia", - "anaesthetic", "anesthetic", - "anglicising", "anglicizing", - "antagonised", "antagonized", - "antagonises", "antagonizes", - "apologising", "apologizing", - "archaeology", "archeology", - "authorising", "authorizing", - "bastardised", "bastardized", - "bastardises", "bastardizes", - "bedevilling", "bedeviling", - "behavioural", "behavioral", - "belabouring", "belaboring", - "bowdlerised", "bowdlerized", - "bowdlerises", "bowdlerizes", - "breathalyse", "breathalyze", - "brutalising", "brutalizing", - "cannibalise", "cannibalize", - "capitalised", "capitalized", - "capitalises", "capitalizes", - "caramelised", "caramelized", - "caramelises", "caramelizes", - "carbonising", "carbonizing", - "cataloguing", "cataloging", - "categorised", "categorized", - "categorises", "categorizes", - "cauterising", "cauterizing", - "centigramme", "centigram", - "centilitres", "centiliters", - "centimetres", "centimeters", - "centralised", "centralized", - "centralises", "centralizes", - "centrefolds", "centerfolds", - "centrepiece", "centerpiece", - "channelling", "channeling", - "chequebooks", "checkbooks", - "circularise", "circularize", - "colourfully", "colorfully", - "colourizing", "colorizing", - "computerise", "computerize", - "councillors", "councilors", - "counselling", "counseling", - "counsellors", "counselors", - "criminalise", "criminalize", - "criticising", "criticizing", - "crystallise", "crystallize", - "customising", "customizing", - "defenceless", "defenseless", - "dehumanised", "dehumanized", - "dehumanises", "dehumanizes", - "demobilised", "demobilized", - "demobilises", "demobilizes", - "democratise", "democratize", - "demoralised", "demoralized", - "demoralises", "demoralizes", - "deodorising", "deodorizing", - "desensitise", "desensitize", - "destabilise", "destabilize", - "discoloured", "discolored", - "dishevelled", "disheveled", - "dishonoured", "dishonored", - "dramatising", "dramatizing", - "economising", "economizing", - "empathising", "empathizing", - "emphasising", "emphasizing", - "endeavoured", "endeavored", - "epitomising", "epitomizing", - "evangelised", "evangelized", - "evangelises", "evangelizes", - "extemporise", "extemporize", - "externalise", "externalize", - "factorising", "factorizing", - "familiarise", "familiarize", - "fantasising", "fantasizing", - "favouritism", "favoritism", - "fertilisers", "fertilizers", - "fertilising", "fertilizing", - "flavourings", "flavorings", - "flavourless", "flavorless", - "flavoursome", "flavorsome", - "formalising", "formalizing", - "fossilising", "fossilizing", - "fraternised", "fraternized", - "fraternises", "fraternizes", - "galvanising", "galvanizing", - "generalised", "generalized", - "generalises", "generalizes", - "ghettoising", "ghettoizing", - "globalising", "globalizing", - "gruellingly", "gruelingly", - "gynaecology", "gynecology", - "haematology", "hematology", - "haemoglobin", "hemoglobin", - "haemophilia", "hemophilia", - "haemorrhage", "hemorrhage", - "harmonising", "harmonizing", - "homoeopaths", "homeopaths", - "homoeopathy", "homeopathy", - "homogenised", "homogenized", - "homogenises", "homogenizes", - "hospitalise", "hospitalize", - "hybridising", "hybridizing", - "hypnotising", "hypnotizing", - "hypothesise", "hypothesize", - "immobilised", "immobilized", - "immobiliser", "immobilizer", - "immobilises", "immobilizes", - "immortalise", "immortalize", - "impanelling", "impaneling", - "imperilling", "imperiling", - "initialised", "initialized", - "initialises", "initializes", - "initialling", "initialing", - "instalments", "installments", - "internalise", "internalize", - "italicising", "italicizing", - "jeopardised", "jeopardized", - "jeopardises", "jeopardizes", - "kilogrammes", "kilograms", - "legitimised", "legitimized", - "legitimises", "legitimizes", - "liberalised", "liberalized", - "liberalises", "liberalizes", - "lionisation", "lionization", - "liquidisers", "liquidizers", - "liquidising", "liquidizing", - "magnetising", "magnetizing", - "manoeuvring", "maneuvering", - "marginalise", "marginalize", - "marshalling", "marshaling", - "materialise", "materialize", - "mechanising", "mechanizing", - "memorialise", "memorialize", - "mesmerising", "mesmerizing", - "metabolised", "metabolized", - "metabolises", "metabolizes", - "micrometres", "micrometers", - "militarised", "militarized", - "militarises", "militarizes", - "milligramme", "milligram", - "millilitres", "milliliters", - "millimetres", "millimeters", - "miniaturise", "miniaturize", - "modernising", "modernizing", - "moisturised", "moisturized", - "moisturiser", "moisturizer", - "moisturises", "moisturizes", - "monopolised", "monopolized", - "monopolises", "monopolizes", - "nationalise", "nationalize", - "naturalised", "naturalized", - "naturalises", "naturalizes", - "neighbourly", "neighborly", - "neutralised", "neutralized", - "neutralises", "neutralizes", - "normalising", "normalizing", - "orthopaedic", "orthopedic", - "ostracising", "ostracizing", - "oxidisation", "oxidization", - "paediatrics", "pediatrics", - "paedophiles", "pedophiles", - "paedophilia", "pedophilia", - "passivising", "passivizing", - "pasteurised", "pasteurized", - "pasteurises", "pasteurizes", - "patronising", "patronizing", - "personalise", "personalize", - "plagiarised", "plagiarized", - "plagiarises", "plagiarizes", - "ploughshare", "plowshare", - "politicised", "politicized", - "politicises", "politicizes", - "popularised", "popularized", - "popularises", "popularizes", - "praesidiums", "presidiums", - "pressurised", "pressurized", - "pressurises", "pressurizes", - "prioritised", "prioritized", - "prioritises", "prioritizes", - "privatising", "privatizing", - "proselytise", "proselytize", - "publicising", "publicizing", - "pulverising", "pulverizing", - "quarrelling", "quarreling", - "radicalised", "radicalized", - "radicalises", "radicalizes", - "randomising", "randomizing", - "rationalise", "rationalize", - "realisation", "realization", - "recognising", "recognizing", - "reconnoitre", "reconnoiter", - "regularised", "regularized", - "regularises", "regularizes", - "remodelling", "remodeling", - "reorganised", "reorganized", - "reorganises", "reorganizes", - "revitalised", "revitalized", - "revitalises", "revitalizes", - "rhapsodised", "rhapsodized", - "rhapsodises", "rhapsodizes", - "romanticise", "romanticize", - "scandalised", "scandalized", - "scandalises", "scandalizes", - "sceptically", "skeptically", - "scrutinised", "scrutinized", - "scrutinises", "scrutinizes", - "secularised", "secularized", - "secularises", "secularizes", - "sensitising", "sensitizing", - "serialising", "serializing", - "sermonising", "sermonizing", - "shrivelling", "shriveling", - "signalising", "signalizing", - "snorkelling", "snorkeling", - "snowploughs", "snowplow", - "socialising", "socializing", - "solemnising", "solemnizing", - "specialised", "specialized", - "specialises", "specializes", - "squirrelled", "squirreled", - "stabilisers", "stabilizers", - "stabilising", "stabilizing", - "standardise", "standardize", - "stencilling", "stenciling", - "sterilisers", "sterilizers", - "sterilising", "sterilizing", - "stigmatised", "stigmatized", - "stigmatises", "stigmatizes", - "subsidisers", "subsidizers", - "subsidising", "subsidizing", - "summarising", "summarizing", - "symbolising", "symbolizing", - "sympathised", "sympathized", - "sympathiser", "sympathizer", - "sympathises", "sympathizes", - "synchronise", "synchronize", - "synthesised", "synthesized", - "synthesiser", "synthesizer", - "synthesises", "synthesizes", - "systematise", "systematize", - "tantalising", "tantalizing", - "temporising", "temporizing", - "tenderising", "tenderizing", - "terrorising", "terrorizing", - "theatregoer", "theatergoer", - "traumatised", "traumatized", - "traumatises", "traumatizes", - "trivialised", "trivialized", - "trivialises", "trivializes", - "tyrannising", "tyrannizing", - "uncivilised", "uncivilized", - "unorganised", "unorganized", - "unravelling", "unraveling", - "utilisation", "utilization", - "vandalising", "vandalizing", - "verbalising", "verbalizing", - "victimising", "victimizing", - "visualising", "visualizing", - "vulgarising", "vulgarizing", - "watercolour", "watercolor", - "westernised", "westernized", - "westernises", "westernizes", - "worshipping", "worshiping", - "aeroplanes", "airplanes", - "amortising", "amortizing", - "anglicised", "anglicized", - "anglicises", "anglicizes", - "annualised", "annualized", - "antagonise", "antagonize", - "apologised", "apologized", - "apologises", "apologizes", - "appetisers", "appetizers", - "appetising", "appetizing", - "authorised", "authorized", - "authorises", "authorizes", - "bannisters", "banisters", - "bastardise", "bastardize", - "bedevilled", "bedeviled", - "behaviours", "behaviors", - "bejewelled", "bejeweled", - "belaboured", "belabored", - "bowdlerise", "bowdlerize", - "brutalised", "brutalized", - "brutalises", "brutalizes", - "canalising", "canalizing", - "cancelling", "canceling", - "canonising", "canonizing", - "capitalise", "capitalize", - "caramelise", "caramelize", - "carbonised", "carbonized", - "carbonises", "carbonizes", - "catalogued", "cataloged", - "catalogues", "catalogs", - "catalysing", "catalyzing", - "categorise", "categorize", - "cauterised", "cauterized", - "cauterises", "cauterizes", - "centilitre", "centiliter", - "centimetre", "centimeter", - "centralise", "centralize", - "centrefold", "centerfold", - "channelled", "channeled", - "chequebook", "checkbook", - "chiselling", "chiseling", - "civilising", "civilizing", - "clamouring", "clamoring", - "colonisers", "colonizers", - "colonising", "colonizing", - "colourants", "colorants", - "colourized", "colorized", - "colourizes", "colorizes", - "colourless", "colorless", - "connexions", "connections", - "councillor", "councilor", - "counselled", "counseled", - "counsellor", "counselor", - "criticised", "criticized", - "criticises", "criticizes", - "cudgelling", "cudgeling", - "customised", "customized", - "customises", "customizes", - "dehumanise", "dehumanize", - "demobilise", "demobilize", - "demonising", "demonizing", - "demoralise", "demoralize", - "deodorised", "deodorized", - "deodorises", "deodorizes", - "deputising", "deputizing", - "digitising", "digitizing", - "discolours", "discolors", - "dishonours", "dishonors", - "dramatised", "dramatized", - "dramatises", "dramatizes", - "drivelling", "driveling", - "economised", "economized", - "economises", "economizes", - "empathised", "empathized", - "empathises", "empathizes", - "emphasised", "emphasized", - "emphasises", "emphasizes", - "enamelling", "enameling", - "endeavours", "endeavors", - "energising", "energizing", - "epaulettes", "epaulets", - "epicentres", "epicenters", - "epitomised", "epitomized", - "epitomises", "epitomizes", - "equalisers", "equalizers", - "equalising", "equalizing", - "eulogising", "eulogizing", - "evangelise", "evangelize", - "factorised", "factorized", - "factorises", "factorizes", - "fantasised", "fantasized", - "fantasises", "fantasizes", - "favourable", "favorable", - "favourably", "favorably", - "favourites", "favorites", - "feminising", "feminizing", - "fertilised", "fertilized", - "fertiliser", "fertilizer", - "fertilises", "fertilizes", - "fibreglass", "fiberglass", - "finalising", "finalizing", - "flavouring", "flavoring", - "formalised", "formalized", - "formalises", "formalizes", - "fossilised", "fossilized", - "fossilises", "fossilizes", - "fraternise", "fraternize", - "fulfilment", "fulfillment", - "funnelling", "funneling", - "galvanised", "galvanized", - "galvanises", "galvanizes", - "gambolling", "gamboling", - "gaolbreaks", "jailbreaks", - "generalise", "generalize", - "ghettoised", "ghettoized", - "ghettoises", "ghettoizes", - "globalised", "globalized", - "globalises", "globalizes", - "gonorrhoea", "gonorrhea", - "grovelling", "groveling", - "harbouring", "harboring", - "harmonised", "harmonized", - "harmonises", "harmonizes", - "homoeopath", "homeopath", - "homogenise", "homogenize", - "honourable", "honorable", - "honourably", "honorably", - "humanising", "humanizing", - "humourless", "humorless", - "hybridised", "hybridized", - "hybridises", "hybridizes", - "hypnotised", "hypnotized", - "hypnotises", "hypnotizes", - "idealising", "idealizing", - "immobilise", "immobilize", - "immunising", "immunizing", - "impanelled", "impaneled", - "imperilled", "imperiled", - "inflexions", "inflections", - "initialise", "initialize", - "initialled", "initialed", - "instalment", "installment", - "ionisation", "ionization", - "italicised", "italicized", - "italicises", "italicizes", - "jeopardise", "jeopardize", - "kilogramme", "kilogram", - "kilometres", "kilometers", - "lacklustre", "lackluster", - "legalising", "legalizing", - "legitimise", "legitimize", - "liberalise", "liberalize", - "liquidised", "liquidized", - "liquidiser", "liquidizer", - "liquidises", "liquidizes", - "localising", "localizing", - "magnetised", "magnetized", - "magnetises", "magnetizes", - "manoeuvred", "maneuvered", - "manoeuvres", "maneuvers", - "marshalled", "marshaled", - "marvelling", "marveling", - "marvellous", "marvelous", - "maximising", "maximizing", - "mechanised", "mechanized", - "mechanises", "mechanizes", - "memorising", "memorizing", - "mesmerised", "mesmerized", - "mesmerises", "mesmerizes", - "metabolise", "metabolize", - "micrometre", "micrometer", - "militarise", "militarize", - "millilitre", "milliliter", - "millimetre", "millimeter", - "minimising", "minimizing", - "mobilising", "mobilizing", - "modernised", "modernized", - "modernises", "modernizes", - "moisturise", "moisturize", - "monopolise", "monopolize", - "moralising", "moralizing", - "mouldering", "moldering", - "moustached", "mustached", - "moustaches", "mustaches", - "naturalise", "naturalize", - "neighbours", "neighbors", - "neutralise", "neutralize", - "normalised", "normalized", - "normalises", "normalizes", - "oesophagus", "esophagus", - "optimising", "optimizing", - "organisers", "organizers", - "organising", "organizing", - "ostracised", "ostracized", - "ostracises", "ostracizes", - "paederasts", "pederasts", - "paediatric", "pediatric", - "paedophile", "pedophile", - "panellists", "panelists", - "paralysing", "paralyzing", - "parcelling", "parceling", - "passivised", "passivized", - "passivises", "passivizes", - "pasteurise", "pasteurize", - "patronised", "patronized", - "patronises", "patronizes", - "penalising", "penalizing", - "pencilling", "penciling", - "plagiarise", "plagiarize", - "polarising", "polarizing", - "politicise", "politicize", - "popularise", "popularize", - "practising", "practicing", - "praesidium", "presidium", - "pressurise", "pressurize", - "prioritise", "prioritize", - "privatised", "privatized", - "privatises", "privatizes", - "programmes", "programs", - "publicised", "publicized", - "publicises", "publicizes", - "pulverised", "pulverized", - "pulverises", "pulverizes", - "pummelling", "pummeled", - "quarrelled", "quarreled", - "radicalise", "radicalize", - "randomised", "randomized", - "randomises", "randomizes", - "realisable", "realizable", - "recognised", "recognized", - "recognises", "recognizes", - "refuelling", "refueling", - "regularise", "regularize", - "remodelled", "remodeled", - "remoulding", "remolding", - "reorganise", "reorganize", - "revitalise", "revitalize", - "rhapsodise", "rhapsodize", - "ritualised", "ritualized", - "sanitising", "sanitizing", - "satirising", "satirizing", - "scandalise", "scandalize", - "scepticism", "skepticism", - "scrutinise", "scrutinize", - "secularise", "secularize", - "sensitised", "sensitized", - "sensitises", "sensitizes", - "sepulchres", "sepulchers", - "serialised", "serialized", - "serialises", "serializes", - "sermonised", "sermonized", - "sermonises", "sermonizes", - "shovelling", "shoveling", - "shrivelled", "shriveled", - "signalised", "signalized", - "signalises", "signalizes", - "signalling", "signaling", - "snivelling", "sniveling", - "snorkelled", "snorkeled", - "snowplough", "snowplow", - "socialised", "socialized", - "socialises", "socializes", - "sodomising", "sodomizing", - "solemnised", "solemnized", - "solemnises", "solemnizes", - "specialise", "specialize", - "spiralling", "spiraling", - "splendours", "splendors", - "stabilised", "stabilized", - "stabiliser", "stabilizer", - "stabilises", "stabilizes", - "stencilled", "stenciled", - "sterilised", "sterilized", - "steriliser", "sterilizer", - "sterilises", "sterilizes", - "stigmatise", "stigmatize", - "subsidised", "subsidized", - "subsidiser", "subsidizer", - "subsidises", "subsidizes", - "succouring", "succoring", - "sulphurous", "sulfurous", - "summarised", "summarized", - "summarises", "summarizes", - "swivelling", "swiveling", - "symbolised", "symbolized", - "symbolises", "symbolizes", - "sympathise", "sympathize", - "synthesise", "synthesize", - "tantalised", "tantalized", - "tantalises", "tantalizes", - "temporised", "temporized", - "temporises", "temporizes", - "tenderised", "tenderized", - "tenderises", "tenderizes", - "terrorised", "terrorized", - "terrorises", "terrorizes", - "theorising", "theorizing", - "traumatise", "traumatize", - "travellers", "travelers", - "travelling", "traveling", - "tricolours", "tricolors", - "trivialise", "trivialize", - "tunnelling", "tunneling", - "tyrannised", "tyrannized", - "tyrannises", "tyrannizes", - "unequalled", "unequaled", - "unionising", "unionizing", - "unravelled", "unraveled", - "unrivalled", "unrivaled", - "urbanising", "urbanizing", - "utilisable", "utilizable", - "vandalised", "vandalized", - "vandalises", "vandalizes", - "vaporising", "vaporizing", - "verbalised", "verbalized", - "verbalises", "verbalizes", - "victimised", "victimized", - "victimises", "victimizes", - "visualised", "visualized", - "visualises", "visualizes", - "vocalising", "vocalizing", - "vulcanised", "vulcanized", - "vulgarised", "vulgarized", - "vulgarises", "vulgarizes", - "weaselling", "weaseling", - "westernise", "westernize", - "womanisers", "womanizers", - "womanising", "womanizing", - "worshipped", "worshiped", - "worshipper", "worshiper", - "aeroplane", "airplane", - "aetiology", "etiology", - "agonising", "agonizing", - "almanacks", "almanacs", - "aluminium", "aluminum", - "amortised", "amortized", - "amortises", "amortizes", - "analogues", "analogs", - "analysing", "analyzing", - "anglicise", "anglicize", - "apologise", "apologize", - "appetiser", "appetizer", - "armourers", "armorers", - "armouries", "armories", - "artefacts", "artifacts", - "authorise", "authorize", - "baptising", "baptizing", - "behaviour", "behavior", - "belabours", "belabors", - "brutalise", "brutalize", - "callipers", "calipers", - "canalised", "canalized", - "canalises", "canalizes", - "cancelled", "canceled", - "canonised", "canonized", - "canonises", "canonizes", - "carbonise", "carbonize", - "carolling", "caroling", - "catalogue", "catalog", - "catalysed", "catalyzed", - "catalyses", "catalyzes", - "cauterise", "cauterize", - "cavilling", "caviling", - "chequered", "checkered", - "chiselled", "chiseled", - "civilised", "civilized", - "civilises", "civilizes", - "clamoured", "clamored", - "colonised", "colonized", - "coloniser", "colonizer", - "colonises", "colonizes", - "colourant", "colorant", - "coloureds", "coloreds", - "colourful", "colorful", - "colouring", "coloring", - "colourize", "colorize", - "connexion", "connection", - "criticise", "criticize", - "cruellest", "cruelest", - "cudgelled", "cudgeled", - "customise", "customize", - "demeanour", "demeanor", - "demonised", "demonized", - "demonises", "demonizes", - "deodorise", "deodorize", - "deputised", "deputized", - "deputises", "deputizes", - "dialogues", "dialogs", - "diarrhoea", "diarrhea", - "digitised", "digitized", - "digitises", "digitizes", - "discolour", "discolor", - "disfavour", "disfavor", - "dishonour", "dishonor", - "dramatise", "dramatize", - "drivelled", "driveled", - "economise", "economize", - "empathise", "empathize", - "emphasise", "emphasize", - "enamelled", "enameled", - "enamoured", "enamored", - "endeavour", "endeavor", - "energised", "energized", - "energises", "energizes", - "epaulette", "epaulet", - "epicentre", "epicenter", - "epitomise", "epitomize", - "equalised", "equalized", - "equaliser", "equalizer", - "equalises", "equalizes", - "eulogised", "eulogized", - "eulogises", "eulogizes", - "factorise", "factorize", - "fantasise", "fantasize", - "favouring", "favoring", - "favourite", "favorite", - "feminised", "feminized", - "feminises", "feminizes", - "fertilise", "fertilize", - "finalised", "finalized", - "finalises", "finalizes", - "flautists", "flutists", - "flavoured", "flavored", - "formalise", "formalize", - "fossilise", "fossilize", - "funnelled", "funneled", - "galvanise", "galvanize", - "gambolled", "gamboled", - "gaolbirds", "jailbirds", - "gaolbreak", "jailbreak", - "ghettoise", "ghettoize", - "globalise", "globalize", - "gravelled", "graveled", - "grovelled", "groveled", - "gruelling", "grueling", - "harboured", "harbored", - "harmonise", "harmonize", - "honouring", "honoring", - "humanised", "humanized", - "humanises", "humanizes", - "humouring", "humoring", - "hybridise", "hybridize", - "hypnotise", "hypnotize", - "idealised", "idealized", - "idealises", "idealizes", - "idolising", "idolizing", - "immunised", "immunized", - "immunises", "immunizes", - "inflexion", "inflection", - "italicise", "italicize", - "itemising", "itemizing", - "jewellers", "jewelers", - "jewellery", "jewelry", - "kilometre", "kilometer", - "labelling", "labeling", - "labourers", "laborers", - "labouring", "laboring", - "legalised", "legalized", - "legalises", "legalizes", - "leukaemia", "leukemia", - "levellers", "levelers", - "levelling", "leveling", - "libelling", "libeling", - "libellous", "libelous", - "licencing", "licensing", - "lionising", "lionizing", - "liquidise", "liquidize", - "localised", "localized", - "localises", "localizes", - "magnetise", "magnetize", - "manoeuvre", "maneuver", - "marvelled", "marveled", - "maximised", "maximized", - "maximises", "maximizes", - "mechanise", "mechanize", - "mediaeval", "medieval", - "memorised", "memorized", - "memorises", "memorizes", - "mesmerise", "mesmerize", - "minimised", "minimized", - "minimises", "minimizes", - "mobilised", "mobilized", - "mobilises", "mobilizes", - "modellers", "modelers", - "modelling", "modeling", - "modernise", "modernize", - "moralised", "moralized", - "moralises", "moralizes", - "motorised", "motorized", - "mouldered", "moldered", - "mouldiest", "moldiest", - "mouldings", "moldings", - "moustache", "mustache", - "neighbour", "neighbor", - "normalise", "normalize", - "odourless", "odorless", - "oestrogen", "estrogen", - "optimised", "optimized", - "optimises", "optimizes", - "organised", "organized", - "organiser", "organizer", - "organises", "organizes", - "ostracise", "ostracize", - "oxidising", "oxidizing", - "paederast", "pederast", - "panelling", "paneling", - "panellist", "panelist", - "paralysed", "paralyzed", - "paralyses", "paralyzes", - "parcelled", "parceled", - "passivise", "passivize", - "patronise", "patronize", - "pedalling", "pedaling", - "penalised", "penalized", - "penalises", "penalizes", - "pencilled", "penciled", - "ploughing", "plowing", - "ploughman", "plowman", - "ploughmen", "plowmen", - "polarised", "polarized", - "polarises", "polarizes", - "practised", "practiced", - "practises", "practices", - "pretences", "pretenses", - "primaeval", "primeval", - "privatise", "privatize", - "programme", "program", - "publicise", "publicize", - "pulverise", "pulverize", - "pummelled", "pummel", - "randomise", "randomize", - "ravelling", "raveling", - "realising", "realizing", - "recognise", "recognize", - "refuelled", "refueled", - "remoulded", "remolded", - "revellers", "revelers", - "revelling", "reveling", - "rivalling", "rivaling", - "saltpetre", "saltpeter", - "sanitised", "sanitized", - "sanitises", "sanitizes", - "satirised", "satirized", - "satirises", "satirizes", - "savouries", "savories", - "savouring", "savoring", - "sceptical", "skeptical", - "sensitise", "sensitize", - "sepulchre", "sepulcher", - "serialise", "serialize", - "sermonise", "sermonize", - "shovelled", "shoveled", - "signalise", "signalize", - "signalled", "signaled", - "snivelled", "sniveled", - "socialise", "socialize", - "sodomised", "sodomized", - "sodomises", "sodomizes", - "solemnise", "solemnize", - "spiralled", "spiraled", - "splendour", "splendor", - "stabilise", "stabilize", - "sterilise", "sterilize", - "subsidise", "subsidize", - "succoured", "succored", - "sulphates", "sulfates", - "sulphides", "sulfides", - "summarise", "summarize", - "swivelled", "swiveled", - "symbolise", "symbolize", - "syphoning", "siphoning", - "tantalise", "tantalize", - "tasselled", "tasseled", - "temporise", "temporize", - "tenderise", "tenderize", - "terrorise", "terrorize", - "theorised", "theorized", - "theorises", "theorizes", - "towelling", "toweling", - "travelled", "traveled", - "traveller", "traveler", - "trialling", "trialing", - "tricolour", "tricolor", - "tunnelled", "tunneled", - "tyrannise", "tyrannize", - "unionised", "unionized", - "unionises", "unionizes", - "unsavoury", "unsavory", - "urbanised", "urbanized", - "urbanises", "urbanizes", - "utilising", "utilizing", - "vandalise", "vandalize", - "vaporised", "vaporized", - "vaporises", "vaporizes", - "verbalise", "verbalize", - "victimise", "victimize", - "visualise", "visualize", - "vocalised", "vocalized", - "vocalises", "vocalizes", - "vulgarise", "vulgarize", - "weaselled", "weaseled", - "womanised", "womanized", - "womaniser", "womanizer", - "womanises", "womanizes", - "yodelling", "yodeling", - "yoghourts", "yogurts", - "agonised", "agonized", - "agonises", "agonizes", - "almanack", "almanac", - "amortise", "amortize", - "analogue", "analog", - "analysed", "analyzed", - "analyses", "analyzes", - "armoured", "armored", - "armourer", "armorer", - "artefact", "artifact", - "baptised", "baptized", - "baptises", "baptizes", - "baulking", "balking", - "belabour", "belabor", - "bevelled", "beveled", - "calibres", "calibers", - "calliper", "caliper", - "canalise", "canalize", - "canonise", "canonize", - "carolled", "caroled", - "catalyse", "catalyze", - "cavilled", "caviled", - "civilise", "civilize", - "clamours", "clamors", - "clangour", "clangor", - "colonise", "colonize", - "coloured", "colored", - "cosiness", "coziness", - "crueller", "crueler", - "defences", "defenses", - "demonise", "demonize", - "deputise", "deputize", - "dialling", "dialing", - "dialogue", "dialog", - "digitise", "digitize", - "draughty", "drafty", - "duelling", "dueling", - "energise", "energize", - "enthrals", "enthralls", - "equalise", "equalize", - "eulogise", "eulogize", - "favoured", "favored", - "feminise", "feminize", - "finalise", "finalize", - "flautist", "flutist", - "flavours", "flavors", - "foetuses", "fetuses", - "fuelling", "fueling", - "gaolbird", "jailbird", - "gryphons", "griffins", - "harbours", "harbors", - "honoured", "honored", - "humanise", "humanize", - "humoured", "humored", - "idealise", "idealize", - "idolised", "idolized", - "idolises", "idolizes", - "immunise", "immunize", - "ionisers", "ionizers", - "ionising", "ionizing", - "itemised", "itemized", - "itemises", "itemizes", - "jewelled", "jeweled", - "jeweller", "jeweler", - "labelled", "labeled", - "laboured", "labored", - "labourer", "laborer", - "legalise", "legalize", - "levelled", "leveled", - "leveller", "leveler", - "libelled", "libeled", - "licenced", "licensed", - "licences", "licenses", - "lionised", "lionized", - "lionises", "lionizes", - "localise", "localize", - "maximise", "maximize", - "memorise", "memorize", - "minimise", "minimize", - "misspelt", "misspelled", - "mobilise", "mobilize", - "modelled", "modeled", - "modeller", "modeler", - "moralise", "moralize", - "moulders", "molders", - "mouldier", "moldier", - "moulding", "molding", - "moulting", "molting", - "offences", "offenses", - "optimise", "optimize", - "organise", "organize", - "oxidised", "oxidized", - "oxidises", "oxidizes", - "panelled", "paneled", - "paralyse", "paralyze", - "parlours", "parlors", - "pedalled", "pedaled", - "penalise", "penalize", - "philtres", "filters", - "ploughed", "plowed", - "polarise", "polarize", - "practise", "practice", - "pretence", "pretense", - "ravelled", "raveled", - "realised", "realized", - "realises", "realizes", - "remoulds", "remolds", - "revelled", "reveled", - "reveller", "reveler", - "rivalled", "rivaled", - "rumoured", "rumored", - "sanitise", "sanitize", - "satirise", "satirize", - "saviours", "saviors", - "savoured", "savored", - "sceptics", "skeptics", - "sceptres", "scepters", - "sodomise", "sodomize", - "spectres", "specters", - "succours", "succors", - "sulphate", "sulfate", - "sulphide", "sulfide", - "syphoned", "siphoned", - "theatres", "theaters", - "theorise", "theorize", - "towelled", "toweled", - "toxaemia", "toxemia", - "trialled", "trialed", - "unionise", "unionize", - "urbanise", "urbanize", - "utilised", "utilized", - "utilises", "utilizes", - "vaporise", "vaporize", - "vocalise", "vocalize", - "womanise", "womanize", - "yodelled", "yodeled", - "yoghourt", "yogurt", - "yoghurts", "yogurts", - "agonise", "agonize", - "anaemia", "anemia", - "anaemic", "anemic", - "analyse", "analyze", - "arbours", "arbors", - "armoury", "armory", - "baptise", "baptize", - "baulked", "balked", - "behoved", "behooved", - "behoves", "behooves", - "calibre", "caliber", - "candour", "candor", - "centred", "centered", - "centres", "centers", - "cheques", "checks", - "clamour", "clamor", - "colours", "colors", - "cosiest", "coziest", - "defence", "defense", - "dialled", "dialed", - "distils", "distills", - "duelled", "dueled", - "enthral", "enthrall", - "favours", "favors", - "fervour", "fervor", - "flavour", "flavor", - "fuelled", "fueled", - "fulfils", "fulfills", - "gaolers", "jailers", - "gaoling", "jailing", - "gipsies", "gypsies", - "glueing", "gluing", - "goitres", "goiters", - "grammes", "grams", - "groynes", "groins", - "gryphon", "griffin", - "harbour", "harbor", - "honours", "honors", - "humours", "humors", - "idolise", "idolize", - "instals", "installs", - "instils", "instills", - "ionised", "ionized", - "ioniser", "ionizer", - "ionises", "ionizes", - "itemise", "itemize", - "labours", "labors", - "licence", "license", - "lionise", "lionize", - "louvred", "louvered", - "louvres", "louvers", - "moulded", "molded", - "moulder", "molder", - "moulted", "molted", - "offence", "offense", - "oxidise", "oxidize", - "parlour", "parlor", - "philtre", "filter", - "ploughs", "plows", - "pyjamas", "pajamas", - "rancour", "rancor", - "realise", "realize", - "remould", "remold", - "rigours", "rigors", - "rumours", "rumors", - "saviour", "savior", - "savours", "savors", - "savoury", "savory", - "sceptic", "skeptic", - "sceptre", "scepter", - "spectre", "specter", - "storeys", "stories", - "succour", "succor", - "sulphur", "sulfur", - "syphons", "siphons", - "theatre", "theater", - "tumours", "tumors", - "utilise", "utilize", - "vapours", "vapors", - "waggons", "wagons", - "yoghurt", "yogurt", - "ageing", "aging", - "appals", "appalls", - "arbour", "arbor", - "ardour", "ardor", - "baulks", "balks", - "behove", "behoove", - "centre", "center", - "cheque", "check", - "chilli", "chili", - "colour", "color", - "cosier", "cozier", - "cosies", "cozies", - "cosily", "cozily", - "distil", "distill", - "edoema", "edema", - "enrols", "enrolls", - "faecal", "fecal", - "faeces", "feces", - "favour", "favor", - "fibres", "fibers", - "foetal", "fetal", - "foetid", "fetid", - "foetus", "fetus", - "fulfil", "fulfill", - "gaoled", "jailed", - "gaoler", "jailer", - "goitre", "goiter", - "gramme", "gram", - "groyne", "groin", - "honour", "honor", - "humour", "humor", - "instal", "install", - "instil", "instill", - "ionise", "ionize", - "labour", "labor", - "litres", "liters", - "lustre", "luster", - "meagre", "meager", - "metres", "meters", - "mitres", "miters", - "moulds", "molds", - "mouldy", "moldy", - "moults", "molts", - "odours", "odors", - "plough", "plow", - "pyjama", "pajama", - "rigour", "rigor", - "rumour", "rumor", - "savour", "savor", - "storey", "story", - "syphon", "siphon", - "tumour", "tumor", - "valour", "valor", - "vapour", "vapor", - "vigour", "vigor", - "waggon", "wagon", - "appal", "appall", - "baulk", "balk", - "enrol", "enroll", - "fibre", "fiber", - "gaols", "jails", - "litre", "liter", - "metre", "meter", - "mitre", "miter", - "mould", "mold", - "moult", "molt", - "odour", "odor", - "tyres", "tires", - "cosy", "cozy", - "gaol", "jail", - "tyre", "tire", -} - -// DictBritish converts US spellings to UK spellings -var DictBritish = []string{ - "institutionalization", "institutionalisation", - "internationalization", "internationalisation", - "professionalization", "professionalisation", - "compartmentalizing", "compartmentalising", - "institutionalizing", "institutionalising", - "internationalizing", "internationalising", - "compartmentalized", "compartmentalised", - "compartmentalizes", "compartmentalises", - "decriminalization", "decriminalisation", - "denationalization", "denationalisation", - "fictionalizations", "fictionalisations", - "institutionalized", "institutionalised", - "institutionalizes", "institutionalises", - "intellectualizing", "intellectualising", - "internationalized", "internationalised", - "internationalizes", "internationalises", - "pedestrianization", "pedestrianisation", - "professionalizing", "professionalising", - "compartmentalize", "compartmentalise", - "decentralization", "decentralisation", - "demilitarization", "demilitarisation", - "externalizations", "externalisations", - "fictionalization", "fictionalisation", - "institutionalize", "institutionalise", - "intellectualized", "intellectualised", - "intellectualizes", "intellectualises", - "internationalize", "internationalise", - "nationalizations", "nationalisations", - "professionalized", "professionalised", - "professionalizes", "professionalises", - "rationalizations", "rationalisations", - "sensationalizing", "sensationalising", - "sentimentalizing", "sentimentalising", - "acclimatization", "acclimatisation", - "commercializing", "commercialising", - "conceptualizing", "conceptualising", - "contextualizing", "contextualising", - "crystallization", "crystallisation", - "decriminalizing", "decriminalising", - "democratization", "democratisation", - "denationalizing", "denationalising", - "depersonalizing", "depersonalising", - "desensitization", "desensitisation", - "disorganization", "disorganisation", - "extemporization", "extemporisation", - "externalization", "externalisation", - "familiarization", "familiarisation", - "generalizations", "generalisations", - "hospitalization", "hospitalisation", - "individualizing", "individualising", - "industrializing", "industrialising", - "intellectualize", "intellectualise", - "internalization", "internalisation", - "maneuverability", "manoeuvrability", - "materialization", "materialisation", - "miniaturization", "miniaturisation", - "nationalization", "nationalisation", - "overemphasizing", "overemphasising", - "paleontologists", "palaeontologists", - "particularizing", "particularising", - "pedestrianizing", "pedestrianising", - "professionalize", "professionalise", - "psychoanalyzing", "psychoanalysing", - "rationalization", "rationalisation", - "reorganizations", "reorganisations", - "revolutionizing", "revolutionising", - "sensationalized", "sensationalised", - "sensationalizes", "sensationalises", - "sentimentalized", "sentimentalised", - "sentimentalizes", "sentimentalises", - "specializations", "specialisations", - "standardization", "standardisation", - "synchronization", "synchronisation", - "systematization", "systematisation", - "aggrandizement", "aggrandisement", - "characterizing", "characterising", - "collectivizing", "collectivising", - "commercialized", "commercialised", - "commercializes", "commercialises", - "conceptualized", "conceptualised", - "conceptualizes", "conceptualises", - "contextualized", "contextualised", - "contextualizes", "contextualises", - "decentralizing", "decentralising", - "decriminalized", "decriminalised", - "decriminalizes", "decriminalises", - "dehumanization", "dehumanisation", - "demilitarizing", "demilitarising", - "demobilization", "demobilisation", - "demoralization", "demoralisation", - "denationalized", "denationalised", - "denationalizes", "denationalises", - "depersonalized", "depersonalised", - "depersonalizes", "depersonalises", - "dramatizations", "dramatisations", - "editorializing", "editorialising", - "fictionalizing", "fictionalising", - "fraternization", "fraternisation", - "generalization", "generalisation", - "immobilization", "immobilisation", - "individualized", "individualised", - "individualizes", "individualises", - "industrialized", "industrialised", - "industrializes", "industrialises", - "liberalization", "liberalisation", - "monopolization", "monopolisation", - "naturalization", "naturalisation", - "neighborliness", "neighbourliness", - "neutralization", "neutralisation", - "organizational", "organisational", - "outmaneuvering", "outmanoeuvring", - "overemphasized", "overemphasised", - "overemphasizes", "overemphasises", - "paleontologist", "palaeontologist", - "particularized", "particularised", - "particularizes", "particularises", - "pasteurization", "pasteurisation", - "pedestrianized", "pedestrianised", - "pedestrianizes", "pedestrianises", - "philosophizing", "philosophising", - "politicization", "politicisation", - "popularization", "popularisation", - "pressurization", "pressurisation", - "prioritization", "prioritisation", - "privatizations", "privatisations", - "propagandizing", "propagandising", - "psychoanalyzed", "psychoanalysed", - "psychoanalyzes", "psychoanalyses", - "reconnoitering", "reconnoitring", - "regularization", "regularisation", - "reorganization", "reorganisation", - "revolutionized", "revolutionised", - "revolutionizes", "revolutionises", - "secularization", "secularisation", - "sensationalize", "sensationalise", - "sentimentalize", "sentimentalise", - "serializations", "serialisations", - "specialization", "specialisation", - "sterilizations", "sterilisations", - "stigmatization", "stigmatisation", - "transistorized", "transistorised", - "unrecognizable", "unrecognisable", - "visualizations", "visualisations", - "westernization", "westernisation", - "accessorizing", "accessorising", - "acclimatizing", "acclimatising", - "amortizations", "amortisations", - "amphitheaters", "amphitheatres", - "anesthetizing", "anaesthetising", - "archeologists", "archaeologists", - "breathalyzers", "breathalysers", - "breathalyzing", "breathalysing", - "cannibalizing", "cannibalising", - "characterized", "characterised", - "characterizes", "characterises", - "circularizing", "circularising", - "collectivized", "collectivised", - "collectivizes", "collectivises", - "commercialize", "commercialise", - "computerizing", "computerising", - "conceptualize", "conceptualise", - "contextualize", "contextualise", - "criminalizing", "criminalising", - "crystallizing", "crystallising", - "decentralized", "decentralised", - "decentralizes", "decentralises", - "decriminalize", "decriminalise", - "demilitarized", "demilitarised", - "demilitarizes", "demilitarises", - "democratizing", "democratising", - "denationalize", "denationalise", - "depersonalize", "depersonalise", - "desensitizing", "desensitising", - "destabilizing", "destabilising", - "disemboweling", "disembowelling", - "dramatization", "dramatisation", - "editorialized", "editorialised", - "editorializes", "editorialises", - "extemporizing", "extemporising", - "externalizing", "externalising", - "familiarizing", "familiarising", - "fertilization", "fertilisation", - "fictionalized", "fictionalised", - "fictionalizes", "fictionalises", - "formalization", "formalisation", - "fossilization", "fossilisation", - "globalization", "globalisation", - "gynecological", "gynaecological", - "gynecologists", "gynaecologists", - "harmonization", "harmonisation", - "hematological", "haematological", - "hematologists", "haematologists", - "hospitalizing", "hospitalising", - "hypothesizing", "hypothesising", - "immortalizing", "immortalising", - "individualize", "individualise", - "industrialize", "industrialise", - "internalizing", "internalising", - "marginalizing", "marginalising", - "materializing", "materialising", - "mechanization", "mechanisation", - "memorializing", "memorialising", - "miniaturizing", "miniaturising", - "nationalizing", "nationalising", - "neighborhoods", "neighbourhoods", - "normalization", "normalisation", - "organizations", "organisations", - "outmaneuvered", "outmanoeuvred", - "overemphasize", "overemphasise", - "particularize", "particularise", - "passivization", "passivisation", - "patronizingly", "patronisingly", - "pedestrianize", "pedestrianise", - "pediatricians", "paediatricians", - "personalizing", "personalising", - "philosophized", "philosophised", - "philosophizes", "philosophises", - "privatization", "privatisation", - "propagandized", "propagandised", - "propagandizes", "propagandises", - "proselytizers", "proselytisers", - "proselytizing", "proselytising", - "psychoanalyze", "psychoanalyse", - "pulverization", "pulverisation", - "rationalizing", "rationalising", - "reconnoitered", "reconnoitred", - "revolutionize", "revolutionise", - "romanticizing", "romanticising", - "serialization", "serialisation", - "socialization", "socialisation", - "standardizing", "standardising", - "sterilization", "sterilisation", - "subsidization", "subsidisation", - "synchronizing", "synchronising", - "systematizing", "systematising", - "tantalizingly", "tantalisingly", - "underutilized", "underutilised", - "victimization", "victimisation", - "visualization", "visualisation", - "vocalizations", "vocalisations", - "vulgarization", "vulgarisation", - "accessorized", "accessorised", - "accessorizes", "accessorises", - "acclimatized", "acclimatised", - "acclimatizes", "acclimatises", - "amortization", "amortisation", - "amphitheater", "amphitheatre", - "anesthetists", "anaesthetists", - "anesthetized", "anaesthetised", - "anesthetizes", "anaesthetises", - "antagonizing", "antagonising", - "appetizingly", "appetisingly", - "archeologist", "archaeologist", - "backpedaling", "backpedalling", - "bastardizing", "bastardising", - "behaviorists", "behaviourists", - "bowdlerizing", "bowdlerising", - "breathalyzed", "breathalysed", - "breathalyzes", "breathalyses", - "cannibalized", "cannibalised", - "cannibalizes", "cannibalises", - "capitalizing", "capitalising", - "caramelizing", "caramelising", - "categorizing", "categorising", - "centerpieces", "centrepieces", - "centralizing", "centralising", - "characterize", "characterise", - "circularized", "circularised", - "circularizes", "circularises", - "clarinetists", "clarinettists", - "collectivize", "collectivise", - "colonization", "colonisation", - "computerized", "computerised", - "computerizes", "computerises", - "criminalized", "criminalised", - "criminalizes", "criminalises", - "crystallized", "crystallised", - "crystallizes", "crystallises", - "decentralize", "decentralise", - "dehumanizing", "dehumanising", - "demilitarize", "demilitarise", - "demobilizing", "demobilising", - "democratized", "democratised", - "democratizes", "democratises", - "demoralizing", "demoralising", - "desensitized", "desensitised", - "desensitizes", "desensitises", - "destabilized", "destabilised", - "destabilizes", "destabilises", - "disemboweled", "disembowelled", - "dishonorable", "dishonourable", - "dishonorably", "dishonourably", - "disorganized", "disorganised", - "editorialize", "editorialise", - "equalization", "equalisation", - "evangelizing", "evangelising", - "extemporized", "extemporised", - "extemporizes", "extemporises", - "externalized", "externalised", - "externalizes", "externalises", - "familiarized", "familiarised", - "familiarizes", "familiarises", - "fictionalize", "fictionalise", - "finalization", "finalisation", - "fraternizing", "fraternising", - "generalizing", "generalising", - "gynecologist", "gynaecologist", - "hematologist", "haematologist", - "hemophiliacs", "haemophiliacs", - "hemorrhaging", "haemorrhaging", - "homogenizing", "homogenising", - "hospitalized", "hospitalised", - "hospitalizes", "hospitalises", - "hypothesized", "hypothesised", - "hypothesizes", "hypothesises", - "idealization", "idealisation", - "immobilizers", "immobilisers", - "immobilizing", "immobilising", - "immortalized", "immortalised", - "immortalizes", "immortalises", - "immunization", "immunisation", - "initializing", "initialising", - "installments", "instalments", - "internalized", "internalised", - "internalizes", "internalises", - "jeopardizing", "jeopardising", - "legalization", "legalisation", - "legitimizing", "legitimising", - "liberalizing", "liberalising", - "maneuverable", "manoeuvrable", - "maneuverings", "manoeuvrings", - "marginalized", "marginalised", - "marginalizes", "marginalises", - "materialized", "materialised", - "materializes", "materialises", - "maximization", "maximisation", - "memorialized", "memorialised", - "memorializes", "memorialises", - "metabolizing", "metabolising", - "militarizing", "militarising", - "miniaturized", "miniaturised", - "miniaturizes", "miniaturises", - "miscataloged", "miscatalogued", - "misdemeanors", "misdemeanours", - "mobilization", "mobilisation", - "moisturizers", "moisturisers", - "moisturizing", "moisturising", - "monopolizing", "monopolising", - "multicolored", "multicoloured", - "nationalized", "nationalised", - "nationalizes", "nationalises", - "naturalizing", "naturalising", - "neighborhood", "neighbourhood", - "neutralizing", "neutralising", - "organization", "organisation", - "outmaneuvers", "outmanoeuvres", - "paleontology", "palaeontology", - "pasteurizing", "pasteurising", - "pediatrician", "paediatrician", - "personalized", "personalised", - "personalizes", "personalises", - "philosophize", "philosophise", - "plagiarizing", "plagiarising", - "polarization", "polarisation", - "politicizing", "politicising", - "popularizing", "popularising", - "pressurizing", "pressurising", - "prioritizing", "prioritising", - "propagandize", "propagandise", - "proselytized", "proselytised", - "proselytizer", "proselytiser", - "proselytizes", "proselytises", - "radicalizing", "radicalising", - "rationalized", "rationalised", - "rationalizes", "rationalises", - "realizations", "realisations", - "recognizable", "recognisable", - "recognizably", "recognisably", - "recognizance", "recognisance", - "reconnoiters", "reconnoitres", - "regularizing", "regularising", - "reorganizing", "reorganising", - "revitalizing", "revitalising", - "rhapsodizing", "rhapsodising", - "romanticized", "romanticised", - "romanticizes", "romanticises", - "scandalizing", "scandalising", - "scrutinizing", "scrutinising", - "secularizing", "secularising", - "standardized", "standardised", - "standardizes", "standardises", - "stigmatizing", "stigmatising", - "sympathizers", "sympathisers", - "sympathizing", "sympathising", - "synchronized", "synchronised", - "synchronizes", "synchronises", - "synthesizing", "synthesising", - "systematized", "systematised", - "systematizes", "systematises", - "theatergoers", "theatregoers", - "traumatizing", "traumatising", - "trivializing", "trivialising", - "unauthorized", "unauthorised", - "unionization", "unionisation", - "unrecognized", "unrecognised", - "urbanization", "urbanisation", - "vaporization", "vaporisation", - "vocalization", "vocalisation", - "westernizing", "westernising", - "accessorize", "accessorise", - "acclimatize", "acclimatise", - "agonizingly", "agonisingly", - "amortizable", "amortisable", - "anesthetics", "anaesthetics", - "anesthetist", "anaesthetist", - "anesthetize", "anaesthetise", - "anglicizing", "anglicising", - "antagonized", "antagonised", - "antagonizes", "antagonises", - "apologizing", "apologising", - "backpedaled", "backpedalled", - "bastardized", "bastardised", - "bastardizes", "bastardises", - "behaviorism", "behaviourism", - "behaviorist", "behaviourist", - "bowdlerized", "bowdlerised", - "bowdlerizes", "bowdlerises", - "brutalizing", "brutalising", - "cannibalize", "cannibalise", - "capitalized", "capitalised", - "capitalizes", "capitalises", - "caramelized", "caramelised", - "caramelizes", "caramelises", - "carbonizing", "carbonising", - "categorized", "categorised", - "categorizes", "categorises", - "cauterizing", "cauterising", - "centerfolds", "centrefolds", - "centerpiece", "centrepiece", - "centiliters", "centilitres", - "centimeters", "centimetres", - "centralized", "centralised", - "centralizes", "centralises", - "circularize", "circularise", - "clarinetist", "clarinettist", - "computerize", "computerise", - "criminalize", "criminalise", - "criticizing", "criticising", - "crystallize", "crystallise", - "customizing", "customising", - "defenseless", "defenceless", - "dehumanized", "dehumanised", - "dehumanizes", "dehumanises", - "demobilized", "demobilised", - "demobilizes", "demobilises", - "democratize", "democratise", - "demoralized", "demoralised", - "demoralizes", "demoralises", - "deodorizing", "deodorising", - "desensitize", "desensitise", - "destabilize", "destabilise", - "discoloring", "discolouring", - "dishonoring", "dishonouring", - "dramatizing", "dramatising", - "economizing", "economising", - "empathizing", "empathising", - "emphasizing", "emphasising", - "endeavoring", "endeavouring", - "epitomizing", "epitomising", - "esophaguses", "oesophaguses", - "evangelized", "evangelised", - "evangelizes", "evangelises", - "extemporize", "extemporise", - "externalize", "externalise", - "factorizing", "factorising", - "familiarize", "familiarise", - "fantasizing", "fantasising", - "fertilizers", "fertilisers", - "fertilizing", "fertilising", - "formalizing", "formalising", - "fossilizing", "fossilising", - "fraternized", "fraternised", - "fraternizes", "fraternises", - "fulfillment", "fulfilment", - "galvanizing", "galvanising", - "generalized", "generalised", - "generalizes", "generalises", - "ghettoizing", "ghettoising", - "globalizing", "globalising", - "harmonizing", "harmonising", - "hemophiliac", "haemophiliac", - "hemorrhaged", "haemorrhaged", - "hemorrhages", "haemorrhages", - "hemorrhoids", "haemorrhoids", - "homogenized", "homogenised", - "homogenizes", "homogenises", - "hospitalize", "hospitalise", - "hybridizing", "hybridising", - "hypnotizing", "hypnotising", - "hypothesize", "hypothesise", - "immobilized", "immobilised", - "immobilizer", "immobiliser", - "immobilizes", "immobilises", - "immortalize", "immortalise", - "initialized", "initialised", - "initializes", "initialises", - "installment", "instalment", - "internalize", "internalise", - "italicizing", "italicising", - "jeopardized", "jeopardised", - "jeopardizes", "jeopardises", - "legitimized", "legitimised", - "legitimizes", "legitimises", - "liberalized", "liberalised", - "liberalizes", "liberalises", - "lionization", "lionisation", - "liquidizers", "liquidisers", - "liquidizing", "liquidising", - "magnetizing", "magnetising", - "maneuvering", "manoeuvring", - "marginalize", "marginalise", - "marvelously", "marvellously", - "materialize", "materialise", - "mechanizing", "mechanising", - "memorialize", "memorialise", - "mesmerizing", "mesmerising", - "metabolized", "metabolised", - "metabolizes", "metabolises", - "militarized", "militarised", - "militarizes", "militarises", - "milliliters", "millilitres", - "millimeters", "millimetres", - "miniaturize", "miniaturise", - "misbehavior", "misbehaviour", - "misdemeanor", "misdemeanour", - "modernizing", "modernising", - "moisturized", "moisturised", - "moisturizer", "moisturiser", - "moisturizes", "moisturises", - "monopolized", "monopolised", - "monopolizes", "monopolises", - "nationalize", "nationalise", - "naturalized", "naturalised", - "naturalizes", "naturalises", - "neighboring", "neighbouring", - "neutralized", "neutralised", - "neutralizes", "neutralises", - "normalizing", "normalising", - "orthopedics", "orthopaedics", - "ostracizing", "ostracising", - "outmaneuver", "outmanoeuvre", - "oxidization", "oxidisation", - "pasteurized", "pasteurised", - "pasteurizes", "pasteurises", - "patronizing", "patronising", - "personalize", "personalise", - "plagiarized", "plagiarised", - "plagiarizes", "plagiarises", - "politicized", "politicised", - "politicizes", "politicises", - "popularized", "popularised", - "popularizes", "popularises", - "pressurized", "pressurised", - "pressurizes", "pressurises", - "prioritized", "prioritised", - "prioritizes", "prioritises", - "privatizing", "privatising", - "proselytize", "proselytise", - "publicizing", "publicising", - "pulverizing", "pulverising", - "radicalized", "radicalised", - "radicalizes", "radicalises", - "randomizing", "randomising", - "rationalize", "rationalise", - "realization", "realisation", - "recognizing", "recognising", - "reconnoiter", "reconnoitre", - "regularized", "regularised", - "regularizes", "regularises", - "reorganized", "reorganised", - "reorganizes", "reorganises", - "revitalized", "revitalised", - "revitalizes", "revitalises", - "rhapsodized", "rhapsodised", - "rhapsodizes", "rhapsodises", - "romanticize", "romanticise", - "scandalized", "scandalised", - "scandalizes", "scandalises", - "scrutinized", "scrutinised", - "scrutinizes", "scrutinises", - "secularized", "secularised", - "secularizes", "secularises", - "sensitizing", "sensitising", - "serializing", "serialising", - "sermonizing", "sermonising", - "signalizing", "signalising", - "skeptically", "sceptically", - "socializing", "socialising", - "solemnizing", "solemnising", - "specialized", "specialised", - "specializes", "specialises", - "squirreling", "squirrelling", - "stabilizers", "stabilisers", - "stabilizing", "stabilising", - "standardize", "standardise", - "sterilizers", "sterilisers", - "sterilizing", "sterilising", - "stigmatized", "stigmatised", - "stigmatizes", "stigmatises", - "subsidizers", "subsidisers", - "subsidizing", "subsidising", - "summarizing", "summarising", - "symbolizing", "symbolising", - "sympathized", "sympathised", - "sympathizer", "sympathiser", - "sympathizes", "sympathises", - "synchronize", "synchronise", - "synthesized", "synthesised", - "synthesizes", "synthesises", - "systematize", "systematise", - "tantalizing", "tantalising", - "temporizing", "temporising", - "tenderizing", "tenderising", - "terrorizing", "terrorising", - "theatergoer", "theatregoer", - "traumatized", "traumatised", - "traumatizes", "traumatises", - "trivialized", "trivialised", - "trivializes", "trivialises", - "tyrannizing", "tyrannising", - "uncataloged", "uncatalogued", - "uncivilized", "uncivilised", - "unfavorable", "unfavourable", - "unfavorably", "unfavourably", - "unorganized", "unorganised", - "untrammeled", "untrammelled", - "utilization", "utilisation", - "vandalizing", "vandalising", - "verbalizing", "verbalising", - "victimizing", "victimising", - "visualizing", "visualising", - "vulgarizing", "vulgarising", - "watercolors", "watercolours", - "westernized", "westernised", - "westernizes", "westernises", - "amortizing", "amortising", - "anesthesia", "anaesthesia", - "anesthetic", "anaesthetic", - "anglicized", "anglicised", - "anglicizes", "anglicises", - "annualized", "annualised", - "antagonize", "antagonise", - "apologized", "apologised", - "apologizes", "apologises", - "appetizers", "appetisers", - "appetizing", "appetising", - "archeology", "archaeology", - "authorizes", "authorises", - "bastardize", "bastardise", - "bedeviling", "bedevilling", - "behavioral", "behavioural", - "belaboring", "belabouring", - "bowdlerize", "bowdlerise", - "brutalized", "brutalised", - "brutalizes", "brutalises", - "canalizing", "canalising", - "canonizing", "canonising", - "capitalize", "capitalise", - "caramelize", "caramelise", - "carbonized", "carbonised", - "carbonizes", "carbonises", - "cataloging", "cataloguing", - "catalyzing", "catalysing", - "categorize", "categorise", - "cauterized", "cauterised", - "cauterizes", "cauterises", - "centerfold", "centrefold", - "centiliter", "centilitre", - "centimeter", "centimetre", - "centralize", "centralise", - "channeling", "channelling", - "checkbooks", "chequebooks", - "civilizing", "civilising", - "colonizers", "colonisers", - "colonizing", "colonising", - "colorfully", "colourfully", - "colorizing", "colourizing", - "councilors", "councillors", - "counselors", "counsellors", - "criticized", "criticised", - "criticizes", "criticises", - "customized", "customised", - "customizes", "customises", - "dehumanize", "dehumanise", - "demobilize", "demobilise", - "demonizing", "demonising", - "demoralize", "demoralise", - "deodorized", "deodorised", - "deodorizes", "deodorises", - "deputizing", "deputising", - "digitizing", "digitising", - "discolored", "discoloured", - "disheveled", "dishevelled", - "dishonored", "dishonoured", - "dramatized", "dramatised", - "dramatizes", "dramatises", - "economized", "economised", - "economizes", "economises", - "empathized", "empathised", - "empathizes", "empathises", - "emphasized", "emphasised", - "emphasizes", "emphasises", - "endeavored", "endeavoured", - "energizing", "energising", - "epicenters", "epicentres", - "epitomized", "epitomised", - "epitomizes", "epitomises", - "equalizers", "equalisers", - "equalizing", "equalising", - "eulogizing", "eulogising", - "evangelize", "evangelise", - "factorized", "factorised", - "factorizes", "factorises", - "fantasized", "fantasised", - "fantasizes", "fantasises", - "favoritism", "favouritism", - "feminizing", "feminising", - "fertilized", "fertilised", - "fertilizer", "fertiliser", - "fertilizes", "fertilises", - "fiberglass", "fibreglass", - "finalizing", "finalising", - "flavorings", "flavourings", - "flavorless", "flavourless", - "flavorsome", "flavoursome", - "formalized", "formalised", - "formalizes", "formalises", - "fossilized", "fossilised", - "fossilizes", "fossilises", - "fraternize", "fraternise", - "galvanized", "galvanised", - "galvanizes", "galvanises", - "generalize", "generalise", - "ghettoized", "ghettoised", - "ghettoizes", "ghettoises", - "globalized", "globalised", - "globalizes", "globalises", - "gruelingly", "gruellingly", - "gynecology", "gynaecology", - "harmonized", "harmonised", - "harmonizes", "harmonises", - "hematology", "haematology", - "hemoglobin", "haemoglobin", - "hemophilia", "haemophilia", - "hemorrhage", "haemorrhage", - "homogenize", "homogenise", - "humanizing", "humanising", - "hybridized", "hybridised", - "hybridizes", "hybridises", - "hypnotized", "hypnotised", - "hypnotizes", "hypnotises", - "idealizing", "idealising", - "immobilize", "immobilise", - "immunizing", "immunising", - "impaneling", "impanelling", - "imperiling", "imperilling", - "initialing", "initialling", - "initialize", "initialise", - "ionization", "ionisation", - "italicized", "italicised", - "italicizes", "italicises", - "jeopardize", "jeopardise", - "kilometers", "kilometres", - "lackluster", "lacklustre", - "legalizing", "legalising", - "legitimize", "legitimise", - "liberalize", "liberalise", - "liquidized", "liquidised", - "liquidizer", "liquidiser", - "liquidizes", "liquidises", - "localizing", "localising", - "magnetized", "magnetised", - "magnetizes", "magnetises", - "maneuvered", "manoeuvred", - "marshaling", "marshalling", - "maximizing", "maximising", - "mechanized", "mechanised", - "mechanizes", "mechanises", - "memorizing", "memorising", - "mesmerized", "mesmerised", - "mesmerizes", "mesmerises", - "metabolize", "metabolise", - "militarize", "militarise", - "milliliter", "millilitre", - "millimeter", "millimetre", - "minimizing", "minimising", - "mobilizing", "mobilising", - "modernized", "modernised", - "modernizes", "modernises", - "moisturize", "moisturise", - "monopolize", "monopolise", - "moralizing", "moralising", - "naturalize", "naturalise", - "neighborly", "neighbourly", - "neutralize", "neutralise", - "normalized", "normalised", - "normalizes", "normalises", - "optimizing", "optimising", - "organizers", "organisers", - "organizing", "organising", - "orthopedic", "orthopaedic", - "ostracized", "ostracised", - "ostracizes", "ostracises", - "paralyzing", "paralysing", - "pasteurize", "pasteurise", - "patronized", "patronised", - "patronizes", "patronises", - "pedophiles", "paedophiles", - "pedophilia", "paedophilia", - "penalizing", "penalising", - "plagiarize", "plagiarise", - "plowshares", "ploughshares", - "polarizing", "polarising", - "politicize", "politicise", - "popularize", "popularise", - "prioritize", "prioritise", - "privatized", "privatised", - "privatizes", "privatises", - "publicized", "publicised", - "publicizes", "publicises", - "pulverized", "pulverised", - "pulverizes", "pulverises", - "quarreling", "quarrelling", - "radicalize", "radicalise", - "randomized", "randomised", - "randomizes", "randomises", - "realizable", "realisable", - "recognized", "recognised", - "recognizes", "recognises", - "regularize", "regularise", - "remodeling", "remodelling", - "reorganize", "reorganise", - "revitalize", "revitalise", - "rhapsodize", "rhapsodise", - "ritualized", "ritualised", - "sanitizing", "sanitising", - "satirizing", "satirising", - "scandalize", "scandalise", - "scrutinize", "scrutinise", - "secularize", "secularise", - "sensitized", "sensitised", - "sensitizes", "sensitises", - "sepulchers", "sepulchres", - "serialized", "serialised", - "serializes", "serialises", - "sermonized", "sermonised", - "sermonizes", "sermonises", - "shriveling", "shrivelling", - "signalized", "signalised", - "signalizes", "signalises", - "skepticism", "scepticism", - "socialized", "socialised", - "socializes", "socialises", - "sodomizing", "sodomising", - "solemnized", "solemnised", - "solemnizes", "solemnises", - "specialize", "specialise", - "squirreled", "squirrelled", - "stabilized", "stabilised", - "stabilizer", "stabiliser", - "stabilizes", "stabilises", - "stenciling", "stencilling", - "sterilized", "sterilised", - "sterilizer", "steriliser", - "sterilizes", "sterilises", - "stigmatize", "stigmatise", - "subsidized", "subsidised", - "subsidizer", "subsidiser", - "subsidizes", "subsidises", - "summarized", "summarised", - "summarizes", "summarises", - "symbolized", "symbolised", - "symbolizes", "symbolises", - "sympathize", "sympathise", - "tantalized", "tantalised", - "tantalizes", "tantalises", - "temporized", "temporised", - "temporizes", "temporises", - "tenderized", "tenderised", - "tenderizes", "tenderises", - "terrorized", "terrorised", - "terrorizes", "terrorises", - "theorizing", "theorising", - "traumatize", "traumatise", - "trivialize", "trivialise", - "tyrannized", "tyrannised", - "tyrannizes", "tyrannises", - "unionizing", "unionising", - "unraveling", "unravelling", - "urbanizing", "urbanising", - "utilizable", "utilisable", - "vandalized", "vandalised", - "vandalizes", "vandalises", - "vaporizing", "vaporising", - "verbalized", "verbalised", - "verbalizes", "verbalises", - "victimized", "victimised", - "victimizes", "victimises", - "visualized", "visualised", - "visualizes", "visualises", - "vocalizing", "vocalising", - "vulcanized", "vulcanised", - "vulgarized", "vulgarised", - "vulgarizes", "vulgarises", - "watercolor", "watercolour", - "westernize", "westernise", - "womanizers", "womanisers", - "womanizing", "womanising", - "worshiping", "worshipping", - "agonizing", "agonising", - "airplanes", "aeroplanes", - "amortized", "amortised", - "amortizes", "amortises", - "analyzing", "analysing", - "apologize", "apologise", - "appetizer", "appetiser", - "artifacts", "artefacts", - "baptizing", "baptising", - "bedeviled", "bedevilled", - "behaviors", "behaviours", - "bejeweled", "bejewelled", - "belabored", "belaboured", - "brutalize", "brutalise", - "canalized", "canalised", - "canalizes", "canalises", - "canonized", "canonised", - "canonizes", "canonises", - "carbonize", "carbonise", - "cataloged", "catalogued", - "catalyzed", "catalysed", - "catalyzes", "catalyses", - "cauterize", "cauterise", - "channeled", "channelled", - "checkbook", "chequebook", - "checkered", "chequered", - "chiseling", "chiselling", - "civilized", "civilised", - "civilizes", "civilises", - "clamoring", "clamouring", - "colonized", "colonised", - "colonizer", "coloniser", - "colonizes", "colonises", - "colorants", "colourants", - "colorized", "colourized", - "colorizes", "colourizes", - "colorless", "colourless", - "councilor", "councillor", - "counseled", "counselled", - "counselor", "counsellor", - "criticize", "criticise", - "cudgeling", "cudgelling", - "customize", "customise", - "demonized", "demonised", - "demonizes", "demonises", - "deodorize", "deodorise", - "deputized", "deputised", - "deputizes", "deputises", - "digitized", "digitised", - "digitizes", "digitises", - "discolors", "discolours", - "dishonors", "dishonours", - "dramatize", "dramatise", - "driveling", "drivelling", - "economize", "economise", - "empathize", "empathise", - "emphasize", "emphasise", - "enameling", "enamelling", - "endeavors", "endeavours", - "energized", "energised", - "energizes", "energises", - "enthralls", "enthrals", - "epicenter", "epicentre", - "epitomize", "epitomise", - "equalized", "equalised", - "equalizer", "equaliser", - "equalizes", "equalises", - "eulogized", "eulogised", - "eulogizes", "eulogises", - "factorize", "factorise", - "fantasize", "fantasise", - "favorable", "favourable", - "favorably", "favourably", - "favorites", "favourites", - "feminized", "feminised", - "feminizes", "feminises", - "fertilize", "fertilise", - "finalized", "finalised", - "finalizes", "finalises", - "flavoring", "flavouring", - "formalize", "formalise", - "fossilize", "fossilise", - "funneling", "funnelling", - "galvanize", "galvanise", - "gamboling", "gambolling", - "ghettoize", "ghettoise", - "globalize", "globalise", - "gonorrhea", "gonorrhoea", - "groveling", "grovelling", - "harboring", "harbouring", - "harmonize", "harmonise", - "honorably", "honourably", - "humanized", "humanised", - "humanizes", "humanises", - "hybridize", "hybridise", - "hypnotize", "hypnotise", - "idealized", "idealised", - "idealizes", "idealises", - "idolizing", "idolising", - "immunized", "immunised", - "immunizes", "immunises", - "impaneled", "impanelled", - "imperiled", "imperilled", - "initialed", "initialled", - "italicize", "italicise", - "itemizing", "itemising", - "kilometer", "kilometre", - "legalized", "legalised", - "legalizes", "legalises", - "lionizing", "lionising", - "liquidize", "liquidise", - "localized", "localised", - "localizes", "localises", - "magnetize", "magnetise", - "maneuvers", "manoeuvres", - "marshaled", "marshalled", - "marveling", "marvelling", - "marvelous", "marvellous", - "maximized", "maximised", - "maximizes", "maximises", - "mechanize", "mechanise", - "memorized", "memorised", - "memorizes", "memorises", - "mesmerize", "mesmerise", - "minimized", "minimised", - "minimizes", "minimises", - "mobilized", "mobilised", - "mobilizes", "mobilises", - "modernize", "modernise", - "moldering", "mouldering", - "moralized", "moralised", - "moralizes", "moralises", - "motorized", "motorised", - "mustached", "moustached", - "mustaches", "moustaches", - "neighbors", "neighbours", - "normalize", "normalise", - "optimized", "optimised", - "optimizes", "optimises", - "organized", "organised", - "organizer", "organiser", - "organizes", "organises", - "ostracize", "ostracise", - "oxidizing", "oxidising", - "panelists", "panellists", - "paralyzed", "paralysed", - "paralyzes", "paralyses", - "parceling", "parcelling", - "patronize", "patronise", - "pedophile", "paedophile", - "penalized", "penalised", - "penalizes", "penalises", - "penciling", "pencilling", - "plowshare", "ploughshare", - "polarized", "polarised", - "polarizes", "polarises", - "practiced", "practised", - "pretenses", "pretences", - "privatize", "privatise", - "publicize", "publicise", - "pulverize", "pulverise", - "quarreled", "quarrelled", - "randomize", "randomise", - "realizing", "realising", - "recognize", "recognise", - "refueling", "refuelling", - "remodeled", "remodelled", - "remolding", "remoulding", - "saltpeter", "saltpetre", - "sanitized", "sanitised", - "sanitizes", "sanitises", - "satirized", "satirised", - "satirizes", "satirises", - "sensitize", "sensitise", - "sepulcher", "sepulchre", - "serialize", "serialise", - "sermonize", "sermonise", - "shoveling", "shovelling", - "shriveled", "shrivelled", - "signaling", "signalling", - "signalize", "signalise", - "skeptical", "sceptical", - "sniveling", "snivelling", - "snorkeled", "snorkelled", - "socialize", "socialise", - "sodomized", "sodomised", - "sodomizes", "sodomises", - "solemnize", "solemnise", - "spiraling", "spiralling", - "splendors", "splendours", - "stabilize", "stabilise", - "stenciled", "stencilled", - "sterilize", "sterilise", - "subsidize", "subsidise", - "succoring", "succouring", - "sulfurous", "sulphurous", - "summarize", "summarise", - "swiveling", "swivelling", - "symbolize", "symbolise", - "tantalize", "tantalise", - "temporize", "temporise", - "tenderize", "tenderise", - "terrorize", "terrorise", - "theorized", "theorised", - "theorizes", "theorises", - "travelers", "travellers", - "traveling", "travelling", - "tricolors", "tricolours", - "tunneling", "tunnelling", - "tyrannize", "tyrannise", - "unequaled", "unequalled", - "unionized", "unionised", - "unionizes", "unionises", - "unraveled", "unravelled", - "unrivaled", "unrivalled", - "urbanized", "urbanised", - "urbanizes", "urbanises", - "utilizing", "utilising", - "vandalize", "vandalise", - "vaporized", "vaporised", - "vaporizes", "vaporises", - "verbalize", "verbalise", - "victimize", "victimise", - "visualize", "visualise", - "vocalized", "vocalised", - "vocalizes", "vocalises", - "vulgarize", "vulgarise", - "weaseling", "weaselling", - "womanized", "womanised", - "womanizer", "womaniser", - "womanizes", "womanises", - "worshiped", "worshipped", - "worshiper", "worshipper", - "agonized", "agonised", - "agonizes", "agonises", - "airplane", "aeroplane", - "aluminum", "aluminium", - "amortize", "amortise", - "analyzed", "analysed", - "analyzes", "analyses", - "armorers", "armourers", - "armories", "armouries", - "artifact", "artefact", - "baptized", "baptised", - "baptizes", "baptises", - "behavior", "behaviour", - "behooved", "behoved", - "behooves", "behoves", - "belabors", "belabours", - "calibers", "calibres", - "canalize", "canalise", - "canonize", "canonise", - "catalogs", "catalogues", - "catalyze", "catalyse", - "caviling", "cavilling", - "centered", "centred", - "chiseled", "chiselled", - "civilize", "civilise", - "clamored", "clamoured", - "colonize", "colonise", - "colorant", "colourant", - "coloreds", "coloureds", - "colorful", "colourful", - "coloring", "colouring", - "colorize", "colourize", - "coziness", "cosiness", - "cruelest", "cruellest", - "cudgeled", "cudgelled", - "defenses", "defences", - "demeanor", "demeanour", - "demonize", "demonise", - "deputize", "deputise", - "diarrhea", "diarrhoea", - "digitize", "digitise", - "disfavor", "disfavour", - "dishonor", "dishonour", - "distills", "distils", - "driveled", "drivelled", - "enameled", "enamelled", - "enamored", "enamoured", - "endeavor", "endeavour", - "energize", "energise", - "epaulets", "epaulettes", - "equalize", "equalise", - "estrogen", "oestrogen", - "etiology", "aetiology", - "eulogize", "eulogise", - "favoring", "favouring", - "favorite", "favourite", - "feminize", "feminise", - "finalize", "finalise", - "flavored", "flavoured", - "flutists", "flautists", - "fulfills", "fulfils", - "funneled", "funnelled", - "gamboled", "gambolled", - "graveled", "gravelled", - "groveled", "grovelled", - "grueling", "gruelling", - "harbored", "harboured", - "honoring", "honouring", - "humanize", "humanise", - "humoring", "humouring", - "idealize", "idealise", - "idolized", "idolised", - "idolizes", "idolises", - "immunize", "immunise", - "ionizing", "ionising", - "itemized", "itemised", - "itemizes", "itemises", - "jewelers", "jewellers", - "labeling", "labelling", - "laborers", "labourers", - "laboring", "labouring", - "legalize", "legalise", - "leukemia", "leukaemia", - "levelers", "levellers", - "leveling", "levelling", - "libeling", "libelling", - "libelous", "libellous", - "lionized", "lionised", - "lionizes", "lionises", - "localize", "localise", - "louvered", "louvred", - "maneuver", "manoeuvre", - "marveled", "marvelled", - "maximize", "maximise", - "memorize", "memorise", - "minimize", "minimise", - "mobilize", "mobilise", - "modelers", "modellers", - "modeling", "modelling", - "moldered", "mouldered", - "moldiest", "mouldiest", - "moldings", "mouldings", - "moralize", "moralise", - "mustache", "moustache", - "neighbor", "neighbour", - "odorless", "odourless", - "offenses", "offences", - "optimize", "optimise", - "organize", "organise", - "oxidized", "oxidised", - "oxidizes", "oxidises", - "paneling", "panelling", - "panelist", "panellist", - "paralyze", "paralyse", - "parceled", "parcelled", - "pedaling", "pedalling", - "penalize", "penalise", - "penciled", "pencilled", - "polarize", "polarise", - "pretense", "pretence", - "pummeled", "pummelling", - "raveling", "ravelling", - "realized", "realised", - "realizes", "realises", - "refueled", "refuelled", - "remolded", "remoulded", - "revelers", "revellers", - "reveling", "revelling", - "rivaling", "rivalling", - "sanitize", "sanitise", - "satirize", "satirise", - "savories", "savouries", - "savoring", "savouring", - "scepters", "sceptres", - "shoveled", "shovelled", - "signaled", "signalled", - "skeptics", "sceptics", - "sniveled", "snivelled", - "sodomize", "sodomise", - "specters", "spectres", - "spiraled", "spiralled", - "splendor", "splendour", - "succored", "succoured", - "sulfates", "sulphates", - "sulfides", "sulphides", - "swiveled", "swivelled", - "tasseled", "tasselled", - "theaters", "theatres", - "theorize", "theorise", - "toweling", "towelling", - "traveler", "traveller", - "trialing", "trialling", - "tricolor", "tricolour", - "tunneled", "tunnelled", - "unionize", "unionise", - "unsavory", "unsavoury", - "urbanize", "urbanise", - "utilized", "utilised", - "utilizes", "utilises", - "vaporize", "vaporise", - "vocalize", "vocalise", - "weaseled", "weaselled", - "womanize", "womanise", - "yodeling", "yodelling", - "agonize", "agonise", - "analyze", "analyse", - "appalls", "appals", - "armored", "armoured", - "armorer", "armourer", - "baptize", "baptise", - "behoove", "behove", - "belabor", "belabour", - "beveled", "bevelled", - "caliber", "calibre", - "caroled", "carolled", - "caviled", "cavilled", - "centers", "centres", - "clamors", "clamours", - "clangor", "clangour", - "colored", "coloured", - "coziest", "cosiest", - "crueler", "crueller", - "defense", "defence", - "dialing", "dialling", - "dialogs", "dialogues", - "distill", "distil", - "dueling", "duelling", - "enrolls", "enrols", - "epaulet", "epaulette", - "favored", "favoured", - "flavors", "flavours", - "flutist", "flautist", - "fueling", "fuelling", - "fulfill", "fulfil", - "goiters", "goitres", - "harbors", "harbours", - "honored", "honoured", - "humored", "humoured", - "idolize", "idolise", - "ionized", "ionised", - "ionizes", "ionises", - "itemize", "itemise", - "jeweled", "jewelled", - "jeweler", "jeweller", - "jewelry", "jewellery", - "labeled", "labelled", - "labored", "laboured", - "laborer", "labourer", - "leveled", "levelled", - "leveler", "leveller", - "libeled", "libelled", - "lionize", "lionise", - "louvers", "louvres", - "modeled", "modelled", - "modeler", "modeller", - "molders", "moulders", - "moldier", "mouldier", - "molding", "moulding", - "molting", "moulting", - "offense", "offence", - "oxidize", "oxidise", - "pajamas", "pyjamas", - "paneled", "panelled", - "parlors", "parlours", - "pedaled", "pedalled", - "plowing", "ploughing", - "plowman", "ploughman", - "plowmen", "ploughmen", - "realize", "realise", - "remolds", "remoulds", - "reveled", "revelled", - "reveler", "reveller", - "rivaled", "rivalled", - "rumored", "rumoured", - "saviors", "saviours", - "savored", "savoured", - "scepter", "sceptre", - "skeptic", "sceptic", - "specter", "spectre", - "succors", "succours", - "sulfate", "sulphate", - "sulfide", "sulphide", - "theater", "theatre", - "toweled", "towelled", - "toxemia", "toxaemia", - "trialed", "trialled", - "utilize", "utilise", - "yodeled", "yodelled", - "anemia", "anaemia", - "anemic", "anaemic", - "appall", "appal", - "arbors", "arbours", - "armory", "armoury", - "candor", "candour", - "center", "centre", - "clamor", "clamour", - "colors", "colours", - "cozier", "cosier", - "cozies", "cosies", - "cozily", "cosily", - "dialed", "dialled", - "drafty", "draughty", - "dueled", "duelled", - "favors", "favours", - "fervor", "fervour", - "fibers", "fibres", - "flavor", "flavour", - "fueled", "fuelled", - "goiter", "goitre", - "harbor", "harbour", - "honors", "honours", - "humors", "humours", - "labors", "labours", - "liters", "litres", - "louver", "louvre", - "luster", "lustre", - "meager", "meagre", - "miters", "mitres", - "molded", "moulded", - "molder", "moulder", - "molted", "moulted", - "pajama", "pyjama", - "parlor", "parlour", - "plowed", "ploughed", - "rancor", "rancour", - "remold", "remould", - "rigors", "rigours", - "rumors", "rumours", - "savors", "savours", - "savory", "savoury", - "succor", "succour", - "tumors", "tumours", - "vapors", "vapours", - "aging", "ageing", - "arbor", "arbour", - "ardor", "ardour", - "armor", "armour", - "chili", "chilli", - "color", "colour", - "edema", "edoema", - "favor", "favour", - "fecal", "faecal", - "feces", "faeces", - "fiber", "fibre", - "honor", "honour", - "humor", "humour", - "labor", "labour", - "liter", "litre", - "miter", "mitre", - "molds", "moulds", - "moldy", "mouldy", - "molts", "moults", - "odors", "odours", - "plows", "ploughs", - "rigor", "rigour", - "rumor", "rumour", - "savor", "savour", - "valor", "valour", - "vapor", "vapour", - "vigor", "vigour", - "cozy", "cosy", - "mold", "mould", - "molt", "moult", - "odor", "odour", - "plow", "plough", -} diff --git a/vendor/github.com/golangci/misspell/words_uk.go b/vendor/github.com/golangci/misspell/words_uk.go new file mode 100644 index 000000000..01ae08702 --- /dev/null +++ b/vendor/github.com/golangci/misspell/words_uk.go @@ -0,0 +1,1484 @@ +// Code generated by 'internal/gen'. DO NOT EDIT. + +package misspell + +// DictBritish converts US spellings to UK spellings +var DictBritish = []string{ + "institutionalization", "institutionalisation", + "internationalization", "internationalisation", + "professionalization", "professionalisation", + "compartmentalizing", "compartmentalising", + "institutionalizing", "institutionalising", + "internationalizing", "internationalising", + "compartmentalized", "compartmentalised", + "compartmentalizes", "compartmentalises", + "decriminalization", "decriminalisation", + "denationalization", "denationalisation", + "fictionalizations", "fictionalisations", + "institutionalized", "institutionalised", + "institutionalizes", "institutionalises", + "intellectualizing", "intellectualising", + "internationalized", "internationalised", + "internationalizes", "internationalises", + "pedestrianization", "pedestrianisation", + "professionalizing", "professionalising", + "compartmentalize", "compartmentalise", + "decentralization", "decentralisation", + "demilitarization", "demilitarisation", + "externalizations", "externalisations", + "fictionalization", "fictionalisation", + "institutionalize", "institutionalise", + "intellectualized", "intellectualised", + "intellectualizes", "intellectualises", + "internationalize", "internationalise", + "nationalizations", "nationalisations", + "professionalized", "professionalised", + "professionalizes", "professionalises", + "rationalizations", "rationalisations", + "sensationalizing", "sensationalising", + "sentimentalizing", "sentimentalising", + "acclimatization", "acclimatisation", + "commercializing", "commercialising", + "conceptualizing", "conceptualising", + "contextualizing", "contextualising", + "crystallization", "crystallisation", + "decriminalizing", "decriminalising", + "democratization", "democratisation", + "denationalizing", "denationalising", + "depersonalizing", "depersonalising", + "desensitization", "desensitisation", + "disorganization", "disorganisation", + "extemporization", "extemporisation", + "externalization", "externalisation", + "familiarization", "familiarisation", + "generalizations", "generalisations", + "hospitalization", "hospitalisation", + "individualizing", "individualising", + "industrializing", "industrialising", + "intellectualize", "intellectualise", + "internalization", "internalisation", + "maneuverability", "manoeuvrability", + "materialization", "materialisation", + "miniaturization", "miniaturisation", + "nationalization", "nationalisation", + "overemphasizing", "overemphasising", + "paleontologists", "palaeontologists", + "particularizing", "particularising", + "pedestrianizing", "pedestrianising", + "professionalize", "professionalise", + "psychoanalyzing", "psychoanalysing", + "rationalization", "rationalisation", + "reorganizations", "reorganisations", + "revolutionizing", "revolutionising", + "sensationalized", "sensationalised", + "sensationalizes", "sensationalises", + "sentimentalized", "sentimentalised", + "sentimentalizes", "sentimentalises", + "specializations", "specialisations", + "standardization", "standardisation", + "synchronization", "synchronisation", + "systematization", "systematisation", + "aggrandizement", "aggrandisement", + "characterizing", "characterising", + "collectivizing", "collectivising", + "commercialized", "commercialised", + "commercializes", "commercialises", + "conceptualized", "conceptualised", + "conceptualizes", "conceptualises", + "contextualized", "contextualised", + "contextualizes", "contextualises", + "decentralizing", "decentralising", + "decriminalized", "decriminalised", + "decriminalizes", "decriminalises", + "dehumanization", "dehumanisation", + "demilitarizing", "demilitarising", + "demobilization", "demobilisation", + "demoralization", "demoralisation", + "denationalized", "denationalised", + "denationalizes", "denationalises", + "depersonalized", "depersonalised", + "depersonalizes", "depersonalises", + "dramatizations", "dramatisations", + "editorializing", "editorialising", + "fictionalizing", "fictionalising", + "fraternization", "fraternisation", + "generalization", "generalisation", + "immobilization", "immobilisation", + "individualized", "individualised", + "individualizes", "individualises", + "industrialized", "industrialised", + "industrializes", "industrialises", + "liberalization", "liberalisation", + "monopolization", "monopolisation", + "naturalization", "naturalisation", + "neighborliness", "neighbourliness", + "neutralization", "neutralisation", + "organizational", "organisational", + "outmaneuvering", "outmanoeuvring", + "overemphasized", "overemphasised", + "overemphasizes", "overemphasises", + "paleontologist", "palaeontologist", + "particularized", "particularised", + "particularizes", "particularises", + "pasteurization", "pasteurisation", + "pedestrianized", "pedestrianised", + "pedestrianizes", "pedestrianises", + "philosophizing", "philosophising", + "politicization", "politicisation", + "popularization", "popularisation", + "pressurization", "pressurisation", + "prioritization", "prioritisation", + "privatizations", "privatisations", + "propagandizing", "propagandising", + "psychoanalyzed", "psychoanalysed", + "psychoanalyzes", "psychoanalyses", + "reconnoitering", "reconnoitring", + "regularization", "regularisation", + "reorganization", "reorganisation", + "revolutionized", "revolutionised", + "revolutionizes", "revolutionises", + "secularization", "secularisation", + "sensationalize", "sensationalise", + "sentimentalize", "sentimentalise", + "serializations", "serialisations", + "specialization", "specialisation", + "sterilizations", "sterilisations", + "stigmatization", "stigmatisation", + "transistorized", "transistorised", + "unrecognizable", "unrecognisable", + "visualizations", "visualisations", + "westernization", "westernisation", + "accessorizing", "accessorising", + "acclimatizing", "acclimatising", + "amortizations", "amortisations", + "amphitheaters", "amphitheatres", + "anesthetizing", "anaesthetising", + "archeologists", "archaeologists", + "breathalyzers", "breathalysers", + "breathalyzing", "breathalysing", + "cannibalizing", "cannibalising", + "characterized", "characterised", + "characterizes", "characterises", + "circularizing", "circularising", + "collectivized", "collectivised", + "collectivizes", "collectivises", + "commercialize", "commercialise", + "computerizing", "computerising", + "conceptualize", "conceptualise", + "contextualize", "contextualise", + "criminalizing", "criminalising", + "crystallizing", "crystallising", + "decentralized", "decentralised", + "decentralizes", "decentralises", + "decriminalize", "decriminalise", + "demilitarized", "demilitarised", + "demilitarizes", "demilitarises", + "democratizing", "democratising", + "denationalize", "denationalise", + "depersonalize", "depersonalise", + "desensitizing", "desensitising", + "destabilizing", "destabilising", + "disemboweling", "disembowelling", + "dramatization", "dramatisation", + "editorialized", "editorialised", + "editorializes", "editorialises", + "extemporizing", "extemporising", + "externalizing", "externalising", + "familiarizing", "familiarising", + "fertilization", "fertilisation", + "fictionalized", "fictionalised", + "fictionalizes", "fictionalises", + "formalization", "formalisation", + "fossilization", "fossilisation", + "globalization", "globalisation", + "gynecological", "gynaecological", + "gynecologists", "gynaecologists", + "harmonization", "harmonisation", + "hematological", "haematological", + "hematologists", "haematologists", + "hospitalizing", "hospitalising", + "hypothesizing", "hypothesising", + "immortalizing", "immortalising", + "individualize", "individualise", + "industrialize", "industrialise", + "internalizing", "internalising", + "marginalizing", "marginalising", + "materializing", "materialising", + "mechanization", "mechanisation", + "memorializing", "memorialising", + "miniaturizing", "miniaturising", + "nationalizing", "nationalising", + "neighborhoods", "neighbourhoods", + "normalization", "normalisation", + "organizations", "organisations", + "outmaneuvered", "outmanoeuvred", + "overemphasize", "overemphasise", + "particularize", "particularise", + "passivization", "passivisation", + "patronizingly", "patronisingly", + "pedestrianize", "pedestrianise", + "pediatricians", "paediatricians", + "personalizing", "personalising", + "philosophized", "philosophised", + "philosophizes", "philosophises", + "privatization", "privatisation", + "propagandized", "propagandised", + "propagandizes", "propagandises", + "proselytizers", "proselytisers", + "proselytizing", "proselytising", + "psychoanalyze", "psychoanalyse", + "pulverization", "pulverisation", + "rationalizing", "rationalising", + "reconnoitered", "reconnoitred", + "revolutionize", "revolutionise", + "romanticizing", "romanticising", + "serialization", "serialisation", + "socialization", "socialisation", + "standardizing", "standardising", + "sterilization", "sterilisation", + "subsidization", "subsidisation", + "synchronizing", "synchronising", + "systematizing", "systematising", + "tantalizingly", "tantalisingly", + "underutilized", "underutilised", + "victimization", "victimisation", + "visualization", "visualisation", + "vocalizations", "vocalisations", + "vulgarization", "vulgarisation", + "accessorized", "accessorised", + "accessorizes", "accessorises", + "acclimatized", "acclimatised", + "acclimatizes", "acclimatises", + "amortization", "amortisation", + "amphitheater", "amphitheatre", + "anesthetists", "anaesthetists", + "anesthetized", "anaesthetised", + "anesthetizes", "anaesthetises", + "antagonizing", "antagonising", + "appetizingly", "appetisingly", + "archeologist", "archaeologist", + "backpedaling", "backpedalling", + "bastardizing", "bastardising", + "behaviorists", "behaviourists", + "bowdlerizing", "bowdlerising", + "breathalyzed", "breathalysed", + "breathalyzes", "breathalyses", + "cannibalized", "cannibalised", + "cannibalizes", "cannibalises", + "capitalizing", "capitalising", + "caramelizing", "caramelising", + "categorizing", "categorising", + "centerpieces", "centrepieces", + "centralizing", "centralising", + "characterize", "characterise", + "circularized", "circularised", + "circularizes", "circularises", + "clarinetists", "clarinettists", + "collectivize", "collectivise", + "colonization", "colonisation", + "computerized", "computerised", + "computerizes", "computerises", + "criminalized", "criminalised", + "criminalizes", "criminalises", + "crystallized", "crystallised", + "crystallizes", "crystallises", + "decentralize", "decentralise", + "dehumanizing", "dehumanising", + "demilitarize", "demilitarise", + "demobilizing", "demobilising", + "democratized", "democratised", + "democratizes", "democratises", + "demoralizing", "demoralising", + "desensitized", "desensitised", + "desensitizes", "desensitises", + "destabilized", "destabilised", + "destabilizes", "destabilises", + "disemboweled", "disembowelled", + "dishonorable", "dishonourable", + "dishonorably", "dishonourably", + "disorganized", "disorganised", + "editorialize", "editorialise", + "equalization", "equalisation", + "evangelizing", "evangelising", + "extemporized", "extemporised", + "extemporizes", "extemporises", + "externalized", "externalised", + "externalizes", "externalises", + "familiarized", "familiarised", + "familiarizes", "familiarises", + "fictionalize", "fictionalise", + "finalization", "finalisation", + "fraternizing", "fraternising", + "generalizing", "generalising", + "gynecologist", "gynaecologist", + "hematologist", "haematologist", + "hemophiliacs", "haemophiliacs", + "hemorrhaging", "haemorrhaging", + "homogenizing", "homogenising", + "hospitalized", "hospitalised", + "hospitalizes", "hospitalises", + "hypothesized", "hypothesised", + "hypothesizes", "hypothesises", + "idealization", "idealisation", + "immobilizers", "immobilisers", + "immobilizing", "immobilising", + "immortalized", "immortalised", + "immortalizes", "immortalises", + "immunization", "immunisation", + "initializing", "initialising", + "installments", "instalments", + "internalized", "internalised", + "internalizes", "internalises", + "jeopardizing", "jeopardising", + "legalization", "legalisation", + "legitimizing", "legitimising", + "liberalizing", "liberalising", + "maneuverable", "manoeuvrable", + "maneuverings", "manoeuvrings", + "marginalized", "marginalised", + "marginalizes", "marginalises", + "materialized", "materialised", + "materializes", "materialises", + "maximization", "maximisation", + "memorialized", "memorialised", + "memorializes", "memorialises", + "metabolizing", "metabolising", + "militarizing", "militarising", + "miniaturized", "miniaturised", + "miniaturizes", "miniaturises", + "miscataloged", "miscatalogued", + "misdemeanors", "misdemeanours", + "mobilization", "mobilisation", + "moisturizers", "moisturisers", + "moisturizing", "moisturising", + "monopolizing", "monopolising", + "multicolored", "multicoloured", + "nationalized", "nationalised", + "nationalizes", "nationalises", + "naturalizing", "naturalising", + "neighborhood", "neighbourhood", + "neutralizing", "neutralising", + "organization", "organisation", + "outmaneuvers", "outmanoeuvres", + "paleontology", "palaeontology", + "pasteurizing", "pasteurising", + "pediatrician", "paediatrician", + "personalized", "personalised", + "personalizes", "personalises", + "philosophize", "philosophise", + "plagiarizing", "plagiarising", + "polarization", "polarisation", + "politicizing", "politicising", + "popularizing", "popularising", + "pressurizing", "pressurising", + "prioritizing", "prioritising", + "propagandize", "propagandise", + "proselytized", "proselytised", + "proselytizer", "proselytiser", + "proselytizes", "proselytises", + "radicalizing", "radicalising", + "rationalized", "rationalised", + "rationalizes", "rationalises", + "realizations", "realisations", + "recognizable", "recognisable", + "recognizably", "recognisably", + "recognizance", "recognisance", + "reconnoiters", "reconnoitres", + "regularizing", "regularising", + "reorganizing", "reorganising", + "revitalizing", "revitalising", + "rhapsodizing", "rhapsodising", + "romanticized", "romanticised", + "romanticizes", "romanticises", + "scandalizing", "scandalising", + "scrutinizing", "scrutinising", + "secularizing", "secularising", + "standardized", "standardised", + "standardizes", "standardises", + "stigmatizing", "stigmatising", + "sympathizers", "sympathisers", + "sympathizing", "sympathising", + "synchronized", "synchronised", + "synchronizes", "synchronises", + "synthesizing", "synthesising", + "systematized", "systematised", + "systematizes", "systematises", + "theatergoers", "theatregoers", + "traumatizing", "traumatising", + "trivializing", "trivialising", + "unauthorized", "unauthorised", + "unionization", "unionisation", + "unrecognized", "unrecognised", + "urbanization", "urbanisation", + "vaporization", "vaporisation", + "vocalization", "vocalisation", + "westernizing", "westernising", + "accessorize", "accessorise", + "acclimatize", "acclimatise", + "agonizingly", "agonisingly", + "amortizable", "amortisable", + "anesthetics", "anaesthetics", + "anesthetist", "anaesthetist", + "anesthetize", "anaesthetise", + "anglicizing", "anglicising", + "antagonized", "antagonised", + "antagonizes", "antagonises", + "apologizing", "apologising", + "backpedaled", "backpedalled", + "bastardized", "bastardised", + "bastardizes", "bastardises", + "behaviorism", "behaviourism", + "behaviorist", "behaviourist", + "bowdlerized", "bowdlerised", + "bowdlerizes", "bowdlerises", + "brutalizing", "brutalising", + "cannibalize", "cannibalise", + "capitalized", "capitalised", + "capitalizes", "capitalises", + "caramelized", "caramelised", + "caramelizes", "caramelises", + "carbonizing", "carbonising", + "categorized", "categorised", + "categorizes", "categorises", + "cauterizing", "cauterising", + "centerfolds", "centrefolds", + "centerpiece", "centrepiece", + "centiliters", "centilitres", + "centimeters", "centimetres", + "centralized", "centralised", + "centralizes", "centralises", + "circularize", "circularise", + "clarinetist", "clarinettist", + "computerize", "computerise", + "criminalize", "criminalise", + "criticizing", "criticising", + "crystallize", "crystallise", + "customizing", "customising", + "defenseless", "defenceless", + "dehumanized", "dehumanised", + "dehumanizes", "dehumanises", + "demobilized", "demobilised", + "demobilizes", "demobilises", + "democratize", "democratise", + "demoralized", "demoralised", + "demoralizes", "demoralises", + "deodorizing", "deodorising", + "desensitize", "desensitise", + "destabilize", "destabilise", + "discoloring", "discolouring", + "dishonoring", "dishonouring", + "dramatizing", "dramatising", + "economizing", "economising", + "empathizing", "empathising", + "emphasizing", "emphasising", + "endeavoring", "endeavouring", + "epitomizing", "epitomising", + "esophaguses", "oesophaguses", + "evangelized", "evangelised", + "evangelizes", "evangelises", + "extemporize", "extemporise", + "externalize", "externalise", + "factorizing", "factorising", + "familiarize", "familiarise", + "fantasizing", "fantasising", + "fertilizers", "fertilisers", + "fertilizing", "fertilising", + "formalizing", "formalising", + "fossilizing", "fossilising", + "fraternized", "fraternised", + "fraternizes", "fraternises", + "fulfillment", "fulfilment", + "galvanizing", "galvanising", + "generalized", "generalised", + "generalizes", "generalises", + "ghettoizing", "ghettoising", + "globalizing", "globalising", + "harmonizing", "harmonising", + "hemophiliac", "haemophiliac", + "hemorrhaged", "haemorrhaged", + "hemorrhages", "haemorrhages", + "hemorrhoids", "haemorrhoids", + "homogenized", "homogenised", + "homogenizes", "homogenises", + "hospitalize", "hospitalise", + "hybridizing", "hybridising", + "hypnotizing", "hypnotising", + "hypothesize", "hypothesise", + "immobilized", "immobilised", + "immobilizer", "immobiliser", + "immobilizes", "immobilises", + "immortalize", "immortalise", + "initialized", "initialised", + "initializes", "initialises", + "installment", "instalment", + "internalize", "internalise", + "italicizing", "italicising", + "jeopardized", "jeopardised", + "jeopardizes", "jeopardises", + "legitimized", "legitimised", + "legitimizes", "legitimises", + "liberalized", "liberalised", + "liberalizes", "liberalises", + "lionization", "lionisation", + "liquidizers", "liquidisers", + "liquidizing", "liquidising", + "magnetizing", "magnetising", + "maneuvering", "manoeuvring", + "marginalize", "marginalise", + "marvelously", "marvellously", + "materialize", "materialise", + "mechanizing", "mechanising", + "memorialize", "memorialise", + "mesmerizing", "mesmerising", + "metabolized", "metabolised", + "metabolizes", "metabolises", + "militarized", "militarised", + "militarizes", "militarises", + "milliliters", "millilitres", + "millimeters", "millimetres", + "miniaturize", "miniaturise", + "misbehavior", "misbehaviour", + "misdemeanor", "misdemeanour", + "modernizing", "modernising", + "moisturized", "moisturised", + "moisturizer", "moisturiser", + "moisturizes", "moisturises", + "monopolized", "monopolised", + "monopolizes", "monopolises", + "nationalize", "nationalise", + "naturalized", "naturalised", + "naturalizes", "naturalises", + "neighboring", "neighbouring", + "neutralized", "neutralised", + "neutralizes", "neutralises", + "normalizing", "normalising", + "orthopedics", "orthopaedics", + "ostracizing", "ostracising", + "outmaneuver", "outmanoeuvre", + "oxidization", "oxidisation", + "pasteurized", "pasteurised", + "pasteurizes", "pasteurises", + "patronizing", "patronising", + "personalize", "personalise", + "plagiarized", "plagiarised", + "plagiarizes", "plagiarises", + "politicized", "politicised", + "politicizes", "politicises", + "popularized", "popularised", + "popularizes", "popularises", + "pressurized", "pressurised", + "pressurizes", "pressurises", + "prioritized", "prioritised", + "prioritizes", "prioritises", + "privatizing", "privatising", + "proselytize", "proselytise", + "publicizing", "publicising", + "pulverizing", "pulverising", + "radicalized", "radicalised", + "radicalizes", "radicalises", + "randomizing", "randomising", + "rationalize", "rationalise", + "realization", "realisation", + "recognizing", "recognising", + "reconnoiter", "reconnoitre", + "regularized", "regularised", + "regularizes", "regularises", + "reorganized", "reorganised", + "reorganizes", "reorganises", + "revitalized", "revitalised", + "revitalizes", "revitalises", + "rhapsodized", "rhapsodised", + "rhapsodizes", "rhapsodises", + "romanticize", "romanticise", + "scandalized", "scandalised", + "scandalizes", "scandalises", + "scrutinized", "scrutinised", + "scrutinizes", "scrutinises", + "secularized", "secularised", + "secularizes", "secularises", + "sensitizing", "sensitising", + "serializing", "serialising", + "sermonizing", "sermonising", + "signalizing", "signalising", + "skeptically", "sceptically", + "socializing", "socialising", + "solemnizing", "solemnising", + "specialized", "specialised", + "specializes", "specialises", + "squirreling", "squirrelling", + "stabilizers", "stabilisers", + "stabilizing", "stabilising", + "standardize", "standardise", + "sterilizers", "sterilisers", + "sterilizing", "sterilising", + "stigmatized", "stigmatised", + "stigmatizes", "stigmatises", + "subsidizers", "subsidisers", + "subsidizing", "subsidising", + "summarizing", "summarising", + "symbolizing", "symbolising", + "sympathized", "sympathised", + "sympathizer", "sympathiser", + "sympathizes", "sympathises", + "synchronize", "synchronise", + "synthesized", "synthesised", + "synthesizes", "synthesises", + "systematize", "systematise", + "tantalizing", "tantalising", + "temporizing", "temporising", + "tenderizing", "tenderising", + "terrorizing", "terrorising", + "theatergoer", "theatregoer", + "traumatized", "traumatised", + "traumatizes", "traumatises", + "trivialized", "trivialised", + "trivializes", "trivialises", + "tyrannizing", "tyrannising", + "uncataloged", "uncatalogued", + "uncivilized", "uncivilised", + "unfavorable", "unfavourable", + "unfavorably", "unfavourably", + "unorganized", "unorganised", + "untrammeled", "untrammelled", + "utilization", "utilisation", + "vandalizing", "vandalising", + "verbalizing", "verbalising", + "victimizing", "victimising", + "visualizing", "visualising", + "vulgarizing", "vulgarising", + "watercolors", "watercolours", + "westernized", "westernised", + "westernizes", "westernises", + "amortizing", "amortising", + "anesthesia", "anaesthesia", + "anesthetic", "anaesthetic", + "anglicized", "anglicised", + "anglicizes", "anglicises", + "annualized", "annualised", + "antagonize", "antagonise", + "apologized", "apologised", + "apologizes", "apologises", + "appetizers", "appetisers", + "appetizing", "appetising", + "archeology", "archaeology", + "authorizes", "authorises", + "bastardize", "bastardise", + "bedeviling", "bedevilling", + "behavioral", "behavioural", + "belaboring", "belabouring", + "bowdlerize", "bowdlerise", + "brutalized", "brutalised", + "brutalizes", "brutalises", + "canalizing", "canalising", + "canonizing", "canonising", + "capitalize", "capitalise", + "caramelize", "caramelise", + "carbonized", "carbonised", + "carbonizes", "carbonises", + "cataloging", "cataloguing", + "catalyzing", "catalysing", + "categorize", "categorise", + "cauterized", "cauterised", + "cauterizes", "cauterises", + "centerfold", "centrefold", + "centiliter", "centilitre", + "centimeter", "centimetre", + "centralize", "centralise", + "channeling", "channelling", + "checkbooks", "chequebooks", + "civilizing", "civilising", + "colonizers", "colonisers", + "colonizing", "colonising", + "colorfully", "colourfully", + "colorizing", "colourizing", + "councilors", "councillors", + "counselors", "counsellors", + "criticized", "criticised", + "criticizes", "criticises", + "customized", "customised", + "customizes", "customises", + "dehumanize", "dehumanise", + "demobilize", "demobilise", + "demonizing", "demonising", + "demoralize", "demoralise", + "deodorized", "deodorised", + "deodorizes", "deodorises", + "deputizing", "deputising", + "digitizing", "digitising", + "discolored", "discoloured", + "disheveled", "dishevelled", + "dishonored", "dishonoured", + "dramatized", "dramatised", + "dramatizes", "dramatises", + "economized", "economised", + "economizes", "economises", + "empathized", "empathised", + "empathizes", "empathises", + "emphasized", "emphasised", + "emphasizes", "emphasises", + "endeavored", "endeavoured", + "energizing", "energising", + "epicenters", "epicentres", + "epitomized", "epitomised", + "epitomizes", "epitomises", + "equalizers", "equalisers", + "equalizing", "equalising", + "eulogizing", "eulogising", + "evangelize", "evangelise", + "factorized", "factorised", + "factorizes", "factorises", + "fantasized", "fantasised", + "fantasizes", "fantasises", + "favoritism", "favouritism", + "feminizing", "feminising", + "fertilized", "fertilised", + "fertilizer", "fertiliser", + "fertilizes", "fertilises", + "fiberglass", "fibreglass", + "finalizing", "finalising", + "flavorings", "flavourings", + "flavorless", "flavourless", + "flavorsome", "flavoursome", + "formalized", "formalised", + "formalizes", "formalises", + "fossilized", "fossilised", + "fossilizes", "fossilises", + "fraternize", "fraternise", + "galvanized", "galvanised", + "galvanizes", "galvanises", + "generalize", "generalise", + "ghettoized", "ghettoised", + "ghettoizes", "ghettoises", + "globalized", "globalised", + "globalizes", "globalises", + "gruelingly", "gruellingly", + "gynecology", "gynaecology", + "harmonized", "harmonised", + "harmonizes", "harmonises", + "hematology", "haematology", + "hemoglobin", "haemoglobin", + "hemophilia", "haemophilia", + "hemorrhage", "haemorrhage", + "homogenize", "homogenise", + "humanizing", "humanising", + "hybridized", "hybridised", + "hybridizes", "hybridises", + "hypnotized", "hypnotised", + "hypnotizes", "hypnotises", + "idealizing", "idealising", + "immobilize", "immobilise", + "immunizing", "immunising", + "impaneling", "impanelling", + "imperiling", "imperilling", + "initialing", "initialling", + "initialize", "initialise", + "ionization", "ionisation", + "italicized", "italicised", + "italicizes", "italicises", + "jeopardize", "jeopardise", + "kilometers", "kilometres", + "lackluster", "lacklustre", + "legalizing", "legalising", + "legitimize", "legitimise", + "liberalize", "liberalise", + "liquidized", "liquidised", + "liquidizer", "liquidiser", + "liquidizes", "liquidises", + "localizing", "localising", + "magnetized", "magnetised", + "magnetizes", "magnetises", + "maneuvered", "manoeuvred", + "marshaling", "marshalling", + "maximizing", "maximising", + "mechanized", "mechanised", + "mechanizes", "mechanises", + "memorizing", "memorising", + "mesmerized", "mesmerised", + "mesmerizes", "mesmerises", + "metabolize", "metabolise", + "militarize", "militarise", + "milliliter", "millilitre", + "millimeter", "millimetre", + "minimizing", "minimising", + "mobilizing", "mobilising", + "modernized", "modernised", + "modernizes", "modernises", + "moisturize", "moisturise", + "monopolize", "monopolise", + "moralizing", "moralising", + "naturalize", "naturalise", + "neighborly", "neighbourly", + "neutralize", "neutralise", + "normalized", "normalised", + "normalizes", "normalises", + "optimizing", "optimising", + "organizers", "organisers", + "organizing", "organising", + "orthopedic", "orthopaedic", + "ostracized", "ostracised", + "ostracizes", "ostracises", + "paralyzing", "paralysing", + "pasteurize", "pasteurise", + "patronized", "patronised", + "patronizes", "patronises", + "pedophiles", "paedophiles", + "pedophilia", "paedophilia", + "penalizing", "penalising", + "plagiarize", "plagiarise", + "plowshares", "ploughshares", + "polarizing", "polarising", + "politicize", "politicise", + "popularize", "popularise", + "prioritize", "prioritise", + "privatized", "privatised", + "privatizes", "privatises", + "publicized", "publicised", + "publicizes", "publicises", + "pulverized", "pulverised", + "pulverizes", "pulverises", + "quarreling", "quarrelling", + "radicalize", "radicalise", + "randomized", "randomised", + "randomizes", "randomises", + "realizable", "realisable", + "recognized", "recognised", + "recognizes", "recognises", + "regularize", "regularise", + "remodeling", "remodelling", + "reorganize", "reorganise", + "revitalize", "revitalise", + "rhapsodize", "rhapsodise", + "ritualized", "ritualised", + "sanitizing", "sanitising", + "satirizing", "satirising", + "scandalize", "scandalise", + "scrutinize", "scrutinise", + "secularize", "secularise", + "sensitized", "sensitised", + "sensitizes", "sensitises", + "sepulchers", "sepulchres", + "serialized", "serialised", + "serializes", "serialises", + "sermonized", "sermonised", + "sermonizes", "sermonises", + "shriveling", "shrivelling", + "signalized", "signalised", + "signalizes", "signalises", + "skepticism", "scepticism", + "socialized", "socialised", + "socializes", "socialises", + "sodomizing", "sodomising", + "solemnized", "solemnised", + "solemnizes", "solemnises", + "specialize", "specialise", + "squirreled", "squirrelled", + "stabilized", "stabilised", + "stabilizer", "stabiliser", + "stabilizes", "stabilises", + "stenciling", "stencilling", + "sterilized", "sterilised", + "sterilizer", "steriliser", + "sterilizes", "sterilises", + "stigmatize", "stigmatise", + "subsidized", "subsidised", + "subsidizer", "subsidiser", + "subsidizes", "subsidises", + "summarized", "summarised", + "summarizes", "summarises", + "symbolized", "symbolised", + "symbolizes", "symbolises", + "sympathize", "sympathise", + "tantalized", "tantalised", + "tantalizes", "tantalises", + "temporized", "temporised", + "temporizes", "temporises", + "tenderized", "tenderised", + "tenderizes", "tenderises", + "terrorized", "terrorised", + "terrorizes", "terrorises", + "theorizing", "theorising", + "traumatize", "traumatise", + "trivialize", "trivialise", + "tyrannized", "tyrannised", + "tyrannizes", "tyrannises", + "unionizing", "unionising", + "unraveling", "unravelling", + "urbanizing", "urbanising", + "utilizable", "utilisable", + "vandalized", "vandalised", + "vandalizes", "vandalises", + "vaporizing", "vaporising", + "verbalized", "verbalised", + "verbalizes", "verbalises", + "victimized", "victimised", + "victimizes", "victimises", + "visualized", "visualised", + "visualizes", "visualises", + "vocalizing", "vocalising", + "vulcanized", "vulcanised", + "vulgarized", "vulgarised", + "vulgarizes", "vulgarises", + "watercolor", "watercolour", + "westernize", "westernise", + "womanizers", "womanisers", + "womanizing", "womanising", + "worshiping", "worshipping", + "agonizing", "agonising", + "airplanes", "aeroplanes", + "amortized", "amortised", + "amortizes", "amortises", + "analyzing", "analysing", + "apologize", "apologise", + "appetizer", "appetiser", + "artifacts", "artefacts", + "baptizing", "baptising", + "bedeviled", "bedevilled", + "behaviors", "behaviours", + "bejeweled", "bejewelled", + "belabored", "belaboured", + "brutalize", "brutalise", + "canalized", "canalised", + "canalizes", "canalises", + "canonized", "canonised", + "canonizes", "canonises", + "carbonize", "carbonise", + "cataloged", "catalogued", + "catalyzed", "catalysed", + "catalyzes", "catalyses", + "cauterize", "cauterise", + "channeled", "channelled", + "checkbook", "chequebook", + "checkered", "chequered", + "chiseling", "chiselling", + "civilized", "civilised", + "civilizes", "civilises", + "clamoring", "clamouring", + "colonized", "colonised", + "colonizer", "coloniser", + "colonizes", "colonises", + "colorants", "colourants", + "colorized", "colourized", + "colorizes", "colourizes", + "colorless", "colourless", + "councilor", "councillor", + "counseled", "counselled", + "counselor", "counsellor", + "criticize", "criticise", + "cudgeling", "cudgelling", + "customize", "customise", + "demonized", "demonised", + "demonizes", "demonises", + "deodorize", "deodorise", + "deputized", "deputised", + "deputizes", "deputises", + "digitized", "digitised", + "digitizes", "digitises", + "discolors", "discolours", + "dishonors", "dishonours", + "dramatize", "dramatise", + "driveling", "drivelling", + "economize", "economise", + "empathize", "empathise", + "emphasize", "emphasise", + "enameling", "enamelling", + "endeavors", "endeavours", + "energized", "energised", + "energizes", "energises", + "enthralls", "enthrals", + "epicenter", "epicentre", + "epitomize", "epitomise", + "equalized", "equalised", + "equalizer", "equaliser", + "equalizes", "equalises", + "eulogized", "eulogised", + "eulogizes", "eulogises", + "factorize", "factorise", + "fantasize", "fantasise", + "favorable", "favourable", + "favorably", "favourably", + "favorites", "favourites", + "feminized", "feminised", + "feminizes", "feminises", + "fertilize", "fertilise", + "finalized", "finalised", + "finalizes", "finalises", + "flavoring", "flavouring", + "formalize", "formalise", + "fossilize", "fossilise", + "funneling", "funnelling", + "galvanize", "galvanise", + "gamboling", "gambolling", + "ghettoize", "ghettoise", + "globalize", "globalise", + "gonorrhea", "gonorrhoea", + "groveling", "grovelling", + "harboring", "harbouring", + "harmonize", "harmonise", + "honorably", "honourably", + "humanized", "humanised", + "humanizes", "humanises", + "hybridize", "hybridise", + "hypnotize", "hypnotise", + "idealized", "idealised", + "idealizes", "idealises", + "idolizing", "idolising", + "immunized", "immunised", + "immunizes", "immunises", + "impaneled", "impanelled", + "imperiled", "imperilled", + "initialed", "initialled", + "italicize", "italicise", + "itemizing", "itemising", + "kilometer", "kilometre", + "legalized", "legalised", + "legalizes", "legalises", + "lionizing", "lionising", + "liquidize", "liquidise", + "localized", "localised", + "localizes", "localises", + "magnetize", "magnetise", + "maneuvers", "manoeuvres", + "marshaled", "marshalled", + "marveling", "marvelling", + "marvelous", "marvellous", + "maximized", "maximised", + "maximizes", "maximises", + "mechanize", "mechanise", + "memorized", "memorised", + "memorizes", "memorises", + "mesmerize", "mesmerise", + "minimized", "minimised", + "minimizes", "minimises", + "mobilized", "mobilised", + "mobilizes", "mobilises", + "modernize", "modernise", + "moldering", "mouldering", + "moralized", "moralised", + "moralizes", "moralises", + "motorized", "motorised", + "mustached", "moustached", + "mustaches", "moustaches", + "neighbors", "neighbours", + "normalize", "normalise", + "optimized", "optimised", + "optimizes", "optimises", + "organized", "organised", + "organizer", "organiser", + "organizes", "organises", + "ostracize", "ostracise", + "oxidizing", "oxidising", + "panelists", "panellists", + "paralyzed", "paralysed", + "paralyzes", "paralyses", + "parceling", "parcelling", + "patronize", "patronise", + "pedophile", "paedophile", + "penalized", "penalised", + "penalizes", "penalises", + "penciling", "pencilling", + "plowshare", "ploughshare", + "polarized", "polarised", + "polarizes", "polarises", + "practiced", "practised", + "pretenses", "pretences", + "privatize", "privatise", + "publicize", "publicise", + "pulverize", "pulverise", + "quarreled", "quarrelled", + "randomize", "randomise", + "realizing", "realising", + "recognize", "recognise", + "refueling", "refuelling", + "remodeled", "remodelled", + "remolding", "remoulding", + "saltpeter", "saltpetre", + "sanitized", "sanitised", + "sanitizes", "sanitises", + "satirized", "satirised", + "satirizes", "satirises", + "sensitize", "sensitise", + "sepulcher", "sepulchre", + "serialize", "serialise", + "sermonize", "sermonise", + "shoveling", "shovelling", + "shriveled", "shrivelled", + "signaling", "signalling", + "signalize", "signalise", + "skeptical", "sceptical", + "sniveling", "snivelling", + "snorkeled", "snorkelled", + "socialize", "socialise", + "sodomized", "sodomised", + "sodomizes", "sodomises", + "solemnize", "solemnise", + "spiraling", "spiralling", + "splendors", "splendours", + "stabilize", "stabilise", + "stenciled", "stencilled", + "sterilize", "sterilise", + "subsidize", "subsidise", + "succoring", "succouring", + "sulfurous", "sulphurous", + "summarize", "summarise", + "swiveling", "swivelling", + "symbolize", "symbolise", + "tantalize", "tantalise", + "temporize", "temporise", + "tenderize", "tenderise", + "terrorize", "terrorise", + "theorized", "theorised", + "theorizes", "theorises", + "travelers", "travellers", + "traveling", "travelling", + "tricolors", "tricolours", + "tunneling", "tunnelling", + "tyrannize", "tyrannise", + "unequaled", "unequalled", + "unionized", "unionised", + "unionizes", "unionises", + "unraveled", "unravelled", + "unrivaled", "unrivalled", + "urbanized", "urbanised", + "urbanizes", "urbanises", + "utilizing", "utilising", + "vandalize", "vandalise", + "vaporized", "vaporised", + "vaporizes", "vaporises", + "verbalize", "verbalise", + "victimize", "victimise", + "visualize", "visualise", + "vocalized", "vocalised", + "vocalizes", "vocalises", + "vulgarize", "vulgarise", + "weaseling", "weaselling", + "womanized", "womanised", + "womanizer", "womaniser", + "womanizes", "womanises", + "worshiped", "worshipped", + "worshiper", "worshipper", + "agonized", "agonised", + "agonizes", "agonises", + "airplane", "aeroplane", + "aluminum", "aluminium", + "amortize", "amortise", + "analyzed", "analysed", + "analyzes", "analyses", + "armorers", "armourers", + "armories", "armouries", + "artifact", "artefact", + "baptized", "baptised", + "baptizes", "baptises", + "behavior", "behaviour", + "behooved", "behoved", + "behooves", "behoves", + "belabors", "belabours", + "calibers", "calibres", + "canalize", "canalise", + "canonize", "canonise", + "catalogs", "catalogues", + "catalyze", "catalyse", + "caviling", "cavilling", + "centered", "centred", + "chiseled", "chiselled", + "civilize", "civilise", + "clamored", "clamoured", + "colonize", "colonise", + "colorant", "colourant", + "coloreds", "coloureds", + "colorful", "colourful", + "coloring", "colouring", + "colorize", "colourize", + "coziness", "cosiness", + "cruelest", "cruellest", + "cudgeled", "cudgelled", + "defenses", "defences", + "demeanor", "demeanour", + "demonize", "demonise", + "deputize", "deputise", + "diarrhea", "diarrhoea", + "digitize", "digitise", + "disfavor", "disfavour", + "dishonor", "dishonour", + "distills", "distils", + "driveled", "drivelled", + "enameled", "enamelled", + "enamored", "enamoured", + "endeavor", "endeavour", + "energize", "energise", + "epaulets", "epaulettes", + "equalize", "equalise", + "estrogen", "oestrogen", + "etiology", "aetiology", + "eulogize", "eulogise", + "favoring", "favouring", + "favorite", "favourite", + "feminize", "feminise", + "finalize", "finalise", + "flavored", "flavoured", + "flutists", "flautists", + "fulfills", "fulfils", + "funneled", "funnelled", + "gamboled", "gambolled", + "graveled", "gravelled", + "groveled", "grovelled", + "grueling", "gruelling", + "harbored", "harboured", + "honoring", "honouring", + "humanize", "humanise", + "humoring", "humouring", + "idealize", "idealise", + "idolized", "idolised", + "idolizes", "idolises", + "immunize", "immunise", + "ionizing", "ionising", + "itemized", "itemised", + "itemizes", "itemises", + "jewelers", "jewellers", + "labeling", "labelling", + "laborers", "labourers", + "laboring", "labouring", + "legalize", "legalise", + "leukemia", "leukaemia", + "levelers", "levellers", + "leveling", "levelling", + "libeling", "libelling", + "libelous", "libellous", + "lionized", "lionised", + "lionizes", "lionises", + "localize", "localise", + "louvered", "louvred", + "maneuver", "manoeuvre", + "marveled", "marvelled", + "maximize", "maximise", + "memorize", "memorise", + "minimize", "minimise", + "mobilize", "mobilise", + "modelers", "modellers", + "modeling", "modelling", + "moldered", "mouldered", + "moldiest", "mouldiest", + "moldings", "mouldings", + "moralize", "moralise", + "mustache", "moustache", + "neighbor", "neighbour", + "odorless", "odourless", + "offenses", "offences", + "optimize", "optimise", + "organize", "organise", + "oxidized", "oxidised", + "oxidizes", "oxidises", + "paneling", "panelling", + "panelist", "panellist", + "paralyze", "paralyse", + "parceled", "parcelled", + "pedaling", "pedalling", + "penalize", "penalise", + "penciled", "pencilled", + "polarize", "polarise", + "pretense", "pretence", + "pummeled", "pummelling", + "raveling", "ravelling", + "realized", "realised", + "realizes", "realises", + "refueled", "refuelled", + "remolded", "remoulded", + "revelers", "revellers", + "reveling", "revelling", + "rivaling", "rivalling", + "sanitize", "sanitise", + "satirize", "satirise", + "savories", "savouries", + "savoring", "savouring", + "scepters", "sceptres", + "shoveled", "shovelled", + "signaled", "signalled", + "skeptics", "sceptics", + "sniveled", "snivelled", + "sodomize", "sodomise", + "specters", "spectres", + "spiraled", "spiralled", + "splendor", "splendour", + "succored", "succoured", + "sulfates", "sulphates", + "sulfides", "sulphides", + "swiveled", "swivelled", + "tasseled", "tasselled", + "theaters", "theatres", + "theorize", "theorise", + "toweling", "towelling", + "traveler", "traveller", + "trialing", "trialling", + "tricolor", "tricolour", + "tunneled", "tunnelled", + "unionize", "unionise", + "unsavory", "unsavoury", + "urbanize", "urbanise", + "utilized", "utilised", + "utilizes", "utilises", + "vaporize", "vaporise", + "vocalize", "vocalise", + "weaseled", "weaselled", + "womanize", "womanise", + "yodeling", "yodelling", + "agonize", "agonise", + "analyze", "analyse", + "appalls", "appals", + "armored", "armoured", + "armorer", "armourer", + "baptize", "baptise", + "behoove", "behove", + "belabor", "belabour", + "beveled", "bevelled", + "caliber", "calibre", + "caroled", "carolled", + "caviled", "cavilled", + "centers", "centres", + "clamors", "clamours", + "clangor", "clangour", + "colored", "coloured", + "coziest", "cosiest", + "crueler", "crueller", + "defense", "defence", + "dialing", "dialling", + "dialogs", "dialogues", + "distill", "distil", + "dueling", "duelling", + "enrolls", "enrols", + "epaulet", "epaulette", + "favored", "favoured", + "flavors", "flavours", + "flutist", "flautist", + "fueling", "fuelling", + "fulfill", "fulfil", + "goiters", "goitres", + "harbors", "harbours", + "honored", "honoured", + "humored", "humoured", + "idolize", "idolise", + "ionized", "ionised", + "ionizes", "ionises", + "itemize", "itemise", + "jeweled", "jewelled", + "jeweler", "jeweller", + "jewelry", "jewellery", + "labeled", "labelled", + "labored", "laboured", + "laborer", "labourer", + "leveled", "levelled", + "leveler", "leveller", + "libeled", "libelled", + "lionize", "lionise", + "louvers", "louvres", + "modeled", "modelled", + "modeler", "modeller", + "molders", "moulders", + "moldier", "mouldier", + "molding", "moulding", + "molting", "moulting", + "offense", "offence", + "oxidize", "oxidise", + "pajamas", "pyjamas", + "paneled", "panelled", + "parlors", "parlours", + "pedaled", "pedalled", + "plowing", "ploughing", + "plowman", "ploughman", + "plowmen", "ploughmen", + "realize", "realise", + "remolds", "remoulds", + "reveled", "revelled", + "reveler", "reveller", + "rivaled", "rivalled", + "rumored", "rumoured", + "saviors", "saviours", + "savored", "savoured", + "scepter", "sceptre", + "skeptic", "sceptic", + "specter", "spectre", + "succors", "succours", + "sulfate", "sulphate", + "sulfide", "sulphide", + "theater", "theatre", + "toweled", "towelled", + "toxemia", "toxaemia", + "trialed", "trialled", + "utilize", "utilise", + "yodeled", "yodelled", + "anemia", "anaemia", + "anemic", "anaemic", + "appall", "appal", + "arbors", "arbours", + "armory", "armoury", + "candor", "candour", + "center", "centre", + "clamor", "clamour", + "colors", "colours", + "cozier", "cosier", + "cozies", "cosies", + "cozily", "cosily", + "dialed", "dialled", + "drafty", "draughty", + "dueled", "duelled", + "favors", "favours", + "fervor", "fervour", + "fibers", "fibres", + "flavor", "flavour", + "fueled", "fuelled", + "goiter", "goitre", + "harbor", "harbour", + "honors", "honours", + "humors", "humours", + "labors", "labours", + "liters", "litres", + "louver", "louvre", + "luster", "lustre", + "meager", "meagre", + "miters", "mitres", + "molded", "moulded", + "molder", "moulder", + "molted", "moulted", + "pajama", "pyjama", + "parlor", "parlour", + "plowed", "ploughed", + "rancor", "rancour", + "remold", "remould", + "rigors", "rigours", + "rumors", "rumours", + "savors", "savours", + "savory", "savoury", + "succor", "succour", + "tumors", "tumours", + "vapors", "vapours", + "aging", "ageing", + "arbor", "arbour", + "ardor", "ardour", + "armor", "armour", + "chili", "chilli", + "color", "colour", + "edema", "edoema", + "favor", "favour", + "fecal", "faecal", + "feces", "faeces", + "fiber", "fibre", + "honor", "honour", + "humor", "humour", + "labor", "labour", + "liter", "litre", + "miter", "mitre", + "molds", "moulds", + "moldy", "mouldy", + "molts", "moults", + "odors", "odours", + "plows", "ploughs", + "rigor", "rigour", + "rumor", "rumour", + "savor", "savour", + "valor", "valour", + "vapor", "vapour", + "vigor", "vigour", + "cozy", "cosy", + "mold", "mould", + "molt", "moult", + "odor", "odour", + "plow", "plough", +} diff --git a/vendor/github.com/golangci/misspell/words_us.go b/vendor/github.com/golangci/misspell/words_us.go new file mode 100644 index 000000000..4dee20bc7 --- /dev/null +++ b/vendor/github.com/golangci/misspell/words_us.go @@ -0,0 +1,1625 @@ +// Code generated by 'internal/gen'. DO NOT EDIT. + +package misspell + +// DictAmerican converts UK spellings to US spellings +var DictAmerican = []string{ + "institutionalisation", "institutionalization", + "internationalisation", "internationalization", + "professionalisation", "professionalization", + "compartmentalising", "compartmentalizing", + "institutionalising", "institutionalizing", + "internationalising", "internationalizing", + "compartmentalised", "compartmentalized", + "compartmentalises", "compartmentalizes", + "decriminalisation", "decriminalization", + "denationalisation", "denationalization", + "fictionalisations", "fictionalizations", + "institutionalised", "institutionalized", + "institutionalises", "institutionalizes", + "intellectualising", "intellectualizing", + "internationalised", "internationalized", + "internationalises", "internationalizes", + "pedestrianisation", "pedestrianization", + "professionalising", "professionalizing", + "archaeologically", "archeologically", + "compartmentalise", "compartmentalize", + "decentralisation", "decentralization", + "demilitarisation", "demilitarization", + "externalisations", "externalizations", + "fictionalisation", "fictionalization", + "institutionalise", "institutionalize", + "intellectualised", "intellectualized", + "intellectualises", "intellectualizes", + "internationalise", "internationalize", + "nationalisations", "nationalizations", + "palaeontologists", "paleontologists", + "professionalised", "professionalized", + "professionalises", "professionalizes", + "rationalisations", "rationalizations", + "sensationalising", "sensationalizing", + "sentimentalising", "sentimentalizing", + "acclimatisation", "acclimatization", + "bougainvillaeas", "bougainvilleas", + "commercialising", "commercializing", + "conceptualising", "conceptualizing", + "contextualising", "contextualizing", + "crystallisation", "crystallization", + "decriminalising", "decriminalizing", + "democratisation", "democratization", + "denationalising", "denationalizing", + "depersonalising", "depersonalizing", + "desensitisation", "desensitization", + "destabilisation", "destabilization", + "disorganisation", "disorganization", + "extemporisation", "extemporization", + "externalisation", "externalization", + "familiarisation", "familiarization", + "generalisations", "generalizations", + "hospitalisation", "hospitalization", + "individualising", "individualizing", + "industrialising", "industrializing", + "intellectualise", "intellectualize", + "internalisation", "internalization", + "manoeuvrability", "maneuverability", + "marginalisation", "marginalization", + "materialisation", "materialization", + "miniaturisation", "miniaturization", + "nationalisation", "nationalization", + "neighbourliness", "neighborliness", + "overemphasising", "overemphasizing", + "palaeontologist", "paleontologist", + "particularising", "particularizing", + "pedestrianising", "pedestrianizing", + "professionalise", "professionalize", + "psychoanalysing", "psychoanalyzing", + "rationalisation", "rationalization", + "reorganisations", "reorganizations", + "revolutionising", "revolutionizing", + "sensationalised", "sensationalized", + "sensationalises", "sensationalizes", + "sentimentalised", "sentimentalized", + "sentimentalises", "sentimentalizes", + "specialisations", "specializations", + "standardisation", "standardization", + "synchronisation", "synchronization", + "systematisation", "systematization", + "aggrandisement", "aggrandizement", + "anaesthetising", "anesthetizing", + "archaeological", "archeological", + "archaeologists", "archeologists", + "bougainvillaea", "bougainvillea", + "characterising", "characterizing", + "collectivising", "collectivizing", + "commercialised", "commercialized", + "commercialises", "commercializes", + "conceptualised", "conceptualized", + "conceptualises", "conceptualizes", + "contextualised", "contextualized", + "contextualises", "contextualizes", + "decentralising", "decentralizing", + "decriminalised", "decriminalized", + "decriminalises", "decriminalizes", + "dehumanisation", "dehumanization", + "demilitarising", "demilitarizing", + "demobilisation", "demobilization", + "demoralisation", "demoralization", + "denationalised", "denationalized", + "denationalises", "denationalizes", + "depersonalised", "depersonalized", + "depersonalises", "depersonalizes", + "disembowelling", "disemboweling", + "dramatisations", "dramatizations", + "editorialising", "editorializing", + "encyclopaedias", "encyclopedias", + "fictionalising", "fictionalizing", + "fraternisation", "fraternization", + "generalisation", "generalization", + "gynaecological", "gynecological", + "gynaecologists", "gynecologists", + "haematological", "hematological", + "haematologists", "hematologists", + "immobilisation", "immobilization", + "individualised", "individualized", + "individualises", "individualizes", + "industrialised", "industrialized", + "industrialises", "industrializes", + "liberalisation", "liberalization", + "monopolisation", "monopolization", + "naturalisation", "naturalization", + "neighbourhoods", "neighborhoods", + "neutralisation", "neutralization", + "organisational", "organizational", + "outmanoeuvring", "outmaneuvering", + "overemphasised", "overemphasized", + "overemphasises", "overemphasizes", + "paediatricians", "pediatricians", + "particularised", "particularized", + "particularises", "particularizes", + "pasteurisation", "pasteurization", + "pedestrianised", "pedestrianized", + "pedestrianises", "pedestrianizes", + "philosophising", "philosophizing", + "politicisation", "politicization", + "popularisation", "popularization", + "pressurisation", "pressurization", + "prioritisation", "prioritization", + "privatisations", "privatizations", + "propagandising", "propagandizing", + "psychoanalysed", "psychoanalyzed", + "psychoanalyses", "psychoanalyzes", + "regularisation", "regularization", + "reorganisation", "reorganization", + "revolutionised", "revolutionized", + "revolutionises", "revolutionizes", + "secularisation", "secularization", + "sensationalise", "sensationalize", + "sentimentalise", "sentimentalize", + "serialisations", "serializations", + "specialisation", "specialization", + "sterilisations", "sterilizations", + "stigmatisation", "stigmatization", + "transistorised", "transistorized", + "unrecognisable", "unrecognizable", + "visualisations", "visualizations", + "westernisation", "westernization", + "accessorising", "accessorizing", + "acclimatising", "acclimatizing", + "amortisations", "amortizations", + "amphitheatres", "amphitheaters", + "anaesthetised", "anesthetized", + "anaesthetises", "anesthetizes", + "anaesthetists", "anesthetists", + "archaeologist", "archeologist", + "backpedalling", "backpedaling", + "behaviourists", "behaviorists", + "breathalysers", "breathalyzers", + "breathalysing", "breathalyzing", + "callisthenics", "calisthenics", + "cannibalising", "cannibalizing", + "characterised", "characterized", + "characterises", "characterizes", + "circularising", "circularizing", + "clarinettists", "clarinetists", + "collectivised", "collectivized", + "collectivises", "collectivizes", + "commercialise", "commercialize", + "computerising", "computerizing", + "conceptualise", "conceptualize", + "contextualise", "contextualize", + "criminalising", "criminalizing", + "crystallising", "crystallizing", + "decentralised", "decentralized", + "decentralises", "decentralizes", + "decriminalise", "decriminalize", + "demilitarised", "demilitarized", + "demilitarises", "demilitarizes", + "democratising", "democratizing", + "denationalise", "denationalize", + "depersonalise", "depersonalize", + "desensitising", "desensitizing", + "destabilising", "destabilizing", + "disembowelled", "disemboweled", + "dishonourable", "dishonorable", + "dishonourably", "dishonorably", + "dramatisation", "dramatization", + "editorialised", "editorialized", + "editorialises", "editorializes", + "encyclopaedia", "encyclopedia", + "encyclopaedic", "encyclopedic", + "extemporising", "extemporizing", + "externalising", "externalizing", + "familiarising", "familiarizing", + "fertilisation", "fertilization", + "fictionalised", "fictionalized", + "fictionalises", "fictionalizes", + "formalisation", "formalization", + "fossilisation", "fossilization", + "globalisation", "globalization", + "gynaecologist", "gynecologist", + "haematologist", "hematologist", + "haemophiliacs", "hemophiliacs", + "haemorrhaging", "hemorrhaging", + "harmonisation", "harmonization", + "hospitalising", "hospitalizing", + "hypothesising", "hypothesizing", + "immortalising", "immortalizing", + "individualise", "individualize", + "industrialise", "industrialize", + "internalising", "internalizing", + "marginalising", "marginalizing", + "materialising", "materializing", + "mechanisation", "mechanization", + "memorialising", "memorializing", + "miniaturising", "miniaturizing", + "miscatalogued", "miscataloged", + "misdemeanours", "misdemeanors", + "multicoloured", "multicolored", + "nationalising", "nationalizing", + "neighbourhood", "neighborhood", + "normalisation", "normalization", + "organisations", "organizations", + "outmanoeuvred", "outmaneuvered", + "outmanoeuvres", "outmaneuvers", + "overemphasise", "overemphasize", + "paediatrician", "pediatrician", + "palaeontology", "paleontology", + "particularise", "particularize", + "passivisation", "passivization", + "patronisingly", "patronizingly", + "pedestrianise", "pedestrianize", + "personalising", "personalizing", + "philosophised", "philosophized", + "philosophises", "philosophizes", + "privatisation", "privatization", + "propagandised", "propagandized", + "propagandises", "propagandizes", + "proselytisers", "proselytizers", + "proselytising", "proselytizing", + "psychoanalyse", "psychoanalyze", + "pulverisation", "pulverization", + "rationalising", "rationalizing", + "reconnoitring", "reconnoitering", + "revolutionise", "revolutionize", + "romanticising", "romanticizing", + "serialisation", "serialization", + "socialisation", "socialization", + "stabilisation", "stabilization", + "standardising", "standardizing", + "sterilisation", "sterilization", + "subsidisation", "subsidization", + "synchronising", "synchronizing", + "systematising", "systematizing", + "tantalisingly", "tantalizingly", + "underutilised", "underutilized", + "victimisation", "victimization", + "visualisation", "visualization", + "vocalisations", "vocalizations", + "vulgarisation", "vulgarization", + "accessorised", "accessorized", + "accessorises", "accessorizes", + "acclimatised", "acclimatized", + "acclimatises", "acclimatizes", + "amortisation", "amortization", + "amphitheatre", "amphitheater", + "anaesthetics", "anesthetics", + "anaesthetise", "anesthetize", + "anaesthetist", "anesthetist", + "antagonising", "antagonizing", + "appetisingly", "appetizingly", + "backpedalled", "backpedaled", + "bastardising", "bastardizing", + "behaviourism", "behaviorism", + "behaviourist", "behaviorist", + "bowdlerising", "bowdlerizing", + "breathalysed", "breathalyzed", + "breathalyser", "breathalyzer", + "breathalyses", "breathalyzes", + "cannibalised", "cannibalized", + "cannibalises", "cannibalizes", + "capitalising", "capitalizing", + "caramelising", "caramelizing", + "categorising", "categorizing", + "centigrammes", "centigrams", + "centralising", "centralizing", + "centrepieces", "centerpieces", + "characterise", "characterize", + "circularised", "circularized", + "circularises", "circularizes", + "clarinettist", "clarinetist", + "collectivise", "collectivize", + "colonisation", "colonization", + "computerised", "computerized", + "computerises", "computerizes", + "criminalised", "criminalized", + "criminalises", "criminalizes", + "crystallised", "crystallized", + "crystallises", "crystallizes", + "decentralise", "decentralize", + "dehumanising", "dehumanizing", + "demilitarise", "demilitarize", + "demobilising", "demobilizing", + "democratised", "democratized", + "democratises", "democratizes", + "demoralising", "demoralizing", + "desensitised", "desensitized", + "desensitises", "desensitizes", + "destabilised", "destabilized", + "destabilises", "destabilizes", + "discolouring", "discoloring", + "dishonouring", "dishonoring", + "disorganised", "disorganized", + "editorialise", "editorialize", + "endeavouring", "endeavoring", + "equalisation", "equalization", + "evangelising", "evangelizing", + "extemporised", "extemporized", + "extemporises", "extemporizes", + "externalised", "externalized", + "externalises", "externalizes", + "familiarised", "familiarized", + "familiarises", "familiarizes", + "fictionalise", "fictionalize", + "finalisation", "finalization", + "fraternising", "fraternizing", + "generalising", "generalizing", + "haemophiliac", "hemophiliac", + "haemorrhaged", "hemorrhaged", + "haemorrhages", "hemorrhages", + "haemorrhoids", "hemorrhoids", + "homoeopathic", "homeopathic", + "homogenising", "homogenizing", + "hospitalised", "hospitalized", + "hospitalises", "hospitalizes", + "hypothesised", "hypothesized", + "hypothesises", "hypothesizes", + "idealisation", "idealization", + "immobilisers", "immobilizers", + "immobilising", "immobilizing", + "immortalised", "immortalized", + "immortalises", "immortalizes", + "immunisation", "immunization", + "initialising", "initializing", + "internalised", "internalized", + "internalises", "internalizes", + "jeopardising", "jeopardizing", + "legalisation", "legalization", + "legitimising", "legitimizing", + "liberalising", "liberalizing", + "manoeuvrable", "maneuverable", + "manoeuvrings", "maneuverings", + "marginalised", "marginalized", + "marginalises", "marginalizes", + "marvellously", "marvelously", + "materialised", "materialized", + "materialises", "materializes", + "maximisation", "maximization", + "memorialised", "memorialized", + "memorialises", "memorializes", + "metabolising", "metabolizing", + "militarising", "militarizing", + "milligrammes", "milligrams", + "miniaturised", "miniaturized", + "miniaturises", "miniaturizes", + "misbehaviour", "misbehavior", + "misdemeanour", "misdemeanor", + "mobilisation", "mobilization", + "moisturisers", "moisturizers", + "moisturising", "moisturizing", + "monopolising", "monopolizing", + "moustachioed", "mustachioed", + "nationalised", "nationalized", + "nationalises", "nationalizes", + "naturalising", "naturalizing", + "neighbouring", "neighboring", + "neutralising", "neutralizing", + "oesophaguses", "esophaguses", + "organisation", "organization", + "orthopaedics", "orthopedics", + "outmanoeuvre", "outmaneuver", + "palaeolithic", "paleolithic", + "pasteurising", "pasteurizing", + "personalised", "personalized", + "personalises", "personalizes", + "philosophise", "philosophize", + "plagiarising", "plagiarizing", + "ploughshares", "plowshares", + "polarisation", "polarization", + "politicising", "politicizing", + "popularising", "popularizing", + "pressurising", "pressurizing", + "prioritising", "prioritizing", + "propagandise", "propagandize", + "proselytised", "proselytized", + "proselytiser", "proselytizer", + "proselytises", "proselytizes", + "radicalising", "radicalizing", + "rationalised", "rationalized", + "rationalises", "rationalizes", + "realisations", "realizations", + "recognisable", "recognizable", + "recognisably", "recognizably", + "recognisance", "recognizance", + "reconnoitred", "reconnoitered", + "reconnoitres", "reconnoiters", + "regularising", "regularizing", + "reorganising", "reorganizing", + "revitalising", "revitalizing", + "rhapsodising", "rhapsodizing", + "romanticised", "romanticized", + "romanticises", "romanticizes", + "scandalising", "scandalizing", + "scrutinising", "scrutinizing", + "secularising", "secularizing", + "specialising", "specializing", + "squirrelling", "squirreling", + "standardised", "standardized", + "standardises", "standardizes", + "stigmatising", "stigmatizing", + "sympathisers", "sympathizers", + "sympathising", "sympathizing", + "synchronised", "synchronized", + "synchronises", "synchronizes", + "synthesisers", "synthesizers", + "synthesising", "synthesizing", + "systematised", "systematized", + "systematises", "systematizes", + "technicolour", "technicolor", + "theatregoers", "theatergoers", + "traumatising", "traumatizing", + "trivialising", "trivializing", + "unauthorised", "unauthorized", + "uncatalogued", "uncataloged", + "unfavourable", "unfavorable", + "unfavourably", "unfavorably", + "unionisation", "unionization", + "unrecognised", "unrecognized", + "untrammelled", "untrammeled", + "urbanisation", "urbanization", + "vaporisation", "vaporization", + "vocalisation", "vocalization", + "watercolours", "watercolors", + "westernising", "westernizing", + "accessorise", "accessorize", + "acclimatise", "acclimatize", + "agonisingly", "agonizingly", + "amortisable", "amortizable", + "anaesthesia", "anesthesia", + "anaesthetic", "anesthetic", + "anglicising", "anglicizing", + "antagonised", "antagonized", + "antagonises", "antagonizes", + "apologising", "apologizing", + "archaeology", "archeology", + "authorising", "authorizing", + "bastardised", "bastardized", + "bastardises", "bastardizes", + "bedevilling", "bedeviling", + "behavioural", "behavioral", + "belabouring", "belaboring", + "bowdlerised", "bowdlerized", + "bowdlerises", "bowdlerizes", + "breathalyse", "breathalyze", + "brutalising", "brutalizing", + "cannibalise", "cannibalize", + "capitalised", "capitalized", + "capitalises", "capitalizes", + "caramelised", "caramelized", + "caramelises", "caramelizes", + "carbonising", "carbonizing", + "cataloguing", "cataloging", + "categorised", "categorized", + "categorises", "categorizes", + "cauterising", "cauterizing", + "centigramme", "centigram", + "centilitres", "centiliters", + "centimetres", "centimeters", + "centralised", "centralized", + "centralises", "centralizes", + "centrefolds", "centerfolds", + "centrepiece", "centerpiece", + "channelling", "channeling", + "chequebooks", "checkbooks", + "circularise", "circularize", + "colourfully", "colorfully", + "colourizing", "colorizing", + "computerise", "computerize", + "councillors", "councilors", + "counselling", "counseling", + "counsellors", "counselors", + "criminalise", "criminalize", + "criticising", "criticizing", + "crystallise", "crystallize", + "customising", "customizing", + "defenceless", "defenseless", + "dehumanised", "dehumanized", + "dehumanises", "dehumanizes", + "demobilised", "demobilized", + "demobilises", "demobilizes", + "democratise", "democratize", + "demoralised", "demoralized", + "demoralises", "demoralizes", + "deodorising", "deodorizing", + "desensitise", "desensitize", + "destabilise", "destabilize", + "discoloured", "discolored", + "dishevelled", "disheveled", + "dishonoured", "dishonored", + "dramatising", "dramatizing", + "economising", "economizing", + "empathising", "empathizing", + "emphasising", "emphasizing", + "endeavoured", "endeavored", + "epitomising", "epitomizing", + "evangelised", "evangelized", + "evangelises", "evangelizes", + "extemporise", "extemporize", + "externalise", "externalize", + "factorising", "factorizing", + "familiarise", "familiarize", + "fantasising", "fantasizing", + "favouritism", "favoritism", + "fertilisers", "fertilizers", + "fertilising", "fertilizing", + "flavourings", "flavorings", + "flavourless", "flavorless", + "flavoursome", "flavorsome", + "formalising", "formalizing", + "fossilising", "fossilizing", + "fraternised", "fraternized", + "fraternises", "fraternizes", + "galvanising", "galvanizing", + "generalised", "generalized", + "generalises", "generalizes", + "ghettoising", "ghettoizing", + "globalising", "globalizing", + "gruellingly", "gruelingly", + "gynaecology", "gynecology", + "haematology", "hematology", + "haemoglobin", "hemoglobin", + "haemophilia", "hemophilia", + "haemorrhage", "hemorrhage", + "harmonising", "harmonizing", + "homoeopaths", "homeopaths", + "homoeopathy", "homeopathy", + "homogenised", "homogenized", + "homogenises", "homogenizes", + "hospitalise", "hospitalize", + "hybridising", "hybridizing", + "hypnotising", "hypnotizing", + "hypothesise", "hypothesize", + "immobilised", "immobilized", + "immobiliser", "immobilizer", + "immobilises", "immobilizes", + "immortalise", "immortalize", + "impanelling", "impaneling", + "imperilling", "imperiling", + "initialised", "initialized", + "initialises", "initializes", + "initialling", "initialing", + "instalments", "installments", + "internalise", "internalize", + "italicising", "italicizing", + "jeopardised", "jeopardized", + "jeopardises", "jeopardizes", + "kilogrammes", "kilograms", + "legitimised", "legitimized", + "legitimises", "legitimizes", + "liberalised", "liberalized", + "liberalises", "liberalizes", + "lionisation", "lionization", + "liquidisers", "liquidizers", + "liquidising", "liquidizing", + "magnetising", "magnetizing", + "manoeuvring", "maneuvering", + "marginalise", "marginalize", + "marshalling", "marshaling", + "materialise", "materialize", + "mechanising", "mechanizing", + "memorialise", "memorialize", + "mesmerising", "mesmerizing", + "metabolised", "metabolized", + "metabolises", "metabolizes", + "micrometres", "micrometers", + "militarised", "militarized", + "militarises", "militarizes", + "milligramme", "milligram", + "millilitres", "milliliters", + "millimetres", "millimeters", + "miniaturise", "miniaturize", + "modernising", "modernizing", + "moisturised", "moisturized", + "moisturiser", "moisturizer", + "moisturises", "moisturizes", + "monopolised", "monopolized", + "monopolises", "monopolizes", + "nationalise", "nationalize", + "naturalised", "naturalized", + "naturalises", "naturalizes", + "neighbourly", "neighborly", + "neutralised", "neutralized", + "neutralises", "neutralizes", + "normalising", "normalizing", + "orthopaedic", "orthopedic", + "ostracising", "ostracizing", + "oxidisation", "oxidization", + "paediatrics", "pediatrics", + "paedophiles", "pedophiles", + "paedophilia", "pedophilia", + "passivising", "passivizing", + "pasteurised", "pasteurized", + "pasteurises", "pasteurizes", + "patronising", "patronizing", + "personalise", "personalize", + "plagiarised", "plagiarized", + "plagiarises", "plagiarizes", + "ploughshare", "plowshare", + "politicised", "politicized", + "politicises", "politicizes", + "popularised", "popularized", + "popularises", "popularizes", + "praesidiums", "presidiums", + "pressurised", "pressurized", + "pressurises", "pressurizes", + "prioritised", "prioritized", + "prioritises", "prioritizes", + "privatising", "privatizing", + "proselytise", "proselytize", + "publicising", "publicizing", + "pulverising", "pulverizing", + "quarrelling", "quarreling", + "radicalised", "radicalized", + "radicalises", "radicalizes", + "randomising", "randomizing", + "rationalise", "rationalize", + "realisation", "realization", + "recognising", "recognizing", + "reconnoitre", "reconnoiter", + "regularised", "regularized", + "regularises", "regularizes", + "remodelling", "remodeling", + "reorganised", "reorganized", + "reorganises", "reorganizes", + "revitalised", "revitalized", + "revitalises", "revitalizes", + "rhapsodised", "rhapsodized", + "rhapsodises", "rhapsodizes", + "romanticise", "romanticize", + "scandalised", "scandalized", + "scandalises", "scandalizes", + "sceptically", "skeptically", + "scrutinised", "scrutinized", + "scrutinises", "scrutinizes", + "secularised", "secularized", + "secularises", "secularizes", + "sensitising", "sensitizing", + "serialising", "serializing", + "sermonising", "sermonizing", + "shrivelling", "shriveling", + "signalising", "signalizing", + "snorkelling", "snorkeling", + "snowploughs", "snowplow", + "socialising", "socializing", + "solemnising", "solemnizing", + "specialised", "specialized", + "specialises", "specializes", + "squirrelled", "squirreled", + "stabilisers", "stabilizers", + "stabilising", "stabilizing", + "standardise", "standardize", + "stencilling", "stenciling", + "sterilisers", "sterilizers", + "sterilising", "sterilizing", + "stigmatised", "stigmatized", + "stigmatises", "stigmatizes", + "subsidisers", "subsidizers", + "subsidising", "subsidizing", + "summarising", "summarizing", + "symbolising", "symbolizing", + "sympathised", "sympathized", + "sympathiser", "sympathizer", + "sympathises", "sympathizes", + "synchronise", "synchronize", + "synthesised", "synthesized", + "synthesiser", "synthesizer", + "synthesises", "synthesizes", + "systematise", "systematize", + "tantalising", "tantalizing", + "temporising", "temporizing", + "tenderising", "tenderizing", + "terrorising", "terrorizing", + "theatregoer", "theatergoer", + "traumatised", "traumatized", + "traumatises", "traumatizes", + "trivialised", "trivialized", + "trivialises", "trivializes", + "tyrannising", "tyrannizing", + "uncivilised", "uncivilized", + "unorganised", "unorganized", + "unravelling", "unraveling", + "utilisation", "utilization", + "vandalising", "vandalizing", + "verbalising", "verbalizing", + "victimising", "victimizing", + "visualising", "visualizing", + "vulgarising", "vulgarizing", + "watercolour", "watercolor", + "westernised", "westernized", + "westernises", "westernizes", + "worshipping", "worshiping", + "aeroplanes", "airplanes", + "amortising", "amortizing", + "anglicised", "anglicized", + "anglicises", "anglicizes", + "annualised", "annualized", + "antagonise", "antagonize", + "apologised", "apologized", + "apologises", "apologizes", + "appetisers", "appetizers", + "appetising", "appetizing", + "authorised", "authorized", + "authorises", "authorizes", + "bannisters", "banisters", + "bastardise", "bastardize", + "bedevilled", "bedeviled", + "behaviours", "behaviors", + "bejewelled", "bejeweled", + "belaboured", "belabored", + "bowdlerise", "bowdlerize", + "brutalised", "brutalized", + "brutalises", "brutalizes", + "canalising", "canalizing", + "cancelling", "canceling", + "canonising", "canonizing", + "capitalise", "capitalize", + "caramelise", "caramelize", + "carbonised", "carbonized", + "carbonises", "carbonizes", + "catalogued", "cataloged", + "catalogues", "catalogs", + "catalysing", "catalyzing", + "categorise", "categorize", + "cauterised", "cauterized", + "cauterises", "cauterizes", + "centilitre", "centiliter", + "centimetre", "centimeter", + "centralise", "centralize", + "centrefold", "centerfold", + "channelled", "channeled", + "chequebook", "checkbook", + "chiselling", "chiseling", + "civilising", "civilizing", + "clamouring", "clamoring", + "colonisers", "colonizers", + "colonising", "colonizing", + "colourants", "colorants", + "colourized", "colorized", + "colourizes", "colorizes", + "colourless", "colorless", + "connexions", "connections", + "councillor", "councilor", + "counselled", "counseled", + "counsellor", "counselor", + "criticised", "criticized", + "criticises", "criticizes", + "cudgelling", "cudgeling", + "customised", "customized", + "customises", "customizes", + "dehumanise", "dehumanize", + "demobilise", "demobilize", + "demonising", "demonizing", + "demoralise", "demoralize", + "deodorised", "deodorized", + "deodorises", "deodorizes", + "deputising", "deputizing", + "digitising", "digitizing", + "discolours", "discolors", + "dishonours", "dishonors", + "dramatised", "dramatized", + "dramatises", "dramatizes", + "drivelling", "driveling", + "economised", "economized", + "economises", "economizes", + "empathised", "empathized", + "empathises", "empathizes", + "emphasised", "emphasized", + "emphasises", "emphasizes", + "enamelling", "enameling", + "endeavours", "endeavors", + "energising", "energizing", + "epaulettes", "epaulets", + "epicentres", "epicenters", + "epitomised", "epitomized", + "epitomises", "epitomizes", + "equalisers", "equalizers", + "equalising", "equalizing", + "eulogising", "eulogizing", + "evangelise", "evangelize", + "factorised", "factorized", + "factorises", "factorizes", + "fantasised", "fantasized", + "fantasises", "fantasizes", + "favourable", "favorable", + "favourably", "favorably", + "favourites", "favorites", + "feminising", "feminizing", + "fertilised", "fertilized", + "fertiliser", "fertilizer", + "fertilises", "fertilizes", + "fibreglass", "fiberglass", + "finalising", "finalizing", + "flavouring", "flavoring", + "formalised", "formalized", + "formalises", "formalizes", + "fossilised", "fossilized", + "fossilises", "fossilizes", + "fraternise", "fraternize", + "fulfilment", "fulfillment", + "funnelling", "funneling", + "galvanised", "galvanized", + "galvanises", "galvanizes", + "gambolling", "gamboling", + "gaolbreaks", "jailbreaks", + "generalise", "generalize", + "ghettoised", "ghettoized", + "ghettoises", "ghettoizes", + "globalised", "globalized", + "globalises", "globalizes", + "gonorrhoea", "gonorrhea", + "grovelling", "groveling", + "harbouring", "harboring", + "harmonised", "harmonized", + "harmonises", "harmonizes", + "homoeopath", "homeopath", + "homogenise", "homogenize", + "honourable", "honorable", + "honourably", "honorably", + "humanising", "humanizing", + "humourless", "humorless", + "hybridised", "hybridized", + "hybridises", "hybridizes", + "hypnotised", "hypnotized", + "hypnotises", "hypnotizes", + "idealising", "idealizing", + "immobilise", "immobilize", + "immunising", "immunizing", + "impanelled", "impaneled", + "imperilled", "imperiled", + "inflexions", "inflections", + "initialise", "initialize", + "initialled", "initialed", + "instalment", "installment", + "ionisation", "ionization", + "italicised", "italicized", + "italicises", "italicizes", + "jeopardise", "jeopardize", + "kilogramme", "kilogram", + "kilometres", "kilometers", + "lacklustre", "lackluster", + "legalising", "legalizing", + "legitimise", "legitimize", + "liberalise", "liberalize", + "liquidised", "liquidized", + "liquidiser", "liquidizer", + "liquidises", "liquidizes", + "localising", "localizing", + "magnetised", "magnetized", + "magnetises", "magnetizes", + "manoeuvred", "maneuvered", + "manoeuvres", "maneuvers", + "marshalled", "marshaled", + "marvelling", "marveling", + "marvellous", "marvelous", + "maximising", "maximizing", + "mechanised", "mechanized", + "mechanises", "mechanizes", + "memorising", "memorizing", + "mesmerised", "mesmerized", + "mesmerises", "mesmerizes", + "metabolise", "metabolize", + "micrometre", "micrometer", + "militarise", "militarize", + "millilitre", "milliliter", + "millimetre", "millimeter", + "minimising", "minimizing", + "mobilising", "mobilizing", + "modernised", "modernized", + "modernises", "modernizes", + "moisturise", "moisturize", + "monopolise", "monopolize", + "moralising", "moralizing", + "mouldering", "moldering", + "moustached", "mustached", + "moustaches", "mustaches", + "naturalise", "naturalize", + "neighbours", "neighbors", + "neutralise", "neutralize", + "normalised", "normalized", + "normalises", "normalizes", + "oesophagus", "esophagus", + "optimising", "optimizing", + "organisers", "organizers", + "organising", "organizing", + "ostracised", "ostracized", + "ostracises", "ostracizes", + "paederasts", "pederasts", + "paediatric", "pediatric", + "paedophile", "pedophile", + "panellists", "panelists", + "paralysing", "paralyzing", + "parcelling", "parceling", + "passivised", "passivized", + "passivises", "passivizes", + "pasteurise", "pasteurize", + "patronised", "patronized", + "patronises", "patronizes", + "penalising", "penalizing", + "pencilling", "penciling", + "plagiarise", "plagiarize", + "polarising", "polarizing", + "politicise", "politicize", + "popularise", "popularize", + "practising", "practicing", + "praesidium", "presidium", + "pressurise", "pressurize", + "prioritise", "prioritize", + "privatised", "privatized", + "privatises", "privatizes", + "programmes", "programs", + "publicised", "publicized", + "publicises", "publicizes", + "pulverised", "pulverized", + "pulverises", "pulverizes", + "pummelling", "pummeled", + "quarrelled", "quarreled", + "radicalise", "radicalize", + "randomised", "randomized", + "randomises", "randomizes", + "realisable", "realizable", + "recognised", "recognized", + "recognises", "recognizes", + "refuelling", "refueling", + "regularise", "regularize", + "remodelled", "remodeled", + "remoulding", "remolding", + "reorganise", "reorganize", + "revitalise", "revitalize", + "rhapsodise", "rhapsodize", + "ritualised", "ritualized", + "sanitising", "sanitizing", + "satirising", "satirizing", + "scandalise", "scandalize", + "scepticism", "skepticism", + "scrutinise", "scrutinize", + "secularise", "secularize", + "sensitised", "sensitized", + "sensitises", "sensitizes", + "sepulchres", "sepulchers", + "serialised", "serialized", + "serialises", "serializes", + "sermonised", "sermonized", + "sermonises", "sermonizes", + "shovelling", "shoveling", + "shrivelled", "shriveled", + "signalised", "signalized", + "signalises", "signalizes", + "signalling", "signaling", + "snivelling", "sniveling", + "snorkelled", "snorkeled", + "snowplough", "snowplow", + "socialised", "socialized", + "socialises", "socializes", + "sodomising", "sodomizing", + "solemnised", "solemnized", + "solemnises", "solemnizes", + "specialise", "specialize", + "spiralling", "spiraling", + "splendours", "splendors", + "stabilised", "stabilized", + "stabiliser", "stabilizer", + "stabilises", "stabilizes", + "stencilled", "stenciled", + "sterilised", "sterilized", + "steriliser", "sterilizer", + "sterilises", "sterilizes", + "stigmatise", "stigmatize", + "subsidised", "subsidized", + "subsidiser", "subsidizer", + "subsidises", "subsidizes", + "succouring", "succoring", + "sulphurous", "sulfurous", + "summarised", "summarized", + "summarises", "summarizes", + "swivelling", "swiveling", + "symbolised", "symbolized", + "symbolises", "symbolizes", + "sympathise", "sympathize", + "synthesise", "synthesize", + "tantalised", "tantalized", + "tantalises", "tantalizes", + "temporised", "temporized", + "temporises", "temporizes", + "tenderised", "tenderized", + "tenderises", "tenderizes", + "terrorised", "terrorized", + "terrorises", "terrorizes", + "theorising", "theorizing", + "traumatise", "traumatize", + "travellers", "travelers", + "travelling", "traveling", + "tricolours", "tricolors", + "trivialise", "trivialize", + "tunnelling", "tunneling", + "tyrannised", "tyrannized", + "tyrannises", "tyrannizes", + "unequalled", "unequaled", + "unionising", "unionizing", + "unravelled", "unraveled", + "unrivalled", "unrivaled", + "urbanising", "urbanizing", + "utilisable", "utilizable", + "vandalised", "vandalized", + "vandalises", "vandalizes", + "vaporising", "vaporizing", + "verbalised", "verbalized", + "verbalises", "verbalizes", + "victimised", "victimized", + "victimises", "victimizes", + "visualised", "visualized", + "visualises", "visualizes", + "vocalising", "vocalizing", + "vulcanised", "vulcanized", + "vulgarised", "vulgarized", + "vulgarises", "vulgarizes", + "weaselling", "weaseling", + "westernise", "westernize", + "womanisers", "womanizers", + "womanising", "womanizing", + "worshipped", "worshiped", + "worshipper", "worshiper", + "aeroplane", "airplane", + "aetiology", "etiology", + "agonising", "agonizing", + "almanacks", "almanacs", + "aluminium", "aluminum", + "amortised", "amortized", + "amortises", "amortizes", + "analogues", "analogs", + "analysing", "analyzing", + "anglicise", "anglicize", + "apologise", "apologize", + "appetiser", "appetizer", + "armourers", "armorers", + "armouries", "armories", + "artefacts", "artifacts", + "authorise", "authorize", + "baptising", "baptizing", + "behaviour", "behavior", + "belabours", "belabors", + "brutalise", "brutalize", + "callipers", "calipers", + "canalised", "canalized", + "canalises", "canalizes", + "cancelled", "canceled", + "canonised", "canonized", + "canonises", "canonizes", + "carbonise", "carbonize", + "carolling", "caroling", + "catalogue", "catalog", + "catalysed", "catalyzed", + "catalyses", "catalyzes", + "cauterise", "cauterize", + "cavilling", "caviling", + "chequered", "checkered", + "chiselled", "chiseled", + "civilised", "civilized", + "civilises", "civilizes", + "clamoured", "clamored", + "colonised", "colonized", + "coloniser", "colonizer", + "colonises", "colonizes", + "colourant", "colorant", + "coloureds", "coloreds", + "colourful", "colorful", + "colouring", "coloring", + "colourize", "colorize", + "connexion", "connection", + "criticise", "criticize", + "cruellest", "cruelest", + "cudgelled", "cudgeled", + "customise", "customize", + "demeanour", "demeanor", + "demonised", "demonized", + "demonises", "demonizes", + "deodorise", "deodorize", + "deputised", "deputized", + "deputises", "deputizes", + "dialogues", "dialogs", + "diarrhoea", "diarrhea", + "digitised", "digitized", + "digitises", "digitizes", + "discolour", "discolor", + "disfavour", "disfavor", + "dishonour", "dishonor", + "dramatise", "dramatize", + "drivelled", "driveled", + "economise", "economize", + "empathise", "empathize", + "emphasise", "emphasize", + "enamelled", "enameled", + "enamoured", "enamored", + "endeavour", "endeavor", + "energised", "energized", + "energises", "energizes", + "epaulette", "epaulet", + "epicentre", "epicenter", + "epitomise", "epitomize", + "equalised", "equalized", + "equaliser", "equalizer", + "equalises", "equalizes", + "eulogised", "eulogized", + "eulogises", "eulogizes", + "factorise", "factorize", + "fantasise", "fantasize", + "favouring", "favoring", + "favourite", "favorite", + "feminised", "feminized", + "feminises", "feminizes", + "fertilise", "fertilize", + "finalised", "finalized", + "finalises", "finalizes", + "flautists", "flutists", + "flavoured", "flavored", + "formalise", "formalize", + "fossilise", "fossilize", + "funnelled", "funneled", + "galvanise", "galvanize", + "gambolled", "gamboled", + "gaolbirds", "jailbirds", + "gaolbreak", "jailbreak", + "ghettoise", "ghettoize", + "globalise", "globalize", + "gravelled", "graveled", + "grovelled", "groveled", + "gruelling", "grueling", + "harboured", "harbored", + "harmonise", "harmonize", + "honouring", "honoring", + "humanised", "humanized", + "humanises", "humanizes", + "humouring", "humoring", + "hybridise", "hybridize", + "hypnotise", "hypnotize", + "idealised", "idealized", + "idealises", "idealizes", + "idolising", "idolizing", + "immunised", "immunized", + "immunises", "immunizes", + "inflexion", "inflection", + "italicise", "italicize", + "itemising", "itemizing", + "jewellers", "jewelers", + "jewellery", "jewelry", + "kilometre", "kilometer", + "labelling", "labeling", + "labourers", "laborers", + "labouring", "laboring", + "legalised", "legalized", + "legalises", "legalizes", + "leukaemia", "leukemia", + "levellers", "levelers", + "levelling", "leveling", + "libelling", "libeling", + "libellous", "libelous", + "licencing", "licensing", + "lionising", "lionizing", + "liquidise", "liquidize", + "localised", "localized", + "localises", "localizes", + "magnetise", "magnetize", + "manoeuvre", "maneuver", + "marvelled", "marveled", + "maximised", "maximized", + "maximises", "maximizes", + "mechanise", "mechanize", + "mediaeval", "medieval", + "memorised", "memorized", + "memorises", "memorizes", + "mesmerise", "mesmerize", + "minimised", "minimized", + "minimises", "minimizes", + "mobilised", "mobilized", + "mobilises", "mobilizes", + "modellers", "modelers", + "modelling", "modeling", + "modernise", "modernize", + "moralised", "moralized", + "moralises", "moralizes", + "motorised", "motorized", + "mouldered", "moldered", + "mouldiest", "moldiest", + "mouldings", "moldings", + "moustache", "mustache", + "neighbour", "neighbor", + "normalise", "normalize", + "odourless", "odorless", + "oestrogen", "estrogen", + "optimised", "optimized", + "optimises", "optimizes", + "organised", "organized", + "organiser", "organizer", + "organises", "organizes", + "ostracise", "ostracize", + "oxidising", "oxidizing", + "paederast", "pederast", + "panelling", "paneling", + "panellist", "panelist", + "paralysed", "paralyzed", + "paralyses", "paralyzes", + "parcelled", "parceled", + "passivise", "passivize", + "patronise", "patronize", + "pedalling", "pedaling", + "penalised", "penalized", + "penalises", "penalizes", + "pencilled", "penciled", + "ploughing", "plowing", + "ploughman", "plowman", + "ploughmen", "plowmen", + "polarised", "polarized", + "polarises", "polarizes", + "practised", "practiced", + "practises", "practices", + "pretences", "pretenses", + "primaeval", "primeval", + "privatise", "privatize", + "programme", "program", + "publicise", "publicize", + "pulverise", "pulverize", + "pummelled", "pummel", + "randomise", "randomize", + "ravelling", "raveling", + "realising", "realizing", + "recognise", "recognize", + "refuelled", "refueled", + "remoulded", "remolded", + "revellers", "revelers", + "revelling", "reveling", + "rivalling", "rivaling", + "saltpetre", "saltpeter", + "sanitised", "sanitized", + "sanitises", "sanitizes", + "satirised", "satirized", + "satirises", "satirizes", + "savouries", "savories", + "savouring", "savoring", + "sceptical", "skeptical", + "sensitise", "sensitize", + "sepulchre", "sepulcher", + "serialise", "serialize", + "sermonise", "sermonize", + "shovelled", "shoveled", + "signalise", "signalize", + "signalled", "signaled", + "snivelled", "sniveled", + "socialise", "socialize", + "sodomised", "sodomized", + "sodomises", "sodomizes", + "solemnise", "solemnize", + "spiralled", "spiraled", + "splendour", "splendor", + "stabilise", "stabilize", + "sterilise", "sterilize", + "subsidise", "subsidize", + "succoured", "succored", + "sulphates", "sulfates", + "sulphides", "sulfides", + "summarise", "summarize", + "swivelled", "swiveled", + "symbolise", "symbolize", + "syphoning", "siphoning", + "tantalise", "tantalize", + "tasselled", "tasseled", + "temporise", "temporize", + "tenderise", "tenderize", + "terrorise", "terrorize", + "theorised", "theorized", + "theorises", "theorizes", + "towelling", "toweling", + "travelled", "traveled", + "traveller", "traveler", + "trialling", "trialing", + "tricolour", "tricolor", + "tunnelled", "tunneled", + "tyrannise", "tyrannize", + "unionised", "unionized", + "unionises", "unionizes", + "unsavoury", "unsavory", + "urbanised", "urbanized", + "urbanises", "urbanizes", + "utilising", "utilizing", + "vandalise", "vandalize", + "vaporised", "vaporized", + "vaporises", "vaporizes", + "verbalise", "verbalize", + "victimise", "victimize", + "visualise", "visualize", + "vocalised", "vocalized", + "vocalises", "vocalizes", + "vulgarise", "vulgarize", + "weaselled", "weaseled", + "womanised", "womanized", + "womaniser", "womanizer", + "womanises", "womanizes", + "yodelling", "yodeling", + "yoghourts", "yogurts", + "agonised", "agonized", + "agonises", "agonizes", + "almanack", "almanac", + "amortise", "amortize", + "analogue", "analog", + "analysed", "analyzed", + "armoured", "armored", + "armourer", "armorer", + "artefact", "artifact", + "baptised", "baptized", + "baptises", "baptizes", + "baulking", "balking", + "belabour", "belabor", + "bevelled", "beveled", + "calibres", "calibers", + "calliper", "caliper", + "canalise", "canalize", + "canonise", "canonize", + "carolled", "caroled", + "catalyse", "catalyze", + "cavilled", "caviled", + "civilise", "civilize", + "clamours", "clamors", + "clangour", "clangor", + "colonise", "colonize", + "coloured", "colored", + "cosiness", "coziness", + "crueller", "crueler", + "defences", "defenses", + "demonise", "demonize", + "deputise", "deputize", + "dialling", "dialing", + "dialogue", "dialog", + "digitise", "digitize", + "draughty", "drafty", + "duelling", "dueling", + "energise", "energize", + "enthrals", "enthralls", + "equalise", "equalize", + "eulogise", "eulogize", + "favoured", "favored", + "feminise", "feminize", + "finalise", "finalize", + "flautist", "flutist", + "flavours", "flavors", + "foetuses", "fetuses", + "fuelling", "fueling", + "gaolbird", "jailbird", + "gryphons", "griffins", + "harbours", "harbors", + "honoured", "honored", + "humanise", "humanize", + "humoured", "humored", + "idealise", "idealize", + "idolised", "idolized", + "idolises", "idolizes", + "immunise", "immunize", + "ionisers", "ionizers", + "ionising", "ionizing", + "itemised", "itemized", + "itemises", "itemizes", + "jewelled", "jeweled", + "jeweller", "jeweler", + "labelled", "labeled", + "laboured", "labored", + "labourer", "laborer", + "legalise", "legalize", + "levelled", "leveled", + "leveller", "leveler", + "libelled", "libeled", + "licenced", "licensed", + "licences", "licenses", + "lionised", "lionized", + "lionises", "lionizes", + "localise", "localize", + "maximise", "maximize", + "memorise", "memorize", + "minimise", "minimize", + "misspelt", "misspelled", + "mobilise", "mobilize", + "modelled", "modeled", + "modeller", "modeler", + "moralise", "moralize", + "moulders", "molders", + "mouldier", "moldier", + "moulding", "molding", + "moulting", "molting", + "offences", "offenses", + "optimise", "optimize", + "organise", "organize", + "oxidised", "oxidized", + "oxidises", "oxidizes", + "panelled", "paneled", + "paralyse", "paralyze", + "parlours", "parlors", + "pedalled", "pedaled", + "penalise", "penalize", + "philtres", "filters", + "ploughed", "plowed", + "polarise", "polarize", + "practise", "practice", + "pretence", "pretense", + "ravelled", "raveled", + "realised", "realized", + "realises", "realizes", + "remoulds", "remolds", + "revelled", "reveled", + "reveller", "reveler", + "rivalled", "rivaled", + "rumoured", "rumored", + "sanitise", "sanitize", + "satirise", "satirize", + "saviours", "saviors", + "savoured", "savored", + "sceptics", "skeptics", + "sceptres", "scepters", + "sodomise", "sodomize", + "spectres", "specters", + "succours", "succors", + "sulphate", "sulfate", + "sulphide", "sulfide", + "syphoned", "siphoned", + "theatres", "theaters", + "theorise", "theorize", + "towelled", "toweled", + "toxaemia", "toxemia", + "trialled", "trialed", + "unionise", "unionize", + "urbanise", "urbanize", + "utilised", "utilized", + "utilises", "utilizes", + "vaporise", "vaporize", + "vocalise", "vocalize", + "womanise", "womanize", + "yodelled", "yodeled", + "yoghourt", "yogurt", + "yoghurts", "yogurts", + "agonise", "agonize", + "anaemia", "anemia", + "anaemic", "anemic", + "analyse", "analyze", + "arbours", "arbors", + "armoury", "armory", + "baptise", "baptize", + "baulked", "balked", + "behoved", "behooved", + "behoves", "behooves", + "calibre", "caliber", + "candour", "candor", + "centred", "centered", + "centres", "centers", + "cheques", "checks", + "clamour", "clamor", + "colours", "colors", + "cosiest", "coziest", + "defence", "defense", + "dialled", "dialed", + "distils", "distills", + "duelled", "dueled", + "enthral", "enthrall", + "favours", "favors", + "fervour", "fervor", + "flavour", "flavor", + "fuelled", "fueled", + "fulfils", "fulfills", + "gaolers", "jailers", + "gaoling", "jailing", + "gipsies", "gypsies", + "glueing", "gluing", + "goitres", "goiters", + "grammes", "grams", + "groynes", "groins", + "gryphon", "griffin", + "harbour", "harbor", + "honours", "honors", + "humours", "humors", + "idolise", "idolize", + "instals", "installs", + "instils", "instills", + "ionised", "ionized", + "ioniser", "ionizer", + "ionises", "ionizes", + "itemise", "itemize", + "labours", "labors", + "licence", "license", + "lionise", "lionize", + "louvred", "louvered", + "louvres", "louvers", + "moulded", "molded", + "moulder", "molder", + "moulted", "molted", + "offence", "offense", + "oxidise", "oxidize", + "parlour", "parlor", + "philtre", "filter", + "ploughs", "plows", + "pyjamas", "pajamas", + "rancour", "rancor", + "realise", "realize", + "remould", "remold", + "rigours", "rigors", + "rumours", "rumors", + "saviour", "savior", + "savours", "savors", + "savoury", "savory", + "sceptic", "skeptic", + "sceptre", "scepter", + "spectre", "specter", + "storeys", "stories", + "succour", "succor", + "sulphur", "sulfur", + "syphons", "siphons", + "theatre", "theater", + "tumours", "tumors", + "utilise", "utilize", + "vapours", "vapors", + "waggons", "wagons", + "yoghurt", "yogurt", + "ageing", "aging", + "appals", "appalls", + "arbour", "arbor", + "ardour", "ardor", + "baulks", "balks", + "behove", "behoove", + "centre", "center", + "cheque", "check", + "chilli", "chili", + "colour", "color", + "cosier", "cozier", + "cosies", "cozies", + "cosily", "cozily", + "distil", "distill", + "edoema", "edema", + "enrols", "enrolls", + "faecal", "fecal", + "faeces", "feces", + "favour", "favor", + "fibres", "fibers", + "foetal", "fetal", + "foetid", "fetid", + "foetus", "fetus", + "fulfil", "fulfill", + "gaoled", "jailed", + "gaoler", "jailer", + "goitre", "goiter", + "gramme", "gram", + "groyne", "groin", + "honour", "honor", + "humour", "humor", + "instal", "install", + "instil", "instill", + "ionise", "ionize", + "labour", "labor", + "litres", "liters", + "lustre", "luster", + "meagre", "meager", + "metres", "meters", + "mitres", "miters", + "moulds", "molds", + "mouldy", "moldy", + "moults", "molts", + "odours", "odors", + "plough", "plow", + "pyjama", "pajama", + "rigour", "rigor", + "rumour", "rumor", + "savour", "savor", + "storey", "story", + "syphon", "siphon", + "tumour", "tumor", + "valour", "valor", + "vapour", "vapor", + "vigour", "vigor", + "waggon", "wagon", + "appal", "appall", + "baulk", "balk", + "enrol", "enroll", + "fibre", "fiber", + "gaols", "jails", + "litre", "liter", + "metre", "meter", + "mitre", "miter", + "mould", "mold", + "moult", "molt", + "odour", "odor", + "tyres", "tires", + "cosy", "cozy", + "gaol", "jail", + "tyre", "tire", +} diff --git a/vendor/github.com/golangci/plugin-module-register/LICENSE b/vendor/github.com/golangci/plugin-module-register/LICENSE index e72bfddab..cbdf3d374 100644 --- a/vendor/github.com/golangci/plugin-module-register/LICENSE +++ b/vendor/github.com/golangci/plugin-module-register/LICENSE @@ -1,674 +1,201 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file + 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 2024 GolangCI 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. diff --git a/vendor/github.com/golangci/swaggoswag/.gitignore b/vendor/github.com/golangci/swaggoswag/.gitignore new file mode 100644 index 000000000..865a6f357 --- /dev/null +++ b/vendor/github.com/golangci/swaggoswag/.gitignore @@ -0,0 +1,24 @@ +dist +testdata/simple*/docs +testdata/quotes/docs +testdata/quotes/quotes.so +testdata/delims/docs +testdata/delims/delims.so +example/basic/docs/* +example/celler/docs/* +cover.out + + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +.idea +.vscode + +# Etc +.DS_Store + +/swag +/swag.exe diff --git a/vendor/github.com/golangci/swaggoswag/formatter.go b/vendor/github.com/golangci/swaggoswag/formatter.go new file mode 100644 index 000000000..6bf92861d --- /dev/null +++ b/vendor/github.com/golangci/swaggoswag/formatter.go @@ -0,0 +1,180 @@ +package swaggoswag + +import ( + "bytes" + "fmt" + "go/ast" + goparser "go/parser" + "go/token" + "regexp" + "sort" + "strings" + "text/tabwriter" + + "golang.org/x/tools/imports" +) + +// Check of @Param @Success @Failure @Response @Header +var specialTagForSplit = map[string]bool{ + paramAttr: true, + successAttr: true, + failureAttr: true, + responseAttr: true, + headerAttr: true, +} + +var skipChar = map[byte]byte{ + '"': '"', + '(': ')', + '{': '}', + '[': ']', +} + +// Formatter implements a formatter for Go source files. +type Formatter struct{} + +// NewFormatter create a new formatter instance. +func NewFormatter() *Formatter { + formatter := &Formatter{} + return formatter +} + +// Format formats swag comments in contents. It uses fileName to report errors +// that happen during parsing of contents. +func (f *Formatter) Format(fileName string, contents []byte) ([]byte, error) { + fileSet := token.NewFileSet() + ast, err := goparser.ParseFile(fileSet, fileName, contents, goparser.ParseComments) + if err != nil { + return nil, err + } + + // Formatting changes are described as an edit list of byte range + // replacements. We make these content-level edits directly rather than + // changing the AST nodes and writing those out (via [go/printer] or + // [go/format]) so that we only change the formatting of Swag attribute + // comments. This won't touch the formatting of any other comments, or of + // functions, etc. + maxEdits := 0 + for _, comment := range ast.Comments { + maxEdits += len(comment.List) + } + edits := make(edits, 0, maxEdits) + + for _, comment := range ast.Comments { + formatFuncDoc(fileSet, comment.List, &edits) + } + formatted, err := imports.Process(fileName, edits.apply(contents), nil) + if err != nil { + return nil, err + } + return formatted, nil +} + +type edit struct { + begin int + end int + replacement []byte +} + +type edits []edit + +func (edits edits) apply(contents []byte) []byte { + // Apply the edits with the highest offset first, so that earlier edits + // don't affect the offsets of later edits. + sort.Slice(edits, func(i, j int) bool { + return edits[i].begin > edits[j].begin + }) + + for _, edit := range edits { + prefix := contents[:edit.begin] + suffix := contents[edit.end:] + contents = append(prefix, append(edit.replacement, suffix...)...) + } + + return contents +} + +// formatFuncDoc reformats the comment lines in commentList, and appends any +// changes to the edit list. +func formatFuncDoc(fileSet *token.FileSet, commentList []*ast.Comment, edits *edits) { + // Building the edit list to format a comment block is a two-step process. + // First, we iterate over each comment line looking for Swag attributes. In + // each one we find, we replace alignment whitespace with a tab character, + // then write the result into a tab writer. + + linesToComments := make(map[int]int, len(commentList)) + + buffer := &bytes.Buffer{} + w := tabwriter.NewWriter(buffer, 1, 4, 1, '\t', 0) + + for commentIndex, comment := range commentList { + text := comment.Text + if attr, body, found := swagComment(text); found { + formatted := "//\t" + attr + if body != "" { + formatted += "\t" + splitComment2(attr, body) + } + _, _ = fmt.Fprintln(w, formatted) + linesToComments[len(linesToComments)] = commentIndex + } + } + + // Once we've loaded all of the comment lines to be aligned into the tab + // writer, flushing it causes the aligned text to be written out to the + // backing buffer. + _ = w.Flush() + + // Now the second step: we iterate over the aligned comment lines that were + // written into the backing buffer, pair each one up to its original + // comment line, and use the combination to describe the edit that needs to + // be made to the original input. + formattedComments := bytes.Split(buffer.Bytes(), []byte("\n")) + for lineIndex, commentIndex := range linesToComments { + comment := commentList[commentIndex] + *edits = append(*edits, edit{ + begin: fileSet.Position(comment.Pos()).Offset, + end: fileSet.Position(comment.End()).Offset, + replacement: formattedComments[lineIndex], + }) + } +} + +func splitComment2(attr, body string) string { + if specialTagForSplit[strings.ToLower(attr)] { + for i := 0; i < len(body); i++ { + if skipEnd, ok := skipChar[body[i]]; ok { + skipStart, n := body[i], 1 + for i++; i < len(body); i++ { + if skipStart != skipEnd && body[i] == skipStart { + n++ + } else if body[i] == skipEnd { + n-- + if n == 0 { + break + } + } + } + } else if body[i] == ' ' || body[i] == '\t' { + j := i + for ; j < len(body) && (body[j] == ' ' || body[j] == '\t'); j++ { + } + body = replaceRange(body, i, j, "\t") + } + } + } + return body +} + +func replaceRange(s string, start, end int, new string) string { + return s[:start] + new + s[end:] +} + +var swagCommentLineExpression = regexp.MustCompile(`^\/\/\s+(@[\S.]+)\s*(.*)`) + +func swagComment(comment string) (string, string, bool) { + matches := swagCommentLineExpression.FindStringSubmatch(comment) + if matches == nil { + return "", "", false + } + return matches[1], matches[2], true +} diff --git a/vendor/github.com/golangci/swaggoswag/license b/vendor/github.com/golangci/swaggoswag/license new file mode 100644 index 000000000..a97865bf4 --- /dev/null +++ b/vendor/github.com/golangci/swaggoswag/license @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Eason Lin + +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/vendor/github.com/golangci/swaggoswag/parser.go b/vendor/github.com/golangci/swaggoswag/parser.go new file mode 100644 index 000000000..368517b61 --- /dev/null +++ b/vendor/github.com/golangci/swaggoswag/parser.go @@ -0,0 +1,48 @@ +package swaggoswag + +const ( + // CamelCase indicates using CamelCase strategy for struct field. + CamelCase = "camelcase" + + // PascalCase indicates using PascalCase strategy for struct field. + PascalCase = "pascalcase" + + // SnakeCase indicates using SnakeCase strategy for struct field. + SnakeCase = "snakecase" + + idAttr = "@id" + acceptAttr = "@accept" + produceAttr = "@produce" + paramAttr = "@param" + successAttr = "@success" + failureAttr = "@failure" + responseAttr = "@response" + headerAttr = "@header" + tagsAttr = "@tags" + routerAttr = "@router" + deprecatedRouterAttr = "@deprecatedrouter" + summaryAttr = "@summary" + deprecatedAttr = "@deprecated" + securityAttr = "@security" + titleAttr = "@title" + conNameAttr = "@contact.name" + conURLAttr = "@contact.url" + conEmailAttr = "@contact.email" + licNameAttr = "@license.name" + licURLAttr = "@license.url" + versionAttr = "@version" + descriptionAttr = "@description" + descriptionMarkdownAttr = "@description.markdown" + secBasicAttr = "@securitydefinitions.basic" + secAPIKeyAttr = "@securitydefinitions.apikey" + secApplicationAttr = "@securitydefinitions.oauth2.application" + secImplicitAttr = "@securitydefinitions.oauth2.implicit" + secPasswordAttr = "@securitydefinitions.oauth2.password" + secAccessCodeAttr = "@securitydefinitions.oauth2.accesscode" + tosAttr = "@termsofservice" + extDocsDescAttr = "@externaldocs.description" + extDocsURLAttr = "@externaldocs.url" + xCodeSamplesAttr = "@x-codesamples" + scopeAttrPrefix = "@scope." + stateAttr = "@state" +) diff --git a/vendor/github.com/golangci/swaggoswag/readme.md b/vendor/github.com/golangci/swaggoswag/readme.md new file mode 100644 index 000000000..4d1c26005 --- /dev/null +++ b/vendor/github.com/golangci/swaggoswag/readme.md @@ -0,0 +1,26 @@ +# Fork of swaggo/swag + +This is a hard fork of [swaggo/swag](https://github.com/swaggo/swag) to be usable as a library. + +I considered other options before deciding to fork, but there are no straightforward or non-invasive changes. + +Issues should be open either on the original [swaggo/swag repository](https://github.com/swaggo/swag) or on [golangci-lint repository](https://github.com/golangci/golangci-lint). + +**No modifications will be accepted other than the synchronization of the fork.** + +The synchronization of the fork will be done by the golangci-lint maintainers only. + +## Modifications + +- All the files have been removed except: + - `formatter.go` (the unused field `debug Debugger` is removed) + - `formatter_test.go` + - `parser.go` (only the constants are kept.) + - `license` + - `.gitignore` +- The module name has been changed to `github.com/golangci/swaggoswag` to avoid replacement directives inside golangci-lint. + - The package name has been changed from `swag` to `swaggoswag`. + +## History + +- sync with 93e86851e9f22f1f2db57812cf71fc004c02159c (after v1.16.4) diff --git a/vendor/github.com/gordonklaus/ineffassign/pkg/ineffassign/ineffassign.go b/vendor/github.com/gordonklaus/ineffassign/pkg/ineffassign/ineffassign.go index f9dece8f2..19da47b5c 100644 --- a/vendor/github.com/gordonklaus/ineffassign/pkg/ineffassign/ineffassign.go +++ b/vendor/github.com/gordonklaus/ineffassign/pkg/ineffassign/ineffassign.go @@ -5,21 +5,26 @@ import ( "go/ast" "go/token" "sort" - "strings" "golang.org/x/tools/go/analysis" ) +var checkEscapingErrors bool + // Analyzer is the ineffassign analysis.Analyzer instance. var Analyzer = &analysis.Analyzer{ Name: "ineffassign", - Doc: "detect ineffectual assignments in Go code", + Doc: "detects when assignments to existing variables are not used", Run: checkPath, } +func init() { + Analyzer.Flags.BoolVar(&checkEscapingErrors, "check-escaping-errors", false, "check escaping variables of type error, may cause false positives") +} + func checkPath(pass *analysis.Pass) (interface{}, error) { for _, file := range pass.Files { - if isGenerated(file) { + if ast.IsGenerated(file) { continue } @@ -35,6 +40,7 @@ func checkPath(pass *analysis.Pass) (interface{}, error) { for _, id := range chk.ineff { pass.Report(analysis.Diagnostic{ Pos: id.Pos(), + End: id.End(), Message: fmt.Sprintf("ineffectual assignment to %s", id.Name), }) } @@ -43,18 +49,6 @@ func checkPath(pass *analysis.Pass) (interface{}, error) { return nil, nil } -func isGenerated(file *ast.File) bool { - for _, cg := range file.Comments { - for _, c := range cg.List { - if strings.HasPrefix(c.Text, "// Code generated ") && strings.HasSuffix(c.Text, " DO NOT EDIT.") { - return true - } - } - } - - return false -} - type builder struct { roots []*block block *block @@ -96,10 +90,10 @@ func (bld *builder) Visit(n ast.Node) ast.Visitor { switch n := n.(type) { case *ast.FuncDecl: if n.Body != nil { - bld.fun(n.Type, n.Body) + bld.fun(n.Recv, n.Type, n.Body) } case *ast.FuncLit: - bld.fun(n.Type, n.Body) + bld.fun(nil, n.Type, n.Body) case *ast.IfStmt: bld.walk(n.Init) bld.walk(n.Cond) @@ -290,9 +284,7 @@ func (bld *builder) Visit(n ast.Node) ast.Visitor { id, ok = ident(ix.X) } if ok && n.Op == token.AND { - if v, ok := bld.vars[id.Obj]; ok { - v.escapes = true - } + bld.escape(id) } return bld case *ast.SelectorExpr: @@ -301,18 +293,14 @@ func (bld *builder) Visit(n ast.Node) ast.Visitor { // the address of its receiver, causing it to escape. // We can't do any better here without knowing the variable's type. if id, ok := ident(n.X); ok { - if v, ok := bld.vars[id.Obj]; ok { - v.escapes = true - } + bld.escape(id) } return bld case *ast.SliceExpr: bld.maybePanic() // We don't care about slicing into slices, but without type information we can do no better. if id, ok := ident(n.X); ok { - if v, ok := bld.vars[id.Obj]; ok { - v.escapes = true - } + bld.escape(id) } return bld case *ast.StarExpr: @@ -328,6 +316,21 @@ func (bld *builder) Visit(n ast.Node) ast.Visitor { return nil } +func (bld *builder) escape(id *ast.Ident) { + if checkEscapingErrors && id.Obj != nil { + if d, ok := id.Obj.Decl.(*ast.ValueSpec); ok { + if t, ok := d.Type.(*ast.Ident); ok { + if t.Name == "error" { + return + } + } + } + } + if v, ok := bld.vars[id.Obj]; ok { + v.escapes = true + } +} + func isZeroInitializer(x ast.Expr) bool { // Assume that a call expression of a single argument is a conversion expression. We can't do better without type information. if c, ok := x.(*ast.CallExpr); ok { @@ -362,7 +365,7 @@ func isZeroInitializer(x ast.Expr) bool { return false } -func (bld *builder) fun(typ *ast.FuncType, body *ast.BlockStmt) { +func (bld *builder) fun(recv *ast.FieldList, typ *ast.FuncType, body *ast.BlockStmt) { for _, v := range bld.vars { v.fundept++ } @@ -372,6 +375,9 @@ func (bld *builder) fun(typ *ast.FuncType, body *ast.BlockStmt) { b := bld.block bld.newBlock() bld.roots = append(bld.roots, bld.block) + if recv != nil { + bld.walk(recv) + } bld.walk(typ) bld.walk(body) bld.block = b diff --git a/vendor/github.com/gostaticanalysis/nilerr/README.md b/vendor/github.com/gostaticanalysis/nilerr/README.md index d6b4acf8b..d2d8069bb 100644 --- a/vendor/github.com/gostaticanalysis/nilerr/README.md +++ b/vendor/github.com/gostaticanalysis/nilerr/README.md @@ -36,6 +36,12 @@ func f() error { } ``` +## How to use +``` +$ go install github.com/gostaticanalysis/nilerr/cmd/nilerr@latest +$ nilerr ./... +``` + [gopkg]: https://pkg.go.dev/github.com/gostaticanalysis/nilerr [gopkg-badge]: https://pkg.go.dev/badge/github.com/gostaticanalysis/nilerr?status.svg diff --git a/vendor/github.com/gostaticanalysis/nilerr/nilerr.go b/vendor/github.com/gostaticanalysis/nilerr/nilerr.go index 787a9e1e9..4615e6d14 100644 --- a/vendor/github.com/gostaticanalysis/nilerr/nilerr.go +++ b/vendor/github.com/gostaticanalysis/nilerr/nilerr.go @@ -4,6 +4,7 @@ import ( "fmt" "go/token" "go/types" + "slices" "github.com/gostaticanalysis/comment" "github.com/gostaticanalysis/comment/passes/commentmap" @@ -30,9 +31,10 @@ func run(pass *analysis.Pass) (interface{}, error) { reportFail := func(v ssa.Value, ret *ssa.Return, format string) { pos := ret.Pos() - line := getNodeLineNumber(pass, ret) - errLines := getValueLineNumbers(pass, v) - if !cmaps.IgnoreLine(pass.Fset, line, "nilerr") { + if !cmaps.IgnorePos(pos, "nilerr") { + seen := map[string]struct{}{} + errLines := getValueLineNumbers(pass, v, seen) + var errLineText string if len(errLines) == 1 { errLineText = fmt.Sprintf("line %d", errLines[0]) @@ -65,12 +67,30 @@ func run(pass *analysis.Pass) (interface{}, error) { return nil, nil } -func getValueLineNumbers(pass *analysis.Pass, v ssa.Value) []int { +// getValueLineNumbers returns the line numbers. +// `seen` is used to avoid infinite loop. +func getValueLineNumbers(pass *analysis.Pass, v ssa.Value, seen map[string]struct{}) []int { if phi, ok := v.(*ssa.Phi); ok { result := make([]int, 0, len(phi.Edges)) + for _, edge := range phi.Edges { - result = append(result, getValueLineNumbers(pass, edge)...) + if _, ok := seen[edge.Name()]; ok { + if edge.Pos() == token.NoPos { + // Skip elements without a position. + continue + } + + result = append(result, pass.Fset.File(edge.Pos()).Line(edge.Pos())) + continue + } + + seen[edge.Name()] = struct{}{} + + result = append(result, getValueLineNumbers(pass, edge, seen)...) } + + slices.Sort(result) + return result } @@ -80,12 +100,12 @@ func getValueLineNumbers(pass *analysis.Pass, v ssa.Value) []int { } pos := value.Pos() - return []int{pass.Fset.File(pos).Line(pos)} -} -func getNodeLineNumber(pass *analysis.Pass, node ssa.Node) int { - pos := node.Pos() - return pass.Fset.File(pos).Line(pos) + if pos == token.NoPos { + return nil + } + + return []int{pass.Fset.File(pos).Line(pos)} } var errType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) diff --git a/vendor/github.com/hashicorp/go-version/LICENSE b/vendor/github.com/hashicorp/go-version/LICENSE index 1409d6ab9..bb1e9a486 100644 --- a/vendor/github.com/hashicorp/go-version/LICENSE +++ b/vendor/github.com/hashicorp/go-version/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014 HashiCorp, Inc. +Copyright IBM Corp. 2014, 2025 Mozilla Public License, version 2.0 diff --git a/vendor/github.com/hashicorp/go-version/README.md b/vendor/github.com/hashicorp/go-version/README.md index 4b7806cd9..83a8249f7 100644 --- a/vendor/github.com/hashicorp/go-version/README.md +++ b/vendor/github.com/hashicorp/go-version/README.md @@ -1,6 +1,7 @@ # Versioning Library for Go + ![Build Status](https://github.com/hashicorp/go-version/actions/workflows/go-tests.yml/badge.svg) -[![GoDoc](https://godoc.org/github.com/hashicorp/go-version?status.svg)](https://godoc.org/github.com/hashicorp/go-version) +[![Go Reference](https://pkg.go.dev/badge/github.com/hashicorp/go-version.svg)](https://pkg.go.dev/github.com/hashicorp/go-version) go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version @@ -12,7 +13,7 @@ Versions used with go-version must follow [SemVer](http://semver.org/). ## Installation and Usage Package documentation can be found on -[GoDoc](http://godoc.org/github.com/hashicorp/go-version). +[Go Reference](https://pkg.go.dev/github.com/hashicorp/go-version). Installation can be done with a normal `go get`: diff --git a/vendor/github.com/hashicorp/go-version/constraint.go b/vendor/github.com/hashicorp/go-version/constraint.go index 29bdc4d2b..3964da070 100644 --- a/vendor/github.com/hashicorp/go-version/constraint.go +++ b/vendor/github.com/hashicorp/go-version/constraint.go @@ -1,4 +1,4 @@ -// Copyright (c) HashiCorp, Inc. +// Copyright IBM Corp. 2014, 2025 // SPDX-License-Identifier: MPL-2.0 package version @@ -8,8 +8,26 @@ import ( "regexp" "sort" "strings" + "sync" ) +var ( + constraintRegexp *regexp.Regexp + constraintRegexpOnce sync.Once +) + +func getConstraintRegexp() *regexp.Regexp { + constraintRegexpOnce.Do(func() { + // This heavy lifting only happens the first time this function is called + constraintRegexp = regexp.MustCompile(fmt.Sprintf( + `^\s*(%s)\s*(%s)\s*$`, + `<=|>=|!=|~>|<|>|=|`, + VersionRegexpRaw, + )) + }) + return constraintRegexp +} + // Constraint represents a single constraint for a version, such as // ">= 1.0". type Constraint struct { @@ -29,38 +47,11 @@ type Constraints []*Constraint type constraintFunc func(v, c *Version) bool -var constraintOperators map[string]constraintOperation - type constraintOperation struct { op operator f constraintFunc } -var constraintRegexp *regexp.Regexp - -func init() { - constraintOperators = map[string]constraintOperation{ - "": {op: equal, f: constraintEqual}, - "=": {op: equal, f: constraintEqual}, - "!=": {op: notEqual, f: constraintNotEqual}, - ">": {op: greaterThan, f: constraintGreaterThan}, - "<": {op: lessThan, f: constraintLessThan}, - ">=": {op: greaterThanEqual, f: constraintGreaterThanEqual}, - "<=": {op: lessThanEqual, f: constraintLessThanEqual}, - "~>": {op: pessimistic, f: constraintPessimistic}, - } - - ops := make([]string, 0, len(constraintOperators)) - for k := range constraintOperators { - ops = append(ops, regexp.QuoteMeta(k)) - } - - constraintRegexp = regexp.MustCompile(fmt.Sprintf( - `^\s*(%s)\s*(%s)\s*$`, - strings.Join(ops, "|"), - VersionRegexpRaw)) -} - // NewConstraint will parse one or more constraints from the given // constraint string. The string must be a comma-separated list of // constraints. @@ -107,7 +98,7 @@ func (cs Constraints) Check(v *Version) bool { // to '>0.2' it is *NOT* treated as equal. // // Missing operator is treated as equal to '=', whitespaces -// are ignored and constraints are sorted before comaparison. +// are ignored and constraints are sorted before comparison. func (cs Constraints) Equals(c Constraints) bool { if len(cs) != len(c) { return false @@ -176,9 +167,9 @@ func (c *Constraint) String() string { } func parseSingle(v string) (*Constraint, error) { - matches := constraintRegexp.FindStringSubmatch(v) + matches := getConstraintRegexp().FindStringSubmatch(v) if matches == nil { - return nil, fmt.Errorf("Malformed constraint: %s", v) + return nil, fmt.Errorf("malformed constraint: %s", v) } check, err := NewVersion(matches[2]) @@ -186,7 +177,25 @@ func parseSingle(v string) (*Constraint, error) { return nil, err } - cop := constraintOperators[matches[1]] + var cop constraintOperation + switch matches[1] { + case "=": + cop = constraintOperation{op: equal, f: constraintEqual} + case "!=": + cop = constraintOperation{op: notEqual, f: constraintNotEqual} + case ">": + cop = constraintOperation{op: greaterThan, f: constraintGreaterThan} + case "<": + cop = constraintOperation{op: lessThan, f: constraintLessThan} + case ">=": + cop = constraintOperation{op: greaterThanEqual, f: constraintGreaterThanEqual} + case "<=": + cop = constraintOperation{op: lessThanEqual, f: constraintLessThanEqual} + case "~>": + cop = constraintOperation{op: pessimistic, f: constraintPessimistic} + default: + cop = constraintOperation{op: equal, f: constraintEqual} + } return &Constraint{ f: cop.f, diff --git a/vendor/github.com/hashicorp/go-version/version.go b/vendor/github.com/hashicorp/go-version/version.go index 7c683c281..17b29732e 100644 --- a/vendor/github.com/hashicorp/go-version/version.go +++ b/vendor/github.com/hashicorp/go-version/version.go @@ -1,23 +1,39 @@ -// Copyright (c) HashiCorp, Inc. +// Copyright IBM Corp. 2014, 2025 // SPDX-License-Identifier: MPL-2.0 package version import ( - "bytes" "database/sql/driver" "fmt" "regexp" "strconv" "strings" + "sync" ) // The compiled regular expression used to test the validity of a version. var ( - versionRegexp *regexp.Regexp - semverRegexp *regexp.Regexp + versionRegexp *regexp.Regexp + versionRegexpOnce sync.Once + semverRegexp *regexp.Regexp + semverRegexpOnce sync.Once ) +func getVersionRegexp() *regexp.Regexp { + versionRegexpOnce.Do(func() { + versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$") + }) + return versionRegexp +} + +func getSemverRegexp() *regexp.Regexp { + semverRegexpOnce.Do(func() { + semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$") + }) + return semverRegexp +} + // The raw regular expression string used for testing the validity // of a version. const ( @@ -42,28 +58,23 @@ type Version struct { original string } -func init() { - versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$") - semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$") -} - // NewVersion parses the given version and returns a new // Version. func NewVersion(v string) (*Version, error) { - return newVersion(v, versionRegexp) + return newVersion(v, getVersionRegexp()) } // NewSemver parses the given version and returns a new // Version that adheres strictly to SemVer specs // https://semver.org/ func NewSemver(v string) (*Version, error) { - return newVersion(v, semverRegexp) + return newVersion(v, getSemverRegexp()) } func newVersion(v string, pattern *regexp.Regexp) (*Version, error) { matches := pattern.FindStringSubmatch(v) if matches == nil { - return nil, fmt.Errorf("Malformed version: %s", v) + return nil, fmt.Errorf("malformed version: %s", v) } segmentsStr := strings.Split(matches[1], ".") segments := make([]int64, len(segmentsStr)) @@ -71,7 +82,7 @@ func newVersion(v string, pattern *regexp.Regexp) (*Version, error) { val, err := strconv.ParseInt(str, 10, 64) if err != nil { return nil, fmt.Errorf( - "Error parsing version: %s", err) + "error parsing version: %s", err) } segments[i] = val @@ -174,7 +185,7 @@ func (v *Version) Compare(other *Version) int { } else if lhs < rhs { return -1 } - // Otherwis, rhs was > lhs, they're not equal + // Otherwise, rhs was > lhs, they're not equal return 1 } @@ -382,22 +393,29 @@ func (v *Version) Segments64() []int64 { // missing parts (1.0 => 1.0.0) will be made into a canonicalized form // as shown in the parenthesized examples. func (v *Version) String() string { - var buf bytes.Buffer - fmtParts := make([]string, len(v.segments)) + return string(v.bytes()) +} + +func (v *Version) bytes() []byte { + var buf []byte for i, s := range v.segments { - // We can ignore err here since we've pre-parsed the values in segments - str := strconv.FormatInt(s, 10) - fmtParts[i] = str + if i > 0 { + buf = append(buf, '.') + } + buf = strconv.AppendInt(buf, s, 10) } - fmt.Fprintf(&buf, strings.Join(fmtParts, ".")) + if v.pre != "" { - fmt.Fprintf(&buf, "-%s", v.pre) + buf = append(buf, '-') + buf = append(buf, v.pre...) } + if v.metadata != "" { - fmt.Fprintf(&buf, "+%s", v.metadata) + buf = append(buf, '+') + buf = append(buf, v.metadata...) } - return buf.String() + return buf } // Original returns the original parsed version as-is, including any diff --git a/vendor/github.com/hashicorp/go-version/version_collection.go b/vendor/github.com/hashicorp/go-version/version_collection.go index 83547fe13..11bc8b1c5 100644 --- a/vendor/github.com/hashicorp/go-version/version_collection.go +++ b/vendor/github.com/hashicorp/go-version/version_collection.go @@ -1,4 +1,4 @@ -// Copyright (c) HashiCorp, Inc. +// Copyright IBM Corp. 2014, 2025 // SPDX-License-Identifier: MPL-2.0 package version diff --git a/vendor/github.com/jgautheron/goconst/README.md b/vendor/github.com/jgautheron/goconst/README.md index 3ad33b9ce..727974d00 100644 --- a/vendor/github.com/jgautheron/goconst/README.md +++ b/vendor/github.com/jgautheron/goconst/README.md @@ -18,7 +18,7 @@ While this could be considered a beginner mistake, across time, multiple package ``` Usage: - goconst ARGS + goconst ARGS [...] Flags: @@ -27,13 +27,15 @@ Flags: -ignore-tests exclude tests from the search (default: true) -min-occurrences report from how many occurrences (default: 2) -min-length only report strings with the minimum given length (default: 3) - -match-constant look for existing constants matching the values + -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") -numbers search also for duplicated numbers - -min minimum value, only works with -numbers - -max maximum value, only works with -numbers + -min minimum value, only works with -numbers + -max maximum value, only works with -numbers -output output formatting (text or json) -set-exit-status Set exit status to 2 if any issues are found + -grouped print single line per match, only works with -output text Examples: @@ -42,6 +44,7 @@ Examples: goconst -min-occurrences 3 -output json $GOPATH/src/github.com/cockroachdb/cockroach 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" ``` ### Development diff --git a/vendor/github.com/jgautheron/goconst/visitor.go b/vendor/github.com/jgautheron/goconst/visitor.go index 339723f56..350e3ae62 100644 --- a/vendor/github.com/jgautheron/goconst/visitor.go +++ b/vendor/github.com/jgautheron/goconst/visitor.go @@ -133,12 +133,12 @@ func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) { var unquotedStr string if strings.HasPrefix(str, `"`) || strings.HasPrefix(str, "`") { var err error - // Reuse strings from pool if possible to avoid allocations - sb := GetStringBuilder() - defer PutStringBuilder(sb) - unquotedStr, err = strconv.Unquote(str) if err != nil { + // Reuse strings from pool if possible to avoid allocations + sb := GetStringBuilder() + defer PutStringBuilder(sb) + // If unquoting fails, manually strip quotes // This avoids additional temporary strings if len(str) >= 2 { diff --git a/vendor/github.com/jjti/go-spancheck/.gitignore b/vendor/github.com/jjti/go-spancheck/.gitignore index 04b66d911..fc9b2a109 100644 --- a/vendor/github.com/jjti/go-spancheck/.gitignore +++ b/vendor/github.com/jjti/go-spancheck/.gitignore @@ -18,4 +18,5 @@ # vendor/ src/ -.vscode \ No newline at end of file +.vscode +.DS_Store \ No newline at end of file diff --git a/vendor/github.com/jjti/go-spancheck/.golangci.yml b/vendor/github.com/jjti/go-spancheck/.golangci.yml index 5d6ab1287..74a4377ab 100644 --- a/vendor/github.com/jjti/go-spancheck/.golangci.yml +++ b/vendor/github.com/jjti/go-spancheck/.golangci.yml @@ -17,11 +17,9 @@ linters: - errcheck - errname - errorlint - - exportloopref # checks for pointers to enclosing loop variables - gci - gochecknoinits # checks that no init functions are present in Go code - gocritic - - gomnd - gosimple - govet - importas # enforces consistent import aliases @@ -42,7 +40,6 @@ linters: - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint - staticcheck - stylecheck - - tenv - thelper # detects golang test helpers without t.Helper() call and checks the consistency of test helpers - unconvert # removes unnecessary type conversions - unparam # reports unused function parameters @@ -80,7 +77,7 @@ linters-settings: nestif: # Minimal complexity of if statements to report. # Default: 5 - min-complexity: 4 + min-complexity: 5 nolintlint: # Enable to require an explanation of nonzero length after each nolint directive. # Default: false diff --git a/vendor/github.com/jjti/go-spancheck/README.md b/vendor/github.com/jjti/go-spancheck/README.md index 393663ba7..87c32fc66 100644 --- a/vendor/github.com/jjti/go-spancheck/README.md +++ b/vendor/github.com/jjti/go-spancheck/README.md @@ -97,6 +97,8 @@ Flags: ### Ignore Check Signatures +This setting avoids false positives from utility functions that return spans (which are handled gracefully by callers of the function). + The `span.SetStatus()` and `span.RecordError()` checks warn when there is: 1. a path to return statement @@ -134,6 +136,8 @@ spancheck -checks 'end,set-status,record-error' -ignore-check-signatures 'record ### Extra Start Span Signatures +This setting informs spancheck of additional Span creation functions that should be linted (besides the library defaults). + By default, Span creation will be tracked from calls to [(go.opentelemetry.io/otel/trace.Tracer).Start](https://github.com/open-telemetry/opentelemetry-go/blob/98b32a6c3a87fbee5d34c063b9096f416b250897/trace/trace.go#L523), [go.opencensus.io/trace.StartSpan](https://pkg.go.dev/go.opencensus.io/trace#StartSpan), or [go.opencensus.io/trace.StartSpanWithRemoteParent](https://github.com/census-instrumentation/opencensus-go/blob/v0.24.0/trace/trace_api.go#L66). You can use the `-extra-start-span-signatures` flag to list additional Span creation functions. For all such functions: @@ -265,4 +269,6 @@ This linter is the product of liberal copying of: - [github.com/ghostiam/protogetter](https://github.com/ghostiam/protogetter/blob/main/testdata/Makefile) (test setup) And the contributions of: + - [@trixnz](https://github.com/trixnz) who [added support for custom span start functions](https://github.com/jjti/go-spancheck/pull/16) +- [@parsaaes](https://github.com/parsaaes) who [fixed a false negative bug in deferred methods that reference spans](https://github.com/jjti/go-spancheck/pull/31) diff --git a/vendor/github.com/jjti/go-spancheck/spancheck.go b/vendor/github.com/jjti/go-spancheck/spancheck.go index 49e581728..1618682aa 100644 --- a/vendor/github.com/jjti/go-spancheck/spancheck.go +++ b/vendor/github.com/jjti/go-spancheck/spancheck.go @@ -23,6 +23,12 @@ const ( spanOpenCensus // from go.opencensus.io/trace ) +const ( + selNameEnd = "End" + selNameSetStatus = "SetStatus" + selNameRecordError = "RecordError" +) + // SpanTypes is a list of all span types by name. var SpanTypes = map[string]spanType{ "opentelemetry": spanOpenTelemetry, @@ -183,7 +189,7 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) { for _, sv := range spanVars { if config.endCheckEnabled { // Check if there's no End to the span. - if ret := getMissingSpanCalls(pass, g, sv, "End", func(_ *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt { return ret }, nil, config.startSpanMatchers); ret != nil { + if ret := getMissingSpanCalls(pass, g, sv, selNameEnd, func(_ *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt { return ret }, nil, config.startSpanMatchers); ret != nil { pass.ReportRangef(sv.stmt, "%s.End is not called on all paths, possible memory leak", sv.vr.Name()) pass.ReportRangef(ret, "return can be reached without calling %s.End", sv.vr.Name()) } @@ -191,7 +197,7 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) { if config.setStatusEnabled { // Check if there's no SetStatus to the span setting an error. - if ret := getMissingSpanCalls(pass, g, sv, "SetStatus", getErrorReturn, config.ignoreChecksSignatures, config.startSpanMatchers); ret != nil { + if ret := getMissingSpanCalls(pass, g, sv, selNameSetStatus, getErrorReturn, config.ignoreChecksSignatures, config.startSpanMatchers); ret != nil { pass.ReportRangef(sv.stmt, "%s.SetStatus is not called on all paths", sv.vr.Name()) pass.ReportRangef(ret, "return can be reached without calling %s.SetStatus", sv.vr.Name()) } @@ -199,7 +205,7 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) { if config.recordErrorEnabled && sv.spanType == spanOpenTelemetry { // RecordError only exists in OpenTelemetry // Check if there's no RecordError to the span setting an error. - if ret := getMissingSpanCalls(pass, g, sv, "RecordError", getErrorReturn, config.ignoreChecksSignatures, config.startSpanMatchers); ret != nil { + if ret := getMissingSpanCalls(pass, g, sv, selNameRecordError, getErrorReturn, config.ignoreChecksSignatures, config.startSpanMatchers); ret != nil { pass.ReportRangef(sv.stmt, "%s.RecordError is not called on all paths", sv.vr.Name()) pass.ReportRangef(ret, "return can be reached without calling %s.RecordError", sv.vr.Name()) } @@ -216,7 +222,7 @@ func isSpanStart(info *types.Info, n ast.Node, startSpanMatchers []spanStartMatc fnSig := info.ObjectOf(sel.Sel).String() - // Check if the function is a span start function + // Check if the function is a span start function. for _, matcher := range startSpanMatchers { if matcher.signature.MatchString(fnSig) { return matcher.spanType, true @@ -399,6 +405,26 @@ func usesCall( } if g := cfgs.FuncLit(f); g != nil && len(g.Blocks) > 0 { + if selName == selNameEnd { + // Check if all returning blocks call end. + for _, b := range g.Blocks { + if b.Return() != nil && !usesCall( + pass, + b.Nodes, + sv, + selName, + ignoreCheckSig, + startSpanMatchers, + depth+1, + ) { + return false + } + } + + found = true + return false + } + for _, b := range g.Blocks { if usesCall( pass, diff --git a/vendor/github.com/kulti/thelper/pkg/analyzer/analyzer.go b/vendor/github.com/kulti/thelper/pkg/analyzer/analyzer.go index a22fd6aca..5a2d0f89d 100644 --- a/vendor/github.com/kulti/thelper/pkg/analyzer/analyzer.go +++ b/vendor/github.com/kulti/thelper/pkg/analyzer/analyzer.go @@ -1,3 +1,4 @@ +// Package analyzer implements the thelper linter logic. package analyzer import ( @@ -9,14 +10,14 @@ import ( "sort" "strings" - "github.com/gostaticanalysis/analysisutil" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" ) const ( - doc = "thelper detects tests helpers which is not start with t.Helper() method." + doc = "thelper detects tests helpers which do not start with the t.Helper() method." + checksDoc = `coma separated list of enabled checks Available checks @@ -45,7 +46,9 @@ func (m enabledChecksValue) String() string { for s := range m { ss = append(ss, s) } + sort.Strings(ss) + return strings.Join(ss, ",") } @@ -58,6 +61,7 @@ func (m enabledChecksValue) Set(s string) error { for k := range m { delete(m, k) } + for _, v := range ss { switch v { case checkTBegin, checkTFirst, checkTName, @@ -69,6 +73,7 @@ func (m enabledChecksValue) Set(s string) error { return fmt.Errorf("unknown check name %q (see help for full list)", v) } } + return nil } @@ -125,6 +130,7 @@ func NewAnalyzer() *analysis.Analyzer { return a } +//nolint:funlen // The function is easier to grok this way. func (t thelper) run(pass *analysis.Pass) (interface{}, error) { tCheckOpts, fCheckOpts, bCheckOpts, tbCheckOpts, ok := t.buildCheckFuncOpts(pass) if !ok { @@ -137,6 +143,7 @@ func (t thelper) run(pass *analysis.Pass) (interface{}, error) { } var reports reports + nodeFilter := []ast.Node{ (*ast.FuncDecl)(nil), (*ast.FuncLit)(nil), @@ -144,6 +151,7 @@ func (t thelper) run(pass *analysis.Pass) (interface{}, error) { } inspect.Preorder(nodeFilter, func(node ast.Node) { var fd funcDecl + switch n := node.(type) { case *ast.FuncLit: fd.Pos = n.Pos() @@ -157,13 +165,19 @@ func (t thelper) run(pass *analysis.Pass) (interface{}, error) { fd.Name = n.Name case *ast.CallExpr: runSubtestExprs := extractSubtestExp(pass, n, tCheckOpts.subRun, tCheckOpts.subTestFuncType) + if len(runSubtestExprs) == 0 { runSubtestExprs = extractSubtestExp(pass, n, bCheckOpts.subRun, bCheckOpts.subTestFuncType) } + if len(runSubtestExprs) == 0 { runSubtestExprs = extractSubtestFuzzExp(pass, n, fCheckOpts.subRun) } + if len(runSubtestExprs) == 0 { + runSubtestExprs = extractSynctestExp(pass, n, tCheckOpts.subTestFuncType) + } + if len(runSubtestExprs) > 0 { for _, expr := range runSubtestExprs { reports.Filter(funcDefPosition(pass, expr)) @@ -171,6 +185,7 @@ func (t thelper) run(pass *analysis.Pass) (interface{}, error) { } else { reports.NoFilter(funcDefPosition(pass, n.Fun)) } + return default: return @@ -202,7 +217,8 @@ type checkFuncOpts struct { func (t thelper) buildCheckFuncOpts(pass *analysis.Pass) (checkFuncOpts, checkFuncOpts, checkFuncOpts, checkFuncOpts, bool) { var ctxType types.Type - ctxObj := analysisutil.ObjectOf(pass, "context", "Context") + + ctxObj := findTypeObject(pass, "context.Context") if ctxObj != nil { ctxType = ctxObj.Type() } @@ -231,7 +247,7 @@ func (t thelper) buildCheckFuncOpts(pass *analysis.Pass) (checkFuncOpts, checkFu } func (t thelper) buildTestCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) (checkFuncOpts, bool) { - tObj := analysisutil.ObjectOf(pass, "testing", "T") + tObj := findTypeObject(pass, "testing.T") if tObj == nil { return checkFuncOpts{}, false } @@ -248,13 +264,14 @@ func (t thelper) buildTestCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) tType := types.NewPointer(tObj.Type()) tVar := types.NewVar(token.NoPos, nil, "t", tType) + return checkFuncOpts{ skipPrefix: "Test", varName: "t", fnHelper: tHelper, subRun: tRun, hpType: tType, - subTestFuncType: types.NewSignature(nil, types.NewTuple(tVar), nil, false), + subTestFuncType: types.NewSignatureType(nil, nil, nil, types.NewTuple(tVar), nil, false), ctxType: ctxType, checkBegin: t.enabledChecks.Enabled(checkTBegin), checkFirst: t.enabledChecks.Enabled(checkTFirst), @@ -263,7 +280,7 @@ func (t thelper) buildTestCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) } func (t thelper) buildFuzzCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) (checkFuncOpts, bool) { - fObj := analysisutil.ObjectOf(pass, "testing", "F") + fObj := findTypeObject(pass, "testing.F") if fObj == nil { return checkFuncOpts{}, true // fuzzing supports since go1.18, it's ok, that testig.F is missed. } @@ -292,7 +309,7 @@ func (t thelper) buildFuzzCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) } func (t thelper) buildBenchmarkCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) (checkFuncOpts, bool) { - bObj := analysisutil.ObjectOf(pass, "testing", "B") + bObj := findTypeObject(pass, "testing.B") if bObj == nil { return checkFuncOpts{}, false } @@ -309,13 +326,14 @@ func (t thelper) buildBenchmarkCheckFuncOpts(pass *analysis.Pass, ctxType types. bType := types.NewPointer(bObj.Type()) bVar := types.NewVar(token.NoPos, nil, "b", bType) + return checkFuncOpts{ skipPrefix: "Benchmark", varName: "b", fnHelper: bHelper, subRun: bRun, hpType: types.NewPointer(bObj.Type()), - subTestFuncType: types.NewSignature(nil, types.NewTuple(bVar), nil, false), + subTestFuncType: types.NewSignatureType(nil, nil, nil, types.NewTuple(bVar), nil, false), ctxType: ctxType, checkBegin: t.enabledChecks.Enabled(checkBBegin), checkFirst: t.enabledChecks.Enabled(checkBFirst), @@ -324,7 +342,7 @@ func (t thelper) buildBenchmarkCheckFuncOpts(pass *analysis.Pass, ctxType types. } func (t thelper) buildTBCheckFuncOpts(pass *analysis.Pass, ctxType types.Type) (checkFuncOpts, bool) { - tbObj := analysisutil.ObjectOf(pass, "testing", "TB") + tbObj := findTypeObject(pass, "testing.TB") if tbObj == nil { return checkFuncOpts{}, false } @@ -370,6 +388,7 @@ func checkFunc(pass *analysis.Pass, reports *reports, funcDecl funcDecl, opts ch if opts.checkFirst { if pos != 0 { checkFirstPassed := false + if pos == 1 && opts.ctxType != nil { _, pos, ok := searchFuncParam(pass, funcDecl, opts.ctxType) checkFirstPassed = ok && (pos == 0) @@ -404,6 +423,7 @@ func searchFuncParam(pass *analysis.Pass, f funcDecl, p types.Type) (*ast.Field, return f, i, true } } + return nil, 0, false } @@ -473,6 +493,44 @@ func extractSubtestFuzzExp( return []ast.Expr{e.Args[0]} } +// extractSynctestExp analyzes that call expression 'e' is synctest.Test +// and returns the test function. +func extractSynctestExp( + pass *analysis.Pass, e *ast.CallExpr, testFuncType types.Type, +) []ast.Expr { + // Check if this is a call to synctest.Test + selExpr, ok := e.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + // Check if the selector is "Test" + if selExpr.Sel.Name != "Test" { + return nil + } + + // Check if the package is synctest by looking at the identifier + ident, ok := selExpr.X.(*ast.Ident) + if !ok { + return nil + } + + if !isIdentPackageName(pass, ident, "testing/synctest") { + return nil + } + + // synctest.Test takes 2 arguments: t *testing.T, f func(*testing.T) + if len(e.Args) != 2 { + return nil + } + + if funcs := unwrapTestingFunctionBuilding(pass, e.Args[1], testFuncType); funcs != nil { + return funcs + } + + return []ast.Expr{e.Args[1]} +} + // unwrapTestingFunctionConstruction checks that expresion is build testing functions // and returns the result of building. func unwrapTestingFunctionBuilding(pass *analysis.Pass, expr ast.Expr, testFuncType types.Type) []ast.Expr { @@ -482,6 +540,7 @@ func unwrapTestingFunctionBuilding(pass *analysis.Pass, expr ast.Expr, testFuncT } var funcDecl funcDecl + switch f := callExpr.Fun.(type) { case *ast.FuncLit: funcDecl.Body = f.Body @@ -512,6 +571,7 @@ func unwrapTestingFunctionBuilding(pass *analysis.Pass, expr ast.Expr, testFuncT } var funcs []ast.Expr + ast.Inspect(funcDecl.Body, func(n ast.Node) bool { if n == nil { return false @@ -522,6 +582,7 @@ func unwrapTestingFunctionBuilding(pass *analysis.Pass, expr ast.Expr, testFuncT funcs = append(funcs, retStmt.Results[0]) } } + return true }) @@ -542,6 +603,7 @@ func funcDefPosition(pass *analysis.Pass, e ast.Expr) token.Pos { if !ok { return token.NoPos } + funIdent = selExpr.Sel } @@ -574,6 +636,21 @@ func isExprHasType(pass *analysis.Pass, expr ast.Expr, expType types.Type) bool return types.Identical(typeInfo.Type, expType) } +// isIdentPackageName returns true if ident refers to the specified package. +func isIdentPackageName(pass *analysis.Pass, ident *ast.Ident, pkgName string) bool { + obj := pass.TypesInfo.Uses[ident] + if obj == nil { + return false + } + + pkgObj, ok := obj.(*types.PkgName) + if !ok { + return false + } + + return pkgObj.Imported().Path() == pkgName +} + // findSelectorDeclaration returns function declaration called by selector expression. func findSelectorDeclaration(pass *analysis.Pass, expr *ast.SelectorExpr) *ast.FuncDecl { xsel, ok := pass.TypesInfo.Selections[expr] @@ -637,3 +714,22 @@ func findFunctionDeclaration(pass *analysis.Pass, ident *ast.Ident) *ast.FuncDec return nil } + +func findTypeObject(pass *analysis.Pass, typeName string) types.Object { + parts := strings.Split(typeName, ".") + pkgName := parts[0] + typeName = parts[1] + + for _, pkg := range pass.Pkg.Imports() { + if pkg.Name() != pkgName { + continue + } + + obj := pkg.Scope().Lookup(typeName) + if obj != nil { + return obj + } + } + + return nil +} diff --git a/vendor/github.com/kulti/thelper/pkg/analyzer/report.go b/vendor/github.com/kulti/thelper/pkg/analyzer/report.go index 4a23e36d5..3ee332742 100644 --- a/vendor/github.com/kulti/thelper/pkg/analyzer/report.go +++ b/vendor/github.com/kulti/thelper/pkg/analyzer/report.go @@ -31,6 +31,7 @@ func (rr *reports) Filter(pos token.Pos) { if rr.filter == nil { rr.filter = make(map[token.Pos]struct{}) } + rr.filter[pos] = struct{}{} } } @@ -40,17 +41,19 @@ func (rr *reports) NoFilter(pos token.Pos) { if rr.nofilter == nil { rr.nofilter = make(map[token.Pos]struct{}) } + rr.nofilter[pos] = struct{}{} } } -func (rr reports) Flush(pass *analysis.Pass) { +func (rr *reports) Flush(pass *analysis.Pass) { for _, r := range rr.reports { if _, ok := rr.filter[r.pos]; ok { if _, ok := rr.nofilter[r.pos]; !ok { continue } } + pass.Reportf(r.pos, r.format, r.args...) } } diff --git a/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go b/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go index aebbe70ea..6f59e8408 100644 --- a/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go +++ b/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go @@ -13,7 +13,8 @@ import ( const Doc = `check that tests use t.Parallel() method It also checks that the t.Parallel is used if multiple tests cases are run as part of single test. As part of ensuring parallel tests works as expected it checks for reinitializing of the range value -over the test cases.(https://tinyurl.com/y6555cy6)` +over the test cases.(https://tinyurl.com/y6555cy6) +With the -checkcleanup flag, it also checks that defer is not used with t.Parallel (use t.Cleanup instead).` func NewAnalyzer() *analysis.Analyzer { return newParallelAnalyzer().analyzer @@ -27,6 +28,7 @@ type parallelAnalyzer struct { ignoreMissing bool ignoreMissingSubtests bool ignoreLoopVar bool + checkCleanup bool } func newParallelAnalyzer() *parallelAnalyzer { @@ -36,6 +38,7 @@ func newParallelAnalyzer() *parallelAnalyzer { flags.BoolVar(&a.ignoreMissing, "i", false, "ignore missing calls to t.Parallel") flags.BoolVar(&a.ignoreMissingSubtests, "ignoremissingsubtests", false, "ignore missing calls to t.Parallel in subtests") flags.BoolVar(&a.ignoreLoopVar, "ignoreloopVar", false, "ignore loop variable detection") + flags.BoolVar(&a.checkCleanup, "checkcleanup", false, "check that defer is not used with t.Parallel (use t.Cleanup instead)") a.analyzer = &analysis.Analyzer{ Name: "paralleltest", @@ -51,11 +54,13 @@ type testFunctionAnalysis struct { funcCantParallelMethod, rangeStatementOverTestCasesExists, rangeStatementHasParallelMethod, - rangeStatementCantParallelMethod bool + rangeStatementCantParallelMethod, + funcHasDeferStatement bool loopVariableUsedInRun *string numberOfTestRun int positionOfTestRunNode []ast.Node rangeNode ast.Node + deferStatements []ast.Node } type testRunAnalysis struct { @@ -84,6 +89,7 @@ func (a *parallelAnalyzer) analyzeTestRun(pass *analysis.Pass, n ast.Node, testV return true }) } else if ident, ok := callExpr.Args[1].(*ast.Ident); ok { + // Case 2: Direct function identifier: t.Run("name", myFunc) foundFunc := false for _, file := range pass.Files { for _, decl := range file.Decls { @@ -104,6 +110,9 @@ func (a *parallelAnalyzer) analyzeTestRun(pass *analysis.Pass, n ast.Node, testV if !foundFunc { analysis.hasParallel = false } + } else if builderCall, ok := callExpr.Args[1].(*ast.CallExpr); ok { + // Case 3: Function call that returns a function: t.Run("name", builder()) + analysis.hasParallel = a.checkBuilderFunctionForParallel(pass, builderCall) } } @@ -126,6 +135,12 @@ func (a *parallelAnalyzer) analyzeTestFunction(pass *analysis.Pass, funcDecl *as for _, l := range funcDecl.Body.List { switch v := l.(type) { + case *ast.DeferStmt: + if a.checkCleanup { + analysis.funcHasDeferStatement = true + analysis.deferStatements = append(analysis.deferStatements, v) + } + case *ast.ExprStmt: ast.Inspect(v, func(n ast.Node) bool { if !analysis.funcHasParallelMethod { @@ -211,6 +226,89 @@ func (a *parallelAnalyzer) analyzeTestFunction(pass *analysis.Pass, funcDecl *as } } } + + if a.checkCleanup && analysis.funcHasParallelMethod && analysis.funcHasDeferStatement { + for _, deferStmt := range analysis.deferStatements { + pass.Reportf(deferStmt.Pos(), "Function %s uses defer with t.Parallel, use t.Cleanup instead to ensure cleanup runs after parallel subtests complete", funcDecl.Name.Name) + } + } +} + +// checkBuilderFunctionForParallel analyzes a function call that returns a test function +// to see if the returned function contains t.Parallel() +func (a *parallelAnalyzer) checkBuilderFunctionForParallel(pass *analysis.Pass, builderCall *ast.CallExpr) bool { + // Get the name of the builder function being called + var builderFuncName string + switch fun := builderCall.Fun.(type) { + case *ast.Ident: + builderFuncName = fun.Name + case *ast.SelectorExpr: + // Handle method calls like obj.Builder() + builderFuncName = fun.Sel.Name + default: + return false + } + + if builderFuncName == "" { + return false + } + + // Find the builder function declaration + for _, file := range pass.Files { + for _, decl := range file.Decls { + funcDecl, ok := decl.(*ast.FuncDecl) + if !ok || funcDecl.Name.Name != builderFuncName { + continue + } + + // Found the builder function, analyze it and return immediately + hasParallel := false + ast.Inspect(funcDecl, func(n ast.Node) bool { + // Look for return statements + returnStmt, ok := n.(*ast.ReturnStmt) + if !ok || len(returnStmt.Results) == 0 { + return true + } + + // Check if the return value is a function literal + for _, result := range returnStmt.Results { + if funcLit, ok := result.(*ast.FuncLit); ok { + // Get the parameter name from the returned function + var paramName string + if funcLit.Type != nil && funcLit.Type.Params != nil && len(funcLit.Type.Params.List) > 0 { + param := funcLit.Type.Params.List[0] + if len(param.Names) > 0 { + paramName = param.Names[0].Name + } + } + + // Inspect the returned function for t.Parallel() + if paramName != "" { + ast.Inspect(funcLit, func(p ast.Node) bool { + if methodParallelIsCalledInTestFunction(p, paramName) { + hasParallel = true + return false + } + return true + }) + + // Exit inspection immediately if we found t.Parallel() + if hasParallel { + return false + } + } + } + } + // Continue to next return statement if t.Parallel() not found yet + return true + }) + + // Return immediately after processing the matching function + return hasParallel + } + } + + return false } func (a *parallelAnalyzer) run(pass *analysis.Pass) (interface{}, error) { diff --git a/vendor/github.com/ldez/exptostd/.golangci.yml b/vendor/github.com/ldez/exptostd/.golangci.yml index e45135c60..2675c2863 100644 --- a/vendor/github.com/ldez/exptostd/.golangci.yml +++ b/vendor/github.com/ldez/exptostd/.golangci.yml @@ -27,6 +27,7 @@ linters: - testpackage - tparallel - varnamelen + - wsl # deprecated settings: depguard: rules: diff --git a/vendor/github.com/ldez/exptostd/exptostd.go b/vendor/github.com/ldez/exptostd/exptostd.go index 036f9236b..aa5dc5ada 100644 --- a/vendor/github.com/ldez/exptostd/exptostd.go +++ b/vendor/github.com/ldez/exptostd/exptostd.go @@ -267,46 +267,54 @@ func (a *analyzer) detectPackageUsage(pass *analysis.Pass, } func (a *analyzer) detectConstraintsUsage(pass *analysis.Pass, expr ast.Expr, result *Result, goVersion int) { - selExpr, ok := expr.(*ast.SelectorExpr) - if !ok { - return - } - - ident, ok := selExpr.X.(*ast.Ident) - if !ok { - return - } + switch selExpr := expr.(type) { + case *ast.SelectorExpr: + ident, ok := selExpr.X.(*ast.Ident) + if !ok { + return + } - if !isPackageUsed(pass, ident, pkgExpConstraints) { - return - } + if !isPackageUsed(pass, ident, pkgExpConstraints) { + return + } - rp, ok := a.constraintsPkgReplacements[selExpr.Sel.Name] - if !ok { - result.shouldKeepImport = true - return - } + rp, ok := a.constraintsPkgReplacements[selExpr.Sel.Name] + if !ok { + result.shouldKeepImport = true + return + } - if !a.skipGoVersionDetection && rp.MinGo > goVersion { - result.shouldKeepImport = true - return - } + if !a.skipGoVersionDetection && rp.MinGo > goVersion { + result.shouldKeepImport = true + return + } - diagnostic := analysis.Diagnostic{ - Pos: selExpr.Pos(), - Message: fmt.Sprintf("%s.%s can be replaced by %s", pkgExpConstraints, selExpr.Sel.Name, rp.Text), - } + diagnostic := analysis.Diagnostic{ + Pos: selExpr.Pos(), + Message: fmt.Sprintf("%s.%s can be replaced by %s", pkgExpConstraints, selExpr.Sel.Name, rp.Text), + } - if rp.Suggested != nil { - fix, err := rp.Suggested(selExpr) - if err != nil { - diagnostic.Message = fmt.Sprintf("Suggested fix error: %v", err) - } else { - diagnostic.SuggestedFixes = append(diagnostic.SuggestedFixes, fix) + if rp.Suggested != nil { + fix, err := rp.Suggested(selExpr) + if err != nil { + diagnostic.Message = fmt.Sprintf("Suggested fix error: %v", err) + } else { + diagnostic.SuggestedFixes = append(diagnostic.SuggestedFixes, fix) + } } - } - pass.Report(diagnostic) + pass.Report(diagnostic) + + case *ast.BinaryExpr: + a.detectConstraintsUsage(pass, selExpr.X, result, goVersion) + a.detectConstraintsUsage(pass, selExpr.Y, result, goVersion) + + case *ast.UnaryExpr: + a.detectConstraintsUsage(pass, selExpr.X, result, goVersion) + + default: + return + } } func (a *analyzer) suggestReplaceImport(pass *analysis.Pass, imports map[string]*ast.ImportSpec, shouldKeep bool, importPath, stdPackage string) { @@ -320,7 +328,7 @@ func (a *analyzer) suggestReplaceImport(pass *analysis.Pass, imports map[string] pass.Report(analysis.Diagnostic{ Pos: imp.Pos(), End: imp.End(), - Message: fmt.Sprintf("Import statement '%s' can be replaced by '%s'", src, stdPackage), + Message: fmt.Sprintf("Import statement '%s' may be replaced by '%s'", src, stdPackage), SuggestedFixes: []analysis.SuggestedFix{{ TextEdits: []analysis.TextEdit{{ Pos: imp.Path.Pos(), @@ -365,7 +373,7 @@ func suggestedFixForKeysOrValues(callExpr *ast.CallExpr) (analysis.SuggestedFix, Fun: &ast.Ident{Name: "make"}, Args: []ast.Expr{ &ast.ArrayType{ - Elt: &ast.Ident{Name: "T"}, // TODO(ldez) improve the type detection. + Elt: &ast.Ident{Name: "FIXME"}, // TODO(ldez) improve the type detection. }, &ast.BasicLit{Kind: token.INT, Value: "0"}, &ast.CallExpr{ diff --git a/vendor/github.com/ldez/gomoddirectives/.golangci.yml b/vendor/github.com/ldez/gomoddirectives/.golangci.yml index 7f2566656..8eb11ff01 100644 --- a/vendor/github.com/ldez/gomoddirectives/.golangci.yml +++ b/vendor/github.com/ldez/gomoddirectives/.golangci.yml @@ -1,100 +1,100 @@ +version: "2" + +formatters: + enable: + - gci + - gofumpt + settings: + gofumpt: + extra-rules: true + linters: - enable-all: true + default: all disable: - - exportloopref # deprecated - - sqlclosecheck # not relevant (SQL) - - rowserrcheck # not relevant (SQL) + - bodyclose - cyclop # duplicate of gocyclo - - lll - dupl - - prealloc - - bodyclose - - wsl - - nlreturn - - mnd - - testpackage - - paralleltest - - tparallel - err113 - - wrapcheck - exhaustive - exhaustruct + - lll + - mnd + - nlreturn + - paralleltest + - prealloc + - rowserrcheck # not relevant (SQL) + - sqlclosecheck # not relevant (SQL) + - testpackage + - tparallel - varnamelen + - wrapcheck + - wsl # deprecated -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment - gocyclo: - min-complexity: 12 - goconst: - min-len: 3 - min-occurrences: 3 - misspell: - locale: US - gofumpt: - extra-rules: true - depguard: - rules: - main: - deny: - - pkg: "github.com/instana/testify" - desc: not allowed - - pkg: "github.com/pkg/errors" - desc: Should be replaced by standard lib errors package - godox: - keywords: - - FIXME - gocritic: - enabled-tags: - - diagnostic - - style - - performance - disabled-checks: - - sloppyReassign - - rangeValCopy - - octalLiteral - - paramTypeCombine # already handle by gofumpt.extra-rules - settings: - hugeParam: - sizeThreshold: 100 - forbidigo: - forbid: - - '^print(ln)?$' - - '^fmt\.Print(f|ln)?$' - - '^panic$' - - '^spew\.Print(f|ln)?$' - - '^spew\.Dump$' - tagliatelle: - case: + settings: + depguard: rules: - json: pascal + main: + deny: + - pkg: github.com/instana/testify + desc: not allowed + - pkg: github.com/pkg/errors + desc: Should be replaced by standard lib errors package + forbidigo: + forbid: + - pattern: ^print(ln)?$ + - pattern: ^fmt\.Print(f|ln)?$ + - pattern: ^panic$ + - pattern: ^spew\.Print(f|ln)?$ + - pattern: ^spew\.Dump$ + funlen: + lines: -1 + goconst: + min-len: 3 + min-occurrences: 3 + gocritic: + disabled-checks: + - sloppyReassign + - rangeValCopy + - octalLiteral + - paramTypeCombine # already handle by gofumpt.extra-rules + enabled-tags: + - diagnostic + - style + - performance + settings: + hugeParam: + sizeThreshold: 100 + gocyclo: + min-complexity: 12 + godox: + keywords: + - FIXME + govet: + disable: + - fieldalignment + enable-all: true + misspell: + locale: US + tagliatelle: + case: + rules: + json: pascal + + exclusions: + warn-unused: true + presets: + - comments + rules: + - linters: + - funlen + - goconst + - maintidx + path: (.+)_test.go + - linters: + - forbidigo + path: cmd/gomoddirectives/gomoddirectives.go + text: use of `fmt.Println` forbidden issues: - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 - exclude: [ - 'package-comments: should have a package comment' - ] - exclude-rules: - - path: "(.+)_test.go" - linters: - - funlen - - goconst - - maintidx - - path: cmd/gomoddirectives/gomoddirectives.go - linters: - - forbidigo - text: 'use of `fmt.Println` forbidden' - -output: - show-stats: true - sort-results: true - sort-order: - - linter - - file - -run: - timeout: 2m diff --git a/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go b/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go index 857d22f9b..7e3df677c 100644 --- a/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go +++ b/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go @@ -14,17 +14,18 @@ import ( ) const ( - reasonRetract = "a comment is mandatory to explain why the version has been retracted" reasonExclude = "exclude directive is not allowed" - reasonToolchain = "toolchain directive is not allowed" - reasonToolchainPattern = "toolchain directive (%s) doesn't match the pattern '%s'" - reasonTool = "tool directive is not allowed" reasonGoDebug = "godebug directive is not allowed" reasonGoVersion = "go directive (%s) doesn't match the pattern '%s'" - reasonReplaceLocal = "local replacement are not allowed" + reasonIgnore = "ignore directive is not allowed" reasonReplace = "replacement are not allowed" - reasonReplaceIdentical = "the original module and the replacement are identical" reasonReplaceDuplicate = "multiple replacement of the same module" + reasonReplaceIdentical = "the original module and the replacement are identical" + reasonReplaceLocal = "local replacement are not allowed" + reasonRetract = "a comment is mandatory to explain why the version has been retracted" + reasonTool = "tool directive is not allowed" + reasonToolchain = "toolchain directive is not allowed" + reasonToolchainPattern = "toolchain directive (%s) doesn't match the pattern '%s'" ) // Result the analysis result. @@ -52,6 +53,7 @@ type Options struct { ReplaceAllowList []string ReplaceAllowLocal bool ExcludeForbidden bool + IgnoreForbidden bool RetractAllowNoExplanation bool ToolchainForbidden bool ToolchainPattern *regexp.Regexp @@ -68,6 +70,7 @@ func AnalyzePass(pass *analysis.Pass, opts Options) ([]Result, error) { } goMod := info[0].GoMod + if pass.Module != nil && pass.Module.Path != "" { for _, m := range info { if m.Path == pass.Module.Path { @@ -101,6 +104,7 @@ func AnalyzeFile(file *modfile.File, opts Options) []Result { checkRetractDirectives, checkExcludeDirectives, checkToolDirectives, + checkIgnoreDirectives, checkReplaceDirectives, checkToolchainDirective, checkGoDebugDirectives, @@ -175,6 +179,20 @@ func checkExcludeDirectives(file *modfile.File, opts Options) []Result { return results } +func checkIgnoreDirectives(file *modfile.File, opts Options) []Result { + if !opts.IgnoreForbidden { + return nil + } + + var results []Result + + for _, exclude := range file.Ignore { + results = append(results, NewResult(file, exclude.Syntax, reasonIgnore)) + } + + return results +} + func checkToolDirectives(file *modfile.File, opts Options) []Result { if !opts.ToolForbidden { return nil diff --git a/vendor/github.com/ldez/gomoddirectives/readme.md b/vendor/github.com/ldez/gomoddirectives/readme.md index 7d6d2765b..054af4625 100644 --- a/vendor/github.com/ldez/gomoddirectives/readme.md +++ b/vendor/github.com/ldez/gomoddirectives/readme.md @@ -16,43 +16,48 @@ linters: enable: - gomoddirectives -linters-settings: - gomoddirectives: - # Allow local `replace` directives. - # Default: false - replace-local: true - - # List of allowed `replace` directives. - # Default: [] - replace-allow-list: - - launchpad.net/gocheck - # Allow to not explain why the version has been retracted in the `retract` directives. - # Default: false - retract-allow-no-explanation: true - - # Forbid the use of the `exclude` directives. - # Default: false - exclude-forbidden: true - - # Forbid the use of the `toolchain` directive. - # Default: false - toolchain-forbidden: true - - # Defines a pattern to validate `toolchain` directive. - # Default: '' (no match) - toolchain-pattern: 'go1\.22\.\d+$' - - # Forbid the use of the `tool` directives. - # Default: false - tool-forbidden: true - - # Forbid the use of the `godebug` directive. - # Default: false - go-debug-forbidden: true - - # Defines a pattern to validate `go` minimum version directive. - # Default: '' (no match) - go-version-pattern: '1\.\d+(\.0)?$' + settings: + gomoddirectives: + # Allow local `replace` directives. + # Default: false + replace-local: true + + # List of allowed `replace` directives. + # Default: [] + replace-allow-list: + - launchpad.net/gocheck + + # Allow to not explain why the version has been retracted in the `retract` directives. + # Default: false + retract-allow-no-explanation: true + + # Forbid the use of the `exclude` directives. + # Default: false + exclude-forbidden: true + + # Forbid the use of the `ignore` directives (go >= 1.25). + # Default: false + ignore-forbidden: true + + # Forbid the use of the `toolchain` directive. + # Default: false + toolchain-forbidden: true + + # Defines a pattern to validate `toolchain` directive. + # Default: '' (no match) + toolchain-pattern: 'go1\.22\.\d+$' + + # Forbid the use of the `tool` directives. + # Default: false + tool-forbidden: true + + # Forbid the use of the `godebug` directive. + # Default: false + go-debug-forbidden: true + + # Defines a pattern to validate `go` minimum version directive. + # Default: '' (no match) + go-version-pattern: '1\.\d+(\.0)?$' ``` ### As a CLI @@ -68,6 +73,8 @@ Flags: -goversion string Pattern to validate go min version directive -h Show this help. + -ignore + Forbid the use of ignore directives -list value List of allowed replace directives -local @@ -141,6 +148,25 @@ exclude ( ) ``` +### [`ignore`](TODO) directives + +- Ban all `ignore` directives. + +```go +module example.com/foo + +go 1.25 + +require ( + github.com/ldez/grignotin v0.4.1 +) + +ignore ( + ./foo/bar/path + foo/bar +) +``` + ### [`tool`](https://golang.org/ref/mod#go-mod-file-tool) directives - Ban all `tool` directives. diff --git a/vendor/github.com/ldez/grignotin/LICENSE b/vendor/github.com/ldez/grignotin/LICENSE new file mode 100644 index 000000000..79f380e5c --- /dev/null +++ b/vendor/github.com/ldez/grignotin/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 2024 Fernandez Ludovic + + 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/vendor/github.com/ldez/grignotin/goenv/goenv.go b/vendor/github.com/ldez/grignotin/goenv/goenv.go index 1f0c31e4e..58dbb5f8c 100644 --- a/vendor/github.com/ldez/grignotin/goenv/goenv.go +++ b/vendor/github.com/ldez/grignotin/goenv/goenv.go @@ -41,6 +41,7 @@ func Get(ctx context.Context, name ...string) (map[string]string, error) { } v := map[string]string{} + err = json.NewDecoder(bytes.NewBuffer(out)).Decode(&v) if err != nil { return nil, err diff --git a/vendor/github.com/ldez/tagliatelle/.golangci.yml b/vendor/github.com/ldez/tagliatelle/.golangci.yml index 01c76dca9..371822b51 100644 --- a/vendor/github.com/ldez/tagliatelle/.golangci.yml +++ b/vendor/github.com/ldez/tagliatelle/.golangci.yml @@ -1,77 +1,83 @@ +version: "2" + +formatters: + enable: + - gci + - gofumpt + settings: + gofumpt: + extra-rules: true + linters: - enable-all: true + default: all disable: - - exportloopref # deprecated - - sqlclosecheck # not relevant (SQL) - - rowserrcheck # not relevant (SQL) - cyclop # duplicate of gocyclo - - lll - dupl - - wsl - - nlreturn - - mnd - err113 - - wrapcheck + - errchkjson - exhaustive - exhaustruct - - testpackage - - tparallel - - paralleltest - - prealloc - forcetypeassert - - varnamelen + - lll + - mnd - nilnil - - errchkjson + - nlreturn - nonamedreturns + - paralleltest + - prealloc + - rowserrcheck # not relevant (SQL) + - sqlclosecheck # not relevant (SQL) + - testpackage + - tparallel + - varnamelen + - wrapcheck + - wsl # Deprecated + + settings: + depguard: + rules: + main: + deny: + - pkg: github.com/instana/testify + desc: not allowed + - pkg: github.com/pkg/errors + desc: Should be replaced by standard lib errors package + funlen: + lines: -1 + statements: 40 + goconst: + min-len: 5 + min-occurrences: 3 + gocritic: + disabled-checks: + - sloppyReassign + - rangeValCopy + - octalLiteral + - paramTypeCombine # already handle by gofumpt.extra-rules + enabled-tags: + - diagnostic + - style + - performance + settings: + hugeParam: + sizeThreshold: 100 + gocyclo: + min-complexity: 20 + godox: + keywords: + - FIXME + govet: + disable: + - fieldalignment + enable-all: true + misspell: + locale: US -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment - gocyclo: - min-complexity: 20 - goconst: - min-len: 5 - min-occurrences: 3 - misspell: - locale: US - funlen: - lines: -1 - statements: 40 - godox: - keywords: - - FIXME - gofumpt: - extra-rules: true - depguard: - rules: - main: - deny: - - pkg: "github.com/instana/testify" - desc: not allowed - - pkg: "github.com/pkg/errors" - desc: Should be replaced by standard lib errors package - gocritic: - enabled-tags: - - diagnostic - - style - - performance - disabled-checks: - - sloppyReassign - - rangeValCopy - - octalLiteral - - paramTypeCombine # already handle by gofumpt.extra-rules - settings: - hugeParam: - sizeThreshold: 100 + exclusions: + warn-unused: true + presets: + - comments issues: - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 - exclude: - - 'package-comments: should have a package comment' - -run: - timeout: 5m diff --git a/vendor/github.com/ldez/tagliatelle/converter.go b/vendor/github.com/ldez/tagliatelle/converter.go index 6005f5b75..97bcf369c 100644 --- a/vendor/github.com/ldez/tagliatelle/converter.go +++ b/vendor/github.com/ldez/tagliatelle/converter.go @@ -2,6 +2,7 @@ package tagliatelle import ( "fmt" + "maps" "strings" "github.com/ettle/strcase" @@ -63,17 +64,19 @@ func toHeader(s string) string { } func ruleToConverter(rule ExtendedRule) (Converter, error) { + initialismOverrides := maps.Clone(rule.InitialismOverrides) + if rule.ExtraInitialisms { for k, v := range staticcheckInitialisms { - if _, found := rule.InitialismOverrides[k]; found { + if _, found := initialismOverrides[k]; found { continue } - rule.InitialismOverrides[k] = v + initialismOverrides[k] = v } } - caser := strcase.NewCaser(strings.HasPrefix(rule.Case, "go"), rule.InitialismOverrides, nil) + caser := strcase.NewCaser(strings.HasPrefix(rule.Case, "go"), initialismOverrides, nil) switch strings.ToLower(strings.TrimPrefix(rule.Case, "go")) { case "camel": diff --git a/vendor/github.com/ldez/tagliatelle/readme.md b/vendor/github.com/ldez/tagliatelle/readme.md index 52d10304b..77dd416ca 100644 --- a/vendor/github.com/ldez/tagliatelle/readme.md +++ b/vendor/github.com/ldez/tagliatelle/readme.md @@ -99,10 +99,10 @@ type Foo struct { ## What this linter is about -This linter is about validating tags according to rules you define. -The linter also allows to fix tags according to the rules you defined. +This linter is about validating tags according to the rules you define. +The linter also allows you to fix tags according to the rules you defined. -This linter is not intended to validate the fact a tag in valid or not. +This linter is not intended to validate the fact a tag is valid or not. ## How to use the linter @@ -111,100 +111,103 @@ This linter is not intended to validate the fact a tag in valid or not. Define the rules, you want via your [golangci-lint](https://golangci-lint.run) configuration file: ```yaml -linters-settings: - tagliatelle: - # Checks the struct tag name case. - case: - # Defines the association between tag name and case. - # Any struct tag name can be used. - # Supported string cases: - # - `camel` - # - `pascal` - # - `kebab` - # - `snake` - # - `upperSnake` - # - `goCamel` - # - `goPascal` - # - `goKebab` - # - `goSnake` - # - `upper` - # - `lower` - # - `header` - rules: - json: camel - yaml: camel - xml: camel - toml: camel - bson: camel - avro: snake - mapstructure: kebab - env: upperSnake - envconfig: upperSnake - whatever: snake - # Defines the association between tag name and case. - # Important: the `extended-rules` overrides `rules`. - # Default: empty - extended-rules: - json: - # Supported string cases: - # - `camel` - # - `pascal` - # - `kebab` - # - `snake` - # - `upperSnake` - # - `goCamel` - # - `goPascal` - # - `goKebab` - # - `goSnake` - # - `header` - # - `lower` - # - `header` - # - # Required - case: camel - # Adds 'AMQP', 'DB', 'GID', 'RTP', 'SIP', 'TS' to initialisms, - # and removes 'LHS', 'RHS' from initialisms. - # Default: false - extra-initialisms: true - # Defines initialism additions and overrides. - # Default: empty - initialism-overrides: - DB: true # add a new initialism - LHS: false # disable a default initialism. - # ... - # Uses the struct field name to check the name of the struct tag. - # Default: false - use-field-name: true - # The field names to ignore. - # Default: [] - ignored-fields: - - Bar - - Foo - # Overrides the default/root configuration. - # Default: [] - overrides: - - - # The package path (uses `/` only as a separator). - # Required - pkg: foo/bar - # Default: empty or the same as the default/root configuration. - rules: - json: snake - xml: pascal - # Default: empty or the same as the default/root configuration. - extended-rules: - # same options as the base `extended-rules`. - # Default: false (WARNING: it doesn't follow the default/root configuration) - use-field-name: true - # The field names to ignore. - # Default: [] or the same as the default/root configuration. - ignored-fields: - - Bar - - Foo - # Ignore the package (takes precedence over all other configurations). - # Default: false - ignore: true - +linters: + enable: + - tagliatelle + + settings: + tagliatelle: + # Checks the struct tag name case. + case: + # Defines the association between tag name and case. + # Any struct tag name can be used. + # Supported string cases: + # - `camel` + # - `pascal` + # - `kebab` + # - `snake` + # - `upperSnake` + # - `goCamel` + # - `goPascal` + # - `goKebab` + # - `goSnake` + # - `upper` + # - `lower` + # - `header` + rules: + json: camel + yaml: camel + xml: camel + toml: camel + bson: camel + avro: snake + mapstructure: kebab + env: upperSnake + envconfig: upperSnake + whatever: snake + # Defines the association between tag name and case. + # Important: the `extended-rules` overrides `rules`. + # Default: empty + extended-rules: + json: + # Supported string cases: + # - `camel` + # - `pascal` + # - `kebab` + # - `snake` + # - `upperSnake` + # - `goCamel` + # - `goPascal` + # - `goKebab` + # - `goSnake` + # - `header` + # - `lower` + # - `header` + # + # Required + case: camel + # Adds 'AMQP', 'DB', 'GID', 'RTP', 'SIP', 'TS' to initialisms, + # and removes 'LHS', 'RHS' from initialisms. + # Default: false + extra-initialisms: true + # Defines initialism additions and overrides. + # Default: empty + initialism-overrides: + DB: true # add a new initialism + LHS: false # disable a default initialism. + # ... + # Uses the struct field name to check the name of the struct tag. + # Default: false + use-field-name: true + # The field names to ignore. + # Default: [] + ignored-fields: + - Bar + - Foo + # Overrides the default/root configuration. + # Default: [] + overrides: + - + # The package path (uses `/` only as a separator). + # Required + pkg: foo/bar + # Default: empty or the same as the default/root configuration. + rules: + json: snake + xml: pascal + # Default: empty or the same as the default/root configuration. + extended-rules: + # same options as the base `extended-rules`. + # Default: false (WARNING: it doesn't follow the default/root configuration) + use-field-name: true + # The field names to ignore. + # Default: [] or the same as the default/root configuration. + ignored-fields: + - Bar + - Foo + # Ignore the package (takes precedence over all other configurations). + # Default: false + ignore: true ``` #### Examples @@ -212,50 +215,53 @@ linters-settings: Overrides case rules for the package `foo/bar`: ```yaml -linters-settings: - tagliatelle: - case: - rules: - json: camel - yaml: camel - xml: camel - overrides: - - pkg: foo/bar - rules: - json: snake - xml: pascal +linters: + settings: + tagliatelle: + case: + rules: + json: camel + yaml: camel + xml: camel + overrides: + - pkg: foo/bar + rules: + json: snake + xml: pascal ``` Ignore fields inside the package `foo/bar`: ```yaml -linters-settings: - tagliatelle: - case: - rules: - json: camel - yaml: camel - xml: camel - overrides: - - pkg: foo/bar - ignored-fields: - - Bar - - Foo +linters: + settings: + tagliatelle: + case: + rules: + json: camel + yaml: camel + xml: camel + overrides: + - pkg: foo/bar + ignored-fields: + - Bar + - Foo ``` Ignore the package `foo/bar`: ```yaml -linters-settings: - tagliatelle: - case: - rules: - json: camel - yaml: camel - xml: camel - overrides: - - pkg: foo/bar - ignore: true +linters: + settings: + tagliatelle: + case: + rules: + json: camel + yaml: camel + xml: camel + overrides: + - pkg: foo/bar + ignore: true ``` More information here https://golangci-lint.run/usage/linters/#tagliatelle @@ -272,7 +278,7 @@ then launch it manually. ## Rules -Here are the default rules for the well known and used tags, when using tagliatelle as a binary or [golangci-lint linter](https://golangci-lint.run/usage/linters/#tagliatelle): +Here are the default rules for the well-known and used tags, when using tagliatelle as a binary or [golangci-lint linter](https://golangci-lint.run/usage/linters/#tagliatelle): - `json`: `camel` - `yaml`: `camel` @@ -292,19 +298,20 @@ You can add your own tag, for example `whatever` and tells the linter you want t This option is only available via [golangci-lint](https://golangci-lint.run). ```yaml -linters-settings: - tagliatelle: - # Check the struck tag name case. - case: - rules: - # Any struct tag type can be used. - # Support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower` - json: camel - yaml: camel - xml: camel - toml: camel - whatever: kebab - # Use the struct field name to check the name of the struct tag. - # Default: false - use-field-name: true +linters: + settings: + tagliatelle: + # Check the struck tag name case. + case: + rules: + # Any struct tag type can be used. + # Support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower` + json: camel + yaml: camel + xml: camel + toml: camel + whatever: kebab + # Use the struct field name to check the name of the struct tag. + # Default: false + use-field-name: true ``` diff --git a/vendor/github.com/ldez/tagliatelle/tagliatelle.go b/vendor/github.com/ldez/tagliatelle/tagliatelle.go index 99c7da2d0..ccd1b63e6 100644 --- a/vendor/github.com/ldez/tagliatelle/tagliatelle.go +++ b/vendor/github.com/ldez/tagliatelle/tagliatelle.go @@ -22,12 +22,14 @@ import ( // Config the tagliatelle configuration. type Config struct { Base + Overrides []Overrides } // Overrides applies configuration overrides by package. type Overrides struct { Base + Package string } @@ -74,6 +76,7 @@ func run(pass *analysis.Pass, config Config) (any, error) { } cfg := config.Base + if pass.Module != nil { radixTree := createRadixTree(config, pass.Module.Path) _, cfg, _ = radixTree.Root().LongestPrefix([]byte(pass.Pkg.Path())) @@ -160,7 +163,7 @@ func report(pass *analysis.Pass, config Base, key, convName, fieldName string, n // This is an exception because of a bug. // https://github.com/ldez/tagliatelle/issues/8 // For now, tagliatelle should try to remain neutral in terms of format. - if hasTagFlag(flags, "inline") { + if slices.Contains(flags, "inline") { // skip for inline children (no name to lint) return } @@ -187,6 +190,7 @@ func report(pass *analysis.Pass, config Base, key, convName, fieldName string, n func getFieldName(field *ast.Field) (string, error) { var name string + for _, n := range field.Names { if n.Name != "" { name = n.Name @@ -231,16 +235,6 @@ func lookupTagValue(tag *ast.BasicLit, key string) (name string, flags []string, return values[0], values[1:], true } -func hasTagFlag(flags []string, query string) bool { - for _, flag := range flags { - if flag == query { - return true - } - } - - return false -} - func createRadixTree(config Config, modPath string) *iradix.Tree[Base] { r := iradix.New[Base]() @@ -261,7 +255,7 @@ func createRadixTree(config Config, modPath string) *iradix.Tree[Base] { Ignore: override.Ignore, } - // If there is an override the base configuration is ignored. + // If there is an override, the base configuration is ignored. if len(override.IgnoredFields) == 0 { c.IgnoredFields = append(c.IgnoredFields, config.IgnoredFields...) } else { diff --git a/vendor/github.com/ldez/usetesting/readme.md b/vendor/github.com/ldez/usetesting/readme.md index 0da8c8d11..c4dd3daa1 100644 --- a/vendor/github.com/ldez/usetesting/readme.md +++ b/vendor/github.com/ldez/usetesting/readme.md @@ -40,13 +40,13 @@ linters: # Enable/disable `context.Background()` detections. # Disabled if Go < 1.24. - # Default: true - context-background: false + # Default: false + context-background: true # Enable/disable `context.TODO()` detections. # Disabled if Go < 1.24. - # Default: true - context-todo: false + # Default: false + context-todo: true ``` ### As a CLI diff --git a/vendor/github.com/ldez/usetesting/usetesting.go b/vendor/github.com/ldez/usetesting/usetesting.go index 6ff18f9af..ecd113b95 100644 --- a/vendor/github.com/ldez/usetesting/usetesting.go +++ b/vendor/github.com/ldez/usetesting/usetesting.go @@ -76,8 +76,8 @@ func NewAnalyzer() *analysis.Analyzer { Run: l.run, } - a.Flags.BoolVar(&l.contextBackground, "contextbackground", true, "Enable/disable context.Background() detections") - a.Flags.BoolVar(&l.contextTodo, "contexttodo", true, "Enable/disable context.TODO() detections") + a.Flags.BoolVar(&l.contextBackground, "contextbackground", false, "Enable/disable context.Background() detections") + a.Flags.BoolVar(&l.contextTodo, "contexttodo", false, "Enable/disable context.TODO() detections") a.Flags.BoolVar(&l.osChdir, "oschdir", true, "Enable/disable os.Chdir() detections") a.Flags.BoolVar(&l.osMkdirTemp, "osmkdirtemp", true, "Enable/disable os.MkdirTemp() detections") a.Flags.BoolVar(&l.osSetenv, "ossetenv", false, "Enable/disable os.Setenv() detections") diff --git a/vendor/github.com/manuelarte/embeddedstructfieldcheck/LICENSE b/vendor/github.com/manuelarte/embeddedstructfieldcheck/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/github.com/manuelarte/embeddedstructfieldcheck/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/vendor/github.com/manuelarte/embeddedstructfieldcheck/analyzer/analyzer.go b/vendor/github.com/manuelarte/embeddedstructfieldcheck/analyzer/analyzer.go new file mode 100644 index 000000000..dc137d71e --- /dev/null +++ b/vendor/github.com/manuelarte/embeddedstructfieldcheck/analyzer/analyzer.go @@ -0,0 +1,64 @@ +package analyzer + +import ( + "go/ast" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" + + "github.com/manuelarte/embeddedstructfieldcheck/internal" +) + +const ( + EmptyLineCheck = "empty-line" + ForbidMutexCheck = "forbid-mutex" +) + +func NewAnalyzer() *analysis.Analyzer { + var ( + emptyLine bool + forbidMutex bool + ) + + a := &analysis.Analyzer{ + Name: "embeddedstructfieldcheck", + Doc: "Embedded types should be at the top of the field list of a struct, " + + "and there must be an empty line separating embedded fields from regular fields.", + URL: "https://github.com/manuelarte/embeddedstructfieldcheck", + Run: func(pass *analysis.Pass) (any, error) { + run(pass, emptyLine, forbidMutex) + + //nolint:nilnil // impossible case. + return nil, nil + }, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } + + a.Flags.BoolVar(&emptyLine, EmptyLineCheck, true, + "Checks that there is an empty space between the embedded fields and regular fields.") + a.Flags.BoolVar(&forbidMutex, ForbidMutexCheck, false, + "Checks that sync.Mutex and sync.RWMutex are not used as an embedded fields.") + + return a +} + +func run(pass *analysis.Pass, emptyLine, forbidMutex bool) { + insp, found := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + if !found { + return + } + + nodeFilter := []ast.Node{ + (*ast.StructType)(nil), + } + + insp.Preorder(nodeFilter, func(n ast.Node) { + node, ok := n.(*ast.StructType) + if !ok { + return + } + + internal.Analyze(pass, node, emptyLine, forbidMutex) + }) +} diff --git a/vendor/github.com/manuelarte/embeddedstructfieldcheck/internal/diag.go b/vendor/github.com/manuelarte/embeddedstructfieldcheck/internal/diag.go new file mode 100644 index 000000000..337b0dff7 --- /dev/null +++ b/vendor/github.com/manuelarte/embeddedstructfieldcheck/internal/diag.go @@ -0,0 +1,48 @@ +package internal + +import ( + "fmt" + "go/ast" + + "golang.org/x/tools/go/analysis" +) + +func NewMisplacedEmbeddedFieldDiag(embeddedField *ast.Field) analysis.Diagnostic { + return analysis.Diagnostic{ + Pos: embeddedField.Pos(), + Message: "embedded fields should be listed before regular fields", + } +} + +func NewMissingSpaceDiag( + lastEmbeddedField *ast.Field, + firstRegularField *ast.Field, +) analysis.Diagnostic { + suggestedPos := firstRegularField.Pos() + if firstRegularField.Doc != nil { + suggestedPos = firstRegularField.Doc.Pos() + } + + return analysis.Diagnostic{ + Pos: lastEmbeddedField.Pos(), + Message: "there must be an empty line separating embedded fields from regular fields", + SuggestedFixes: []analysis.SuggestedFix{ + { + Message: "adding extra line separating embedded fields from regular fields", + TextEdits: []analysis.TextEdit{ + { + Pos: suggestedPos, + NewText: []byte("\n\n"), + }, + }, + }, + }, + } +} + +func NewForbiddenEmbeddedFieldDiag(forbidField *ast.SelectorExpr) analysis.Diagnostic { + return analysis.Diagnostic{ + Pos: forbidField.Pos(), + Message: fmt.Sprintf("%s.%s should not be embedded", forbidField.X, forbidField.Sel.Name), + } +} diff --git a/vendor/github.com/manuelarte/embeddedstructfieldcheck/internal/structanalyzer.go b/vendor/github.com/manuelarte/embeddedstructfieldcheck/internal/structanalyzer.go new file mode 100644 index 000000000..2df53692a --- /dev/null +++ b/vendor/github.com/manuelarte/embeddedstructfieldcheck/internal/structanalyzer.go @@ -0,0 +1,88 @@ +package internal + +import ( + "go/ast" + + "golang.org/x/tools/go/analysis" +) + +func Analyze(pass *analysis.Pass, st *ast.StructType, emptyLine, forbidMutex bool) { + var firstEmbeddedField *ast.Field + + var lastEmbeddedField *ast.Field + + var firstNotEmbeddedField *ast.Field + + for _, field := range st.Fields.List { + if isFieldEmbedded(field) { + checkForbiddenEmbeddedField(pass, field, forbidMutex) + + if firstEmbeddedField == nil { + firstEmbeddedField = field + } + + if lastEmbeddedField == nil || lastEmbeddedField.Pos() < field.Pos() { + lastEmbeddedField = field + } + + if firstNotEmbeddedField != nil && firstNotEmbeddedField.Pos() < field.Pos() { + pass.Report(NewMisplacedEmbeddedFieldDiag(field)) + return + } + } else if firstNotEmbeddedField == nil { + firstNotEmbeddedField = field + } + } + + if emptyLine { + checkMissingSpace(pass, lastEmbeddedField, firstNotEmbeddedField) + } +} + +func checkForbiddenEmbeddedField(pass *analysis.Pass, field *ast.Field, forbidMutex bool) { + if !forbidMutex { + return + } + + switch e := field.Type.(type) { + case *ast.StarExpr: + if se, isSelectorExpr := e.X.(*ast.SelectorExpr); isSelectorExpr { + reportSyncMutex(pass, se) + } + + case *ast.SelectorExpr: + reportSyncMutex(pass, e) + } +} + +func checkMissingSpace(pass *analysis.Pass, lastEmbeddedField, firstNotEmbeddedField *ast.Field) { + if lastEmbeddedField != nil && firstNotEmbeddedField != nil { + // check for missing space + // TODO: isn't it easy to remove as many lines as comments between last embedded type and first not embedded + line := pass.Fset.Position(lastEmbeddedField.End()).Line + + nextLine := pass.Fset.Position(firstNotEmbeddedField.Pos()).Line + if firstNotEmbeddedField.Doc != nil { + nextLine = pass.Fset.Position(firstNotEmbeddedField.Doc.Pos()).Line + } + + if nextLine != line+2 { + pass.Report(NewMissingSpaceDiag(lastEmbeddedField, firstNotEmbeddedField)) + } + } +} + +func isFieldEmbedded(field *ast.Field) bool { + return len(field.Names) == 0 +} + +func reportSyncMutex(pass *analysis.Pass, se *ast.SelectorExpr) { + packageName, isIdent := se.X.(*ast.Ident) + if !isIdent { + return + } + + if packageName.Name == "sync" && (se.Sel.Name == "Mutex" || se.Sel.Name == "RWMutex") { + pass.Report(NewForbiddenEmbeddedFieldDiag(se)) + } +} diff --git a/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go b/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go index f8aabbfcf..c3112107d 100644 --- a/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go +++ b/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go @@ -7,13 +7,13 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" - "github.com/manuelarte/funcorder/internal/features" - "github.com/manuelarte/funcorder/internal/fileprocessor" + "github.com/manuelarte/funcorder/internal" ) const ( ConstructorCheckName = "constructor" StructMethodCheckName = "struct-method" + AlphabeticalCheckName = "alphabetical" ) func NewAnalyzer() *analysis.Analyzer { @@ -22,15 +22,17 @@ func NewAnalyzer() *analysis.Analyzer { a := &analysis.Analyzer{ Name: "funcorder", Doc: "checks the order of functions, methods, and constructors", + URL: "https://github.com/manuelarte/funcorder", Run: f.run, Requires: []*analysis.Analyzer{inspect.Analyzer}, } a.Flags.BoolVar(&f.constructorCheck, ConstructorCheckName, true, - "Enable/disable feature to check constructors are placed after struct declaration") + "Checks that constructors are placed after the structure declaration.") a.Flags.BoolVar(&f.structMethodCheck, StructMethodCheckName, true, - "Enable/disable feature to check whether the exported struct's methods "+ - "are placed before the non-exported") + "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.") return a } @@ -38,19 +40,24 @@ func NewAnalyzer() *analysis.Analyzer { type funcorder struct { constructorCheck bool structMethodCheck bool + alphabeticalCheck bool } func (f *funcorder) run(pass *analysis.Pass) (any, error) { - var enabledCheckers features.Feature + var enabledCheckers internal.Feature if f.constructorCheck { - enabledCheckers |= features.ConstructorCheck + enabledCheckers.Enable(internal.ConstructorCheck) } if f.structMethodCheck { - enabledCheckers |= features.StructMethodCheck + enabledCheckers.Enable(internal.StructMethodCheck) } - fp := fileprocessor.NewFileProcessor(enabledCheckers) + if f.alphabeticalCheck { + enabledCheckers.Enable(internal.AlphabeticalCheck) + } + + fp := internal.NewFileProcessor(pass.Fset, enabledCheckers) insp, found := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) if !found { diff --git a/vendor/github.com/manuelarte/funcorder/internal/astutils.go b/vendor/github.com/manuelarte/funcorder/internal/astutils.go new file mode 100644 index 000000000..af7fa8c81 --- /dev/null +++ b/vendor/github.com/manuelarte/funcorder/internal/astutils.go @@ -0,0 +1,93 @@ +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/vendor/github.com/manuelarte/funcorder/internal/astutils/utils.go b/vendor/github.com/manuelarte/funcorder/internal/astutils/utils.go deleted file mode 100644 index 788399765..000000000 --- a/vendor/github.com/manuelarte/funcorder/internal/astutils/utils.go +++ /dev/null @@ -1,54 +0,0 @@ -package astutils - -import ( - "go/ast" - "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 - } -} diff --git a/vendor/github.com/manuelarte/funcorder/internal/diag.go b/vendor/github.com/manuelarte/funcorder/internal/diag.go new file mode 100644 index 000000000..faf2ffdd1 --- /dev/null +++ b/vendor/github.com/manuelarte/funcorder/internal/diag.go @@ -0,0 +1,69 @@ +package internal + +import ( + "fmt" + "go/ast" + + "golang.org/x/tools/go/analysis" +) + +func NewConstructorNotAfterStructType(structSpec *ast.TypeSpec, constructor *ast.FuncDecl) analysis.Diagnostic { + return 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( + structSpec *ast.TypeSpec, + constructor *ast.FuncDecl, + method *ast.FuncDecl, +) analysis.Diagnostic { + return 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( + structSpec *ast.TypeSpec, + constructorNotSorted *ast.FuncDecl, + otherConstructorNotSorted *ast.FuncDecl, +) analysis.Diagnostic { + return 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( + structSpec *ast.TypeSpec, + privateMethod *ast.FuncDecl, + publicMethod *ast.FuncDecl, +) analysis.Diagnostic { + return 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( + structSpec *ast.TypeSpec, + method *ast.FuncDecl, + otherMethod *ast.FuncDecl, +) analysis.Diagnostic { + return 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), + } +} diff --git a/vendor/github.com/manuelarte/funcorder/internal/diag/diag.go b/vendor/github.com/manuelarte/funcorder/internal/diag/diag.go deleted file mode 100644 index 3a5012b1c..000000000 --- a/vendor/github.com/manuelarte/funcorder/internal/diag/diag.go +++ /dev/null @@ -1,40 +0,0 @@ -package diag - -import ( - "fmt" - "go/ast" - - "golang.org/x/tools/go/analysis" -) - -func NewConstructorNotAfterStructType(structSpec *ast.TypeSpec, constructor *ast.FuncDecl) analysis.Diagnostic { - return analysis.Diagnostic{ - Pos: constructor.Pos(), - Message: fmt.Sprintf("function %q for struct %q should be placed after the struct declaration", - constructor.Name, structSpec.Name), - } -} - -func NewConstructorNotBeforeStructMethod( - structSpec *ast.TypeSpec, - constructor *ast.FuncDecl, - method *ast.FuncDecl, -) analysis.Diagnostic { - return analysis.Diagnostic{ - Pos: constructor.Pos(), - Message: fmt.Sprintf("constructor %q for struct %q should be placed before struct method %q", - constructor.Name, structSpec.Name, method.Name), - } -} - -func NewNonExportedMethodBeforeExportedForStruct( - structSpec *ast.TypeSpec, - privateMethod *ast.FuncDecl, - publicMethod *ast.FuncDecl, -) analysis.Diagnostic { - return analysis.Diagnostic{ - Pos: privateMethod.Pos(), - Message: fmt.Sprintf("unexported method %q for struct %q should be placed after the exported method %q", - privateMethod.Name, structSpec.Name, publicMethod.Name), - } -} diff --git a/vendor/github.com/manuelarte/funcorder/internal/features.go b/vendor/github.com/manuelarte/funcorder/internal/features.go new file mode 100644 index 000000000..55d5caba3 --- /dev/null +++ b/vendor/github.com/manuelarte/funcorder/internal/features.go @@ -0,0 +1,17 @@ +package internal + +const ( + ConstructorCheck Feature = 1 << iota + StructMethodCheck + AlphabeticalCheck +) + +type Feature uint8 + +func (f *Feature) Enable(other Feature) { + *f |= other +} + +func (f *Feature) IsEnabled(other Feature) bool { + return *f&other != 0 +} diff --git a/vendor/github.com/manuelarte/funcorder/internal/features/features.go b/vendor/github.com/manuelarte/funcorder/internal/features/features.go deleted file mode 100644 index 244ea64b7..000000000 --- a/vendor/github.com/manuelarte/funcorder/internal/features/features.go +++ /dev/null @@ -1,12 +0,0 @@ -package features - -const ( - ConstructorCheck Feature = 1 << iota - StructMethodCheck -) - -type Feature uint8 - -func (c Feature) IsEnabled(other Feature) bool { - return c&other != 0 -} diff --git a/vendor/github.com/manuelarte/funcorder/internal/fileprocessor/file_processor.go b/vendor/github.com/manuelarte/funcorder/internal/file_processor.go similarity index 64% rename from vendor/github.com/manuelarte/funcorder/internal/fileprocessor/file_processor.go rename to vendor/github.com/manuelarte/funcorder/internal/file_processor.go index 8a2fb0e35..88ae00f2e 100644 --- a/vendor/github.com/manuelarte/funcorder/internal/fileprocessor/file_processor.go +++ b/vendor/github.com/manuelarte/funcorder/internal/file_processor.go @@ -1,25 +1,24 @@ -package fileprocessor +package internal import ( "go/ast" + "go/token" "golang.org/x/tools/go/analysis" - - "github.com/manuelarte/funcorder/internal/astutils" - "github.com/manuelarte/funcorder/internal/features" - "github.com/manuelarte/funcorder/internal/models" ) // FileProcessor Holder to store all the functions that are potential to be constructors and all the structs. type FileProcessor struct { - structs map[string]*models.StructHolder - features features.Feature + fset *token.FileSet + structs map[string]*StructHolder + features Feature } // NewFileProcessor creates a new file processor. -func NewFileProcessor(checkers features.Feature) *FileProcessor { +func NewFileProcessor(fset *token.FileSet, checkers Feature) *FileProcessor { return &FileProcessor{ - structs: make(map[string]*models.StructHolder), + fset: fset, + structs: make(map[string]*StructHolder), features: checkers, } } @@ -38,27 +37,17 @@ func (fp *FileProcessor) Analyze() []analysis.Diagnostic { return reports } -func (fp *FileProcessor) addConstructor(sc models.StructConstructor) { - sh := fp.getOrCreate(sc.GetStructReturn().Name) - sh.AddConstructor(sc.GetConstructor()) -} - -func (fp *FileProcessor) addMethod(st string, n *ast.FuncDecl) { - sh := fp.getOrCreate(st) - sh.AddMethod(n) -} - func (fp *FileProcessor) NewFileNode(_ *ast.File) { - fp.structs = make(map[string]*models.StructHolder) + fp.structs = make(map[string]*StructHolder) } func (fp *FileProcessor) NewFuncDecl(n *ast.FuncDecl) { - if sc, ok := models.NewStructConstructor(n); ok { + if sc, ok := NewStructConstructor(n); ok { fp.addConstructor(sc) return } - if st, ok := astutils.FuncIsMethod(n); ok { + if st, ok := FuncIsMethod(n); ok { fp.addMethod(st.Name, n) } } @@ -68,12 +57,25 @@ func (fp *FileProcessor) NewTypeSpec(n *ast.TypeSpec) { sh.Struct = n } -func (fp *FileProcessor) getOrCreate(structName string) *models.StructHolder { +func (fp *FileProcessor) addConstructor(sc StructConstructor) { + sh := fp.getOrCreate(sc.GetStructReturn().Name) + sh.AddConstructor(sc.GetConstructor()) +} + +func (fp *FileProcessor) addMethod(st string, n *ast.FuncDecl) { + sh := fp.getOrCreate(st) + sh.AddMethod(n) +} + +func (fp *FileProcessor) getOrCreate(structName string) *StructHolder { if holder, ok := fp.structs[structName]; ok { return holder } - created := &models.StructHolder{Features: fp.features} + created := &StructHolder{ + Fset: fp.fset, + Features: fp.features, + } fp.structs[structName] = created return created diff --git a/vendor/github.com/manuelarte/funcorder/internal/models/struct_holder.go b/vendor/github.com/manuelarte/funcorder/internal/models/struct_holder.go deleted file mode 100644 index 4b832f3a2..000000000 --- a/vendor/github.com/manuelarte/funcorder/internal/models/struct_holder.go +++ /dev/null @@ -1,91 +0,0 @@ -package models - -import ( - "cmp" - "go/ast" - "slices" - - "golang.org/x/tools/go/analysis" - - "github.com/manuelarte/funcorder/internal/diag" - "github.com/manuelarte/funcorder/internal/features" -) - -// StructHolder contains all the information around a Go struct. -type StructHolder struct { - // The features to be analyzed - Features features.Feature - - // The struct declaration - Struct *ast.TypeSpec - - // A Struct constructor is considered if starts with `New...` and the 1st output parameter is a struct - Constructors []*ast.FuncDecl - - // Struct methods - 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) -} - -//nolint:gocognit,nestif // refactor later -func (sh *StructHolder) Analyze() []analysis.Diagnostic { - // 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 - - if sh.Features.IsEnabled(features.ConstructorCheck) { - structPos := sh.Struct.Pos() - - for _, c := range sh.Constructors { - if c.Pos() < structPos { - reports = append(reports, diag.NewConstructorNotAfterStructType(sh.Struct, c)) - } - - if len(sh.StructMethods) > 0 && c.Pos() > sh.StructMethods[0].Pos() { - reports = append(reports, diag.NewConstructorNotBeforeStructMethod(sh.Struct, c, sh.StructMethods[0])) - } - } - } - - if sh.Features.IsEnabled(features.StructMethodCheck) { - var lastExportedMethod *ast.FuncDecl - - for _, m := range sh.StructMethods { - if !m.Name.IsExported() { - continue - } - - if lastExportedMethod == nil { - lastExportedMethod = m - } - - if lastExportedMethod.Pos() < m.Pos() { - lastExportedMethod = m - } - } - - if lastExportedMethod != nil { - for _, m := range sh.StructMethods { - if m.Name.IsExported() || m.Pos() >= lastExportedMethod.Pos() { - continue - } - - reports = append(reports, diag.NewNonExportedMethodBeforeExportedForStruct(sh.Struct, m, lastExportedMethod)) - } - } - } - - // TODO also check that the methods are declared after the struct - return reports -} diff --git a/vendor/github.com/manuelarte/funcorder/internal/models/struct_constructor.go b/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go similarity index 80% rename from vendor/github.com/manuelarte/funcorder/internal/models/struct_constructor.go rename to vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go index 668ab3461..fc4b252df 100644 --- a/vendor/github.com/manuelarte/funcorder/internal/models/struct_constructor.go +++ b/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go @@ -1,9 +1,7 @@ -package models +package internal import ( "go/ast" - - "github.com/manuelarte/funcorder/internal/astutils" ) type StructConstructor struct { @@ -12,13 +10,13 @@ type StructConstructor struct { } func NewStructConstructor(funcDec *ast.FuncDecl) (StructConstructor, bool) { - if !astutils.FuncCanBeConstructor(funcDec) { + if !FuncCanBeConstructor(funcDec) { return StructConstructor{}, false } expr := funcDec.Type.Results.List[0].Type - returnType, ok := astutils.GetIdent(expr) + returnType, ok := GetIdent(expr) if !ok { return StructConstructor{}, false } diff --git a/vendor/github.com/manuelarte/funcorder/internal/structholder.go b/vendor/github.com/manuelarte/funcorder/internal/structholder.go new file mode 100644 index 000000000..424b2ddd7 --- /dev/null +++ b/vendor/github.com/manuelarte/funcorder/internal/structholder.go @@ -0,0 +1,141 @@ +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 + + // The struct declaration + Struct *ast.TypeSpec + + // A Struct constructor is considered if starts with `New...` and the 1st output parameter is a struct + Constructors []*ast.FuncDecl + + // Struct methods + 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 { + // 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 + + if sh.Features.IsEnabled(ConstructorCheck) { + reports = append(reports, sh.analyzeConstructor()...) + } + + if sh.Features.IsEnabled(StructMethodCheck) { + reports = append(reports, sh.analyzeStructMethod()...) + } + + // TODO also check that the methods are declared after the struct + return reports +} + +func (sh *StructHolder) analyzeConstructor() []analysis.Diagnostic { + var reports []analysis.Diagnostic + + for i, constructor := range sh.Constructors { + if constructor.Pos() < sh.Struct.Pos() { + reports = append(reports, NewConstructorNotAfterStructType(sh.Struct, constructor)) + } + + if len(sh.StructMethods) > 0 && constructor.Pos() > sh.StructMethods[0].Pos() { + reports = append(reports, NewConstructorNotBeforeStructMethod(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]), + ) + } + } + + return reports +} + +func (sh *StructHolder) analyzeStructMethod() []analysis.Diagnostic { + var lastExportedMethod *ast.FuncDecl + + for _, m := range sh.StructMethods { + if !m.Name.IsExported() { + continue + } + + if lastExportedMethod == nil { + lastExportedMethod = m + } + + if lastExportedMethod.Pos() < m.Pos() { + lastExportedMethod = m + } + } + + 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)) + } + } + + if sh.Features.IsEnabled(AlphabeticalCheck) { + exported, unexported := SplitExportedUnexported(sh.StructMethods) + reports = slices.Concat(reports, + sortDiagnostics(sh.Struct, exported), + sortDiagnostics(sh.Struct, unexported), + ) + } + + return reports +} + +func sortDiagnostics(typeSpec *ast.TypeSpec, funcDecls []*ast.FuncDecl) []analysis.Diagnostic { + var reports []analysis.Diagnostic + + 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])) + } + } + + return reports +} diff --git a/vendor/github.com/maratori/testableexamples/pkg/testableexamples/testableexamples.go b/vendor/github.com/maratori/testableexamples/pkg/testableexamples/testableexamples.go index 26d22c703..91a8509d2 100644 --- a/vendor/github.com/maratori/testableexamples/pkg/testableexamples/testableexamples.go +++ b/vendor/github.com/maratori/testableexamples/pkg/testableexamples/testableexamples.go @@ -13,7 +13,7 @@ func NewAnalyzer() *analysis.Analyzer { return &analysis.Analyzer{ Name: "testableexamples", Doc: "linter checks if examples are testable (have an expected output)", - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { testFiles := make([]*ast.File, 0, len(pass.Files)) for _, file := range pass.Files { fileName := pass.Fset.File(file.Pos()).Name() diff --git a/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go b/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go index 2e0572972..6eebabc2d 100644 --- a/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go +++ b/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go @@ -2,11 +2,11 @@ package testpackage import ( "flag" + "go/ast" "regexp" + "slices" "strings" - "go/ast" - "golang.org/x/tools/go/analysis" ) @@ -25,10 +25,8 @@ const ( func processTestFile(pass *analysis.Pass, f *ast.File, allowedPackages []string) { packageName := f.Name.Name - for _, p := range allowedPackages { - if p == packageName { - return - } + if slices.Contains(allowedPackages, packageName) { + return } if !strings.HasSuffix(packageName, "_test") { @@ -51,7 +49,7 @@ func NewAnalyzer() *analysis.Analyzer { Name: "testpackage", Doc: "linter that makes you use a separate _test package", Flags: fs, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { allowedPackages := strings.Split(allowPackagesStr, ",") skipFile, err := regexp.Compile(skipFileRegexp) if err != nil { diff --git a/vendor/github.com/mgechev/revive/config/config.go b/vendor/github.com/mgechev/revive/config/config.go index 34340b71c..224644479 100644 --- a/vendor/github.com/mgechev/revive/config/config.go +++ b/vendor/github.com/mgechev/revive/config/config.go @@ -83,6 +83,7 @@ var allRules = append([]lint.Rule{ &rule.UselessBreak{}, &rule.UncheckedTypeAssertionRule{}, &rule.TimeEqualRule{}, + &rule.TimeDateRule{}, &rule.BannedCharsRule{}, &rule.OptimizeOperandsOrderRule{}, &rule.UseAnyRule{}, @@ -101,6 +102,20 @@ var allRules = append([]lint.Rule{ &rule.RedundantBuildTagRule{}, &rule.UseErrorsNewRule{}, &rule.RedundantTestMainExitRule{}, + &rule.UnnecessaryFormatRule{}, + &rule.UseFmtPrintRule{}, + &rule.EnforceSwitchStyleRule{}, + &rule.IdenticalSwitchConditionsRule{}, + &rule.IdenticalIfElseIfConditionsRule{}, + &rule.IdenticalIfElseIfBranchesRule{}, + &rule.IdenticalSwitchBranchesRule{}, + &rule.UselessFallthroughRule{}, + &rule.PackageDirectoryMismatchRule{}, + &rule.UseWaitGroupGoRule{}, + &rule.UnsecureURLSchemeRule{}, + &rule.InefficientMapLookupRule{}, + &rule.ForbiddenCallInWgGoRule{}, + &rule.UnnecessaryIfRule{}, }, defaultRules...) // allFormatters is a list of all available formatters to output the linting results. @@ -125,7 +140,7 @@ func getFormatters() map[string]lint.Formatter { return result } -// GetLintingRules yields the linting rules that must be applied by the linter +// GetLintingRules yields the linting rules that must be applied by the linter. func GetLintingRules(config *lint.Config, extraRules []lint.Rule) ([]lint.Rule, error) { rulesMap := map[string]lint.Rule{} for _, r := range allRules { @@ -195,19 +210,22 @@ func normalizeConfig(config *lint.Config) { if len(config.Rules) == 0 { config.Rules = map[string]lint.RuleConfig{} } - if config.EnableAllRules { - // Add to the configuration all rules not yet present in it - for _, r := range allRules { + + addRules := func(config *lint.Config, rules []lint.Rule) { + for _, r := range rules { ruleName := r.Name() - _, alreadyInConf := config.Rules[ruleName] - if alreadyInConf { - continue + if _, ok := config.Rules[ruleName]; !ok { + config.Rules[ruleName] = lint.RuleConfig{} } - // Add the rule with an empty conf for - config.Rules[ruleName] = lint.RuleConfig{} } } + if config.EnableAllRules { + addRules(config, allRules) + } else if config.EnableDefaultRules { + addRules(config, defaultRules) + } + severity := config.Severity if severity != "" { for k, v := range config.Rules { @@ -227,7 +245,7 @@ func normalizeConfig(config *lint.Config) { const defaultConfidence = 0.8 -// GetConfig yields the configuration +// GetConfig yields the configuration. func GetConfig(configPath string) (*lint.Config, error) { config := &lint.Config{} switch { @@ -246,7 +264,7 @@ func GetConfig(configPath string) (*lint.Config, error) { return config, nil } -// GetFormatter yields the formatter for lint failures +// GetFormatter yields the formatter for lint failures. func GetFormatter(formatterName string) (lint.Formatter, error) { formatters := getFormatters() if formatterName == "" { diff --git a/vendor/github.com/mgechev/revive/formatter/checkstyle.go b/vendor/github.com/mgechev/revive/formatter/checkstyle.go index 8fe85fae5..1fb17d4d9 100644 --- a/vendor/github.com/mgechev/revive/formatter/checkstyle.go +++ b/vendor/github.com/mgechev/revive/formatter/checkstyle.go @@ -14,7 +14,7 @@ type Checkstyle struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Checkstyle) Name() string { return "checkstyle" } @@ -43,7 +43,7 @@ func (*Checkstyle) Format(failures <-chan lint.Failure, config lint.Config) (str Severity: severity(config, failure), RuleName: failure.RuleName, } - fn := failure.GetFilename() + fn := failure.Filename() if issues[fn] == nil { issues[fn] = []issue{} } diff --git a/vendor/github.com/mgechev/revive/formatter/default.go b/vendor/github.com/mgechev/revive/formatter/default.go index 7af4aad06..ffb9d5f3f 100644 --- a/vendor/github.com/mgechev/revive/formatter/default.go +++ b/vendor/github.com/mgechev/revive/formatter/default.go @@ -13,7 +13,7 @@ type Default struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Default) Name() string { return "default" } @@ -21,12 +21,14 @@ func (*Default) Name() string { // Format formats the failures gotten from the lint. func (*Default) Format(failures <-chan lint.Failure, _ lint.Config) (string, error) { var buf bytes.Buffer + prefix := "" for failure := range failures { - fmt.Fprintf(&buf, "%v: %s\n", failure.Position.Start, failure.Failure) + fmt.Fprintf(&buf, "%s%v: %s", prefix, failure.Position.Start, failure.Failure) + prefix = "\n" } return buf.String(), nil } func ruleDescriptionURL(ruleName string) string { - return "https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#" + ruleName + return "https://revive.run/r#" + ruleName } diff --git a/vendor/github.com/mgechev/revive/formatter/friendly.go b/vendor/github.com/mgechev/revive/formatter/friendly.go index 9c1a0f617..de24df887 100644 --- a/vendor/github.com/mgechev/revive/formatter/friendly.go +++ b/vendor/github.com/mgechev/revive/formatter/friendly.go @@ -7,27 +7,20 @@ import ( "io" "slices" "strings" + "text/tabwriter" "github.com/fatih/color" + "github.com/mgechev/revive/lint" - "github.com/olekukonko/tablewriter" ) -func getErrorEmoji() string { - return color.RedString("✘") -} - -func getWarningEmoji() string { - return color.YellowString("⚠") -} - // Friendly is an implementation of the Formatter interface // which formats the errors to JSON. type Friendly struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Friendly) Name() string { return "friendly" } @@ -64,16 +57,19 @@ func (f *Friendly) printFriendlyFailure(sb *strings.Builder, failure lint.Failur sb.WriteString("\n\n") } -func (f *Friendly) printHeaderRow(sb *strings.Builder, failure lint.Failure, severity lint.Severity) { - emoji := getWarningEmoji() +var errorEmoji = color.RedString("✘") +var warningEmoji = color.YellowString("⚠") + +func (*Friendly) printHeaderRow(sb *strings.Builder, failure lint.Failure, severity lint.Severity) { + emoji := warningEmoji if severity == lint.SeverityError { - emoji = getErrorEmoji() + emoji = errorEmoji } - sb.WriteString(f.table([][]string{{emoji, ruleDescriptionURL(failure.RuleName), color.GreenString(failure.Failure)}})) + sb.WriteString(table([][]string{{emoji, ruleDescriptionURL(failure.RuleName), color.GreenString(failure.Failure)}})) } func (*Friendly) printFilePosition(sb *strings.Builder, failure lint.Failure) { - sb.WriteString(fmt.Sprintf(" %s:%d:%d", failure.GetFilename(), failure.Position.Start.Line, failure.Position.Start.Column)) + fmt.Fprintf(sb, " %s:%d:%d", failure.Filename(), failure.Position.Start.Line, failure.Position.Start.Column) } type statEntry struct { @@ -82,9 +78,9 @@ type statEntry struct { } func (*Friendly) printSummary(w io.Writer, errors, warnings int) { - emoji := getWarningEmoji() + emoji := warningEmoji if errors > 0 { - emoji = getErrorEmoji() + emoji = errorEmoji } problemsLabel := "problems" if errors+warnings == 1 { @@ -109,7 +105,7 @@ func (*Friendly) printSummary(w io.Writer, errors, warnings int) { } } -func (f *Friendly) printStatistics(w io.Writer, header string, stats map[string]int) { +func (*Friendly) printStatistics(w io.Writer, header string, stats map[string]int) { if len(stats) == 0 { return } @@ -125,17 +121,19 @@ func (f *Friendly) printStatistics(w io.Writer, header string, stats map[string] formatted = append(formatted, []string{color.GreenString(fmt.Sprintf("%d", entry.failures)), entry.name}) } fmt.Fprintln(w, header) - fmt.Fprintln(w, f.table(formatted)) + fmt.Fprintln(w, table(formatted)) } -func (*Friendly) table(rows [][]string) string { - buf := new(bytes.Buffer) - table := tablewriter.NewWriter(buf) - table.SetBorder(false) - table.SetColumnSeparator("") - table.SetRowSeparator("") - table.SetAutoWrapText(false) - table.AppendBulk(rows) - table.Render() +func table(rows [][]string) string { + var buf bytes.Buffer + tw := tabwriter.NewWriter(&buf, 0, 0, 2, ' ', 0) + for _, row := range rows { + tw.Write([]byte{'\t'}) + for _, col := range row { + tw.Write(append([]byte(col), '\t')) + } + tw.Write([]byte{'\n'}) + } + tw.Flush() return buf.String() } diff --git a/vendor/github.com/mgechev/revive/formatter/json.go b/vendor/github.com/mgechev/revive/formatter/json.go index 7cace89ec..292c06b36 100644 --- a/vendor/github.com/mgechev/revive/formatter/json.go +++ b/vendor/github.com/mgechev/revive/formatter/json.go @@ -12,14 +12,14 @@ type JSON struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*JSON) Name() string { return "json" } -// jsonObject defines a JSON object of an failure +// jsonObject defines a JSON object of an failure. type jsonObject struct { - Severity lint.Severity + Severity lint.Severity `json:"Severity"` lint.Failure `json:",inline"` } diff --git a/vendor/github.com/mgechev/revive/formatter/ndjson.go b/vendor/github.com/mgechev/revive/formatter/ndjson.go index 58b35dc44..66acff320 100644 --- a/vendor/github.com/mgechev/revive/formatter/ndjson.go +++ b/vendor/github.com/mgechev/revive/formatter/ndjson.go @@ -13,7 +13,7 @@ type NDJSON struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*NDJSON) Name() string { return "ndjson" } diff --git a/vendor/github.com/mgechev/revive/formatter/plain.go b/vendor/github.com/mgechev/revive/formatter/plain.go index 351248742..6c77926ea 100644 --- a/vendor/github.com/mgechev/revive/formatter/plain.go +++ b/vendor/github.com/mgechev/revive/formatter/plain.go @@ -13,7 +13,7 @@ type Plain struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Plain) Name() string { return "plain" } diff --git a/vendor/github.com/mgechev/revive/formatter/sarif.go b/vendor/github.com/mgechev/revive/formatter/sarif.go index 72da16071..c17764902 100644 --- a/vendor/github.com/mgechev/revive/formatter/sarif.go +++ b/vendor/github.com/mgechev/revive/formatter/sarif.go @@ -5,7 +5,8 @@ import ( "fmt" "strings" - "github.com/chavacava/garif" + "codeberg.org/chavacava/garif" + "github.com/mgechev/revive/lint" ) @@ -15,19 +16,19 @@ type Sarif struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Sarif) Name() string { return "sarif" } -const reviveSite = "https://github.com/mgechev/revive" +const reviveSite = "https://revive.run" // Format formats the failures gotten from the lint. func (*Sarif) Format(failures <-chan lint.Failure, cfg lint.Config) (string, error) { sarifLog := newReviveRunLog(cfg) for failure := range failures { - sarifLog.AddResult(failure) + sarifLog.addResult(failure) } buf := new(bytes.Buffer) @@ -72,7 +73,7 @@ func (l *reviveRunLog) addRules(cfg map[string]lint.RuleConfig) { } } -func (l *reviveRunLog) AddResult(failure lint.Failure) { +func (l *reviveRunLog) addResult(failure lint.Failure) { positiveOrZero := func(x int) int { if x > 0 { return x diff --git a/vendor/github.com/mgechev/revive/formatter/stylish.go b/vendor/github.com/mgechev/revive/formatter/stylish.go index bb3d7cd18..8185e8b8a 100644 --- a/vendor/github.com/mgechev/revive/formatter/stylish.go +++ b/vendor/github.com/mgechev/revive/formatter/stylish.go @@ -1,12 +1,11 @@ package formatter import ( - "bytes" "fmt" "github.com/fatih/color" + "github.com/mgechev/revive/lint" - "github.com/olekukonko/tablewriter" ) // Stylish is an implementation of the Formatter interface @@ -15,21 +14,21 @@ type Stylish struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Stylish) Name() string { return "stylish" } func formatFailure(failure lint.Failure, severity lint.Severity) []string { fString := color.CyanString(failure.Failure) - fURL := ruleDescriptionURL(failure.RuleName) - fName := color.RedString(fURL) lineColumn := failure.Position pos := fmt.Sprintf("(%d, %d)", lineColumn.Start.Line, lineColumn.Start.Column) + fURL := ruleDescriptionURL(failure.RuleName) + fName := color.RedString(fURL) if severity == lint.SeverityWarning { fName = color.YellowString(fURL) } - return []string{failure.GetFilename(), pos, fName, fString} + return []string{failure.Filename(), pos, fName, fString} } // Format formats the failures gotten from the lint. @@ -46,10 +45,6 @@ func (*Stylish) Format(failures <-chan lint.Failure, config lint.Config) (string } result = append(result, formatFailure(f, lint.Severity(currentType))) } - ps := "problems" - if total == 1 { - ps = "problem" - } fileReport := map[string][][]string{} @@ -63,20 +58,25 @@ func (*Stylish) Format(failures <-chan lint.Failure, config lint.Config) (string output := "" for filename, val := range fileReport { - buf := new(bytes.Buffer) - table := tablewriter.NewWriter(buf) - table.SetBorder(false) - table.SetColumnSeparator("") - table.SetRowSeparator("") - table.SetAutoWrapText(false) - table.AppendBulk(val) - table.Render() c := color.New(color.Underline) output += c.SprintfFunc()(filename + "\n") - output += buf.String() + "\n" + output += table(val) + "\n" } - suffix := fmt.Sprintf(" %d %s (%d errors) (%d warnings)", total, ps, totalErrors, total-totalErrors) + problemsLabel := "problems" + if total == 1 { + problemsLabel = "problem" + } + totalWarnings := total - totalErrors + warningsLabel := "warnings" + if totalWarnings == 1 { + warningsLabel = "warning" + } + errorsLabel := "errors" + if totalErrors == 1 { + errorsLabel = "error" + } + suffix := fmt.Sprintf(" %d %s (%d %s) (%d %s)", total, problemsLabel, totalErrors, errorsLabel, totalWarnings, warningsLabel) switch { case total > 0 && totalErrors > 0: diff --git a/vendor/github.com/mgechev/revive/formatter/unix.go b/vendor/github.com/mgechev/revive/formatter/unix.go index 9ce8fee4d..dd063a0d8 100644 --- a/vendor/github.com/mgechev/revive/formatter/unix.go +++ b/vendor/github.com/mgechev/revive/formatter/unix.go @@ -15,7 +15,7 @@ type Unix struct { Metadata lint.FormatterMetadata } -// Name returns the name of the formatter +// Name returns the name of the formatter. func (*Unix) Name() string { return "unix" } diff --git a/vendor/github.com/mgechev/revive/internal/astutils/ast_utils.go b/vendor/github.com/mgechev/revive/internal/astutils/ast_utils.go index 0a346043a..fca3ee5a9 100644 --- a/vendor/github.com/mgechev/revive/internal/astutils/ast_utils.go +++ b/vendor/github.com/mgechev/revive/internal/astutils/ast_utils.go @@ -2,51 +2,54 @@ package astutils import ( + "bytes" + "crypto/md5" + "encoding/hex" + "fmt" "go/ast" + "go/printer" + "go/token" + "regexp" + "slices" ) // FuncSignatureIs returns true if the given func decl satisfies a signature characterized // by the given name, parameters types and return types; false otherwise. // // Example: to check if a function declaration has the signature Foo(int, string) (bool,error) -// call to FuncSignatureIs(funcDecl,"Foo",[]string{"int","string"},[]string{"bool","error"}) +// call to FuncSignatureIs(funcDecl,"Foo",[]string{"int","string"},[]string{"bool","error"}). func FuncSignatureIs(funcDecl *ast.FuncDecl, wantName string, wantParametersTypes, wantResultsTypes []string) bool { if wantName != funcDecl.Name.String() { return false // func name doesn't match expected one } - funcParametersTypes := getTypeNames(funcDecl.Type.Params) - if len(wantParametersTypes) != len(funcParametersTypes) { - return false // func has not the expected number of parameters + funcResultsTypes := GetTypeNames(funcDecl.Type.Results) + if !slices.Equal(wantResultsTypes, funcResultsTypes) { + return false // func has not the expected return values } - funcResultsTypes := getTypeNames(funcDecl.Type.Results) - if len(wantResultsTypes) != len(funcResultsTypes) { - return false // func has not the expected number of return values - } + // Name and return values are those we expected, + // the final result depends on parameters being what we want. + return funcParametersSignatureIs(funcDecl, wantParametersTypes) +} - for i, wantType := range wantParametersTypes { - if wantType != funcParametersTypes[i] { - return false // type of a func's parameter does not match the type of the corresponding expected parameter - } - } +// funcParametersSignatureIs returns true if the function has parameters of the given type and order, +// false otherwise. +func funcParametersSignatureIs(funcDecl *ast.FuncDecl, wantParametersTypes []string) bool { + funcParametersTypes := GetTypeNames(funcDecl.Type.Params) - for i, wantType := range wantResultsTypes { - if wantType != funcResultsTypes[i] { - return false // type of a func's return value does not match the type of the corresponding expected return value - } - } - - return true + return slices.Equal(wantParametersTypes, funcParametersTypes) } -func getTypeNames(fields *ast.FieldList) []string { - result := []string{} - +// GetTypeNames yields an slice with the string representation of the types of given fields. +// It yields nil if the field list is nil. +func GetTypeNames(fields *ast.FieldList) []string { if fields == nil { - return result + return nil } + result := []string{} + for _, field := range fields.List { typeName := getFieldTypeName(field.Type) if field.Names == nil { // unnamed field @@ -67,7 +70,7 @@ func getFieldTypeName(typ ast.Expr) string { case *ast.Ident: return f.Name case *ast.SelectorExpr: - return f.Sel.Name + "." + getFieldTypeName(f.X) + return getFieldTypeName(f.X) + "." + getFieldTypeName(f.Sel) case *ast.StarExpr: return "*" + getFieldTypeName(f.X) case *ast.IndexExpr: @@ -80,3 +83,134 @@ func getFieldTypeName(typ ast.Expr) string { return "UNHANDLED_TYPE" } } + +// IsStringLiteral returns true if the given expression is a string literal, false otherwise. +func IsStringLiteral(e ast.Expr) bool { + sl, ok := e.(*ast.BasicLit) + + return ok && sl.Kind == token.STRING +} + +// IsCgoExported returns true if the given function declaration is exported as Cgo function, false otherwise. +func IsCgoExported(f *ast.FuncDecl) bool { + if f.Recv != nil || f.Doc == nil { + return false + } + + cgoExport := regexp.MustCompile(fmt.Sprintf("(?m)^//export %s$", regexp.QuoteMeta(f.Name.Name))) + for _, c := range f.Doc.List { + if cgoExport.MatchString(c.Text) { + return true + } + } + return false +} + +// IsIdent returns true if the given expression is the identifier with name ident, false otherwise. +func IsIdent(expr ast.Expr, ident string) bool { + id, ok := expr.(*ast.Ident) + return ok && id.Name == ident +} + +// IsPkgDotName returns true if the given expression is a selector expression of the form ., false otherwise. +func IsPkgDotName(expr ast.Expr, pkg, name string) bool { + sel, ok := expr.(*ast.SelectorExpr) + return ok && IsIdent(sel.X, pkg) && IsIdent(sel.Sel, name) +} + +// PickNodes yields a list of nodes by picking them from a sub-ast with root node n. +// Nodes are selected by applying the selector function. +func PickNodes(n ast.Node, selector func(n ast.Node) bool) []ast.Node { + var result []ast.Node + + if n == nil { + return result + } + + onSelect := func(n ast.Node) { + result = append(result, n) + } + p := picker{selector: selector, onSelect: onSelect} + ast.Walk(p, n) + return result +} + +type picker struct { + selector func(n ast.Node) bool + onSelect func(n ast.Node) +} + +func (p picker) Visit(node ast.Node) ast.Visitor { + if p.selector == nil { + return nil + } + + if p.selector(node) { + p.onSelect(node) + } + + return p +} + +// SeekNode yields the first node selected by the given selector function in the AST subtree with root n. +// The function returns nil if no matching node is found in the subtree. +func SeekNode[T ast.Node](n ast.Node, selector func(n ast.Node) bool) T { + var result T + + if n == nil { + return result + } + + if selector == nil { + return result + } + + onSelect := func(n ast.Node) { + result, _ = n.(T) + } + + p := &seeker{selector: selector, onSelect: onSelect, found: false} + ast.Walk(p, n) + + return result +} + +type seeker struct { + selector func(n ast.Node) bool + onSelect func(n ast.Node) + found bool +} + +func (s *seeker) Visit(node ast.Node) ast.Visitor { + if s.found { + return nil // stop visiting subtree + } + + if s.selector(node) { + s.onSelect(node) + s.found = true + return nil // skip visiting node children + } + + return s +} + +var gofmtConfig = &printer.Config{Tabwidth: 8} + +// GoFmt returns a string representation of an AST subtree. +func GoFmt(x any) string { + buf := bytes.Buffer{} + fs := token.NewFileSet() + gofmtConfig.Fprint(&buf, fs, x) + return buf.String() +} + +// NodeHash yields the MD5 hash of the given AST node. +func NodeHash(node ast.Node) string { + hasher := func(in string) string { + binHash := md5.Sum([]byte(in)) + return hex.EncodeToString(binHash[:]) + } + str := GoFmt(node) + return hasher(str) +} diff --git a/vendor/github.com/mgechev/revive/internal/ifelse/args.go b/vendor/github.com/mgechev/revive/internal/ifelse/args.go index 8ea196471..288a8e630 100644 --- a/vendor/github.com/mgechev/revive/internal/ifelse/args.go +++ b/vendor/github.com/mgechev/revive/internal/ifelse/args.go @@ -1,7 +1,7 @@ package ifelse -// Args contains arguments common to the early-return, indent-error-flow -// and superfluous-else rules +// Args contains arguments common to the early-return, indent-error-flow, +// and superfluous-else rules. type Args struct { PreserveScope bool AllowJump bool diff --git a/vendor/github.com/mgechev/revive/internal/ifelse/branch.go b/vendor/github.com/mgechev/revive/internal/ifelse/branch.go index dfa744e35..518362781 100644 --- a/vendor/github.com/mgechev/revive/internal/ifelse/branch.go +++ b/vendor/github.com/mgechev/revive/internal/ifelse/branch.go @@ -58,7 +58,7 @@ func StmtBranch(stmt ast.Stmt) Branch { return Regular.Branch() } -// String returns a brief string representation +// String returns a brief string representation. func (b Branch) String() string { switch b.BranchKind { case Empty: @@ -71,7 +71,7 @@ func (b Branch) String() string { return fmt.Sprintf("{ ... %v }", b.BranchKind) } -// LongString returns a longer form string representation +// LongString returns a longer form string representation. func (b Branch) LongString() string { switch b.BranchKind { case Panic, Exit: @@ -80,7 +80,7 @@ func (b Branch) LongString() string { return b.BranchKind.LongString() } -// HasDecls returns whether the branch has any top-level declarations +// HasDecls returns whether the branch has any top-level declarations. func (b Branch) HasDecls() bool { for _, stmt := range b.block { switch stmt := stmt.(type) { @@ -95,13 +95,15 @@ func (b Branch) HasDecls() bool { return false } -// IsShort returns whether the branch is empty or consists of a single statement +// IsShort returns whether the branch is empty or consists of a single statement. func (b Branch) IsShort() bool { switch len(b.block) { case 0: return true case 1: return isShortStmt(b.block[0]) + case 2: + return isShortStmt(b.block[1]) } return false } diff --git a/vendor/github.com/mgechev/revive/internal/ifelse/branch_kind.go b/vendor/github.com/mgechev/revive/internal/ifelse/branch_kind.go index 75d3b0cfe..3f6c76996 100644 --- a/vendor/github.com/mgechev/revive/internal/ifelse/branch_kind.go +++ b/vendor/github.com/mgechev/revive/internal/ifelse/branch_kind.go @@ -5,35 +5,35 @@ package ifelse type BranchKind int const ( - // Empty branches do nothing + // Empty branches do nothing. Empty BranchKind = iota - // Return branches return from the current function + // Return branches return from the current function. Return - // Continue branches continue a surrounding "for" loop + // Continue branches continue a surrounding "for" loop. Continue - // Break branches break a surrounding "for" loop + // Break branches break a surrounding "for" loop. Break - // Goto branches conclude with a "goto" statement + // Goto branches conclude with a "goto" statement. Goto - // Panic branches panic the current function + // Panic branches panic the current function. Panic - // Exit branches end the program + // Exit branches end the program. Exit - // Regular branches do not fit any category above + // Regular branches do not fit any category above. Regular ) -// IsEmpty tests if the branch is empty +// IsEmpty tests if the branch is empty. func (k BranchKind) IsEmpty() bool { return k == Empty } -// Returns tests if the branch returns from the current function +// Returns tests if the branch returns from the current function. func (k BranchKind) Returns() bool { return k == Return } // Deviates tests if the control does not flow to the first @@ -48,15 +48,13 @@ func (k BranchKind) Deviates() bool { panic("invalid kind") } -// Branch returns a Branch with the given kind +// Branch returns a Branch with the given kind. func (k BranchKind) Branch() Branch { return Branch{BranchKind: k} } -// String returns a brief string representation +// String returns a brief string representation. func (k BranchKind) String() string { switch k { - case Empty: - return "" - case Regular: + case Empty, Regular: return "" case Return: return "return" @@ -74,7 +72,7 @@ func (k BranchKind) String() string { panic("invalid kind") } -// LongString returns a longer form string representation +// LongString returns a longer form string representation. func (k BranchKind) LongString() string { switch k { case Empty: diff --git a/vendor/github.com/mgechev/revive/internal/ifelse/func.go b/vendor/github.com/mgechev/revive/internal/ifelse/func.go index 45c78f079..89e251129 100644 --- a/vendor/github.com/mgechev/revive/internal/ifelse/func.go +++ b/vendor/github.com/mgechev/revive/internal/ifelse/func.go @@ -40,7 +40,7 @@ func ExprCall(expr *ast.ExprStmt) (Call, bool) { return Call{}, false } -// String returns the function name with package qualifier (if any) +// String returns the function name with package qualifier (if any). func (f Call) String() string { if f.Pkg != "" { return fmt.Sprintf("%s.%s", f.Pkg, f.Name) diff --git a/vendor/github.com/mgechev/revive/internal/ifelse/target.go b/vendor/github.com/mgechev/revive/internal/ifelse/target.go index 63755acf1..d54fc537b 100644 --- a/vendor/github.com/mgechev/revive/internal/ifelse/target.go +++ b/vendor/github.com/mgechev/revive/internal/ifelse/target.go @@ -6,10 +6,10 @@ import "go/ast" type Target int const ( - // TargetIf means the text refers to the "if" + // TargetIf means the text refers to the "if". TargetIf Target = iota - // TargetElse means the text refers to the "else" + // TargetElse means the text refers to the "else". TargetElse ) diff --git a/vendor/github.com/mgechev/revive/internal/rule/name.go b/vendor/github.com/mgechev/revive/internal/rule/name.go new file mode 100644 index 000000000..60257674a --- /dev/null +++ b/vendor/github.com/mgechev/revive/internal/rule/name.go @@ -0,0 +1,135 @@ +// Package rule defines utility functions some revive rules can share. +package rule + +import ( + "strings" + "unicode" +) + +// commonInitialisms is a set of common initialisms. +// Only add entries that are highly unlikely to be non-initialisms. +// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. +var commonInitialisms = map[string]bool{ + "ACL": true, + "API": true, + "ASCII": true, + "CPU": true, + "CSS": true, + "DNS": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ID": true, + "IDS": true, + "IP": true, + "JSON": true, + "LHS": true, + "QPS": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "UUID": true, + "URI": true, + "URL": true, + "UTF8": true, + "VM": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} + +// Name returns a different name of struct, var, const, or function if it should be different. +func Name(name string, allowlist, blocklist []string, skipInitialismNameChecks bool) (should string) { + // Fast path for simple cases: "_" and all lowercase. + if name == "_" { + return name + } + allLower := true + for _, r := range name { + if !unicode.IsLower(r) { + allLower = false + break + } + } + if allLower { + return name + } + + // Split camelCase at any lower->upper transition, and split on underscores. + // Check each word for common initialisms. + runes := []rune(name) + w, i := 0, 0 // index of start of word, scan + for i+1 <= len(runes) { + eow := false // whether we hit the end of a word + switch { + case i+1 == len(runes): + eow = true + case runes[i+1] == '_': + // underscore; shift the remainder forward over any run of underscores + eow = true + n := 1 + for i+n+1 < len(runes) && runes[i+n+1] == '_' { + n++ + } + + // Leave at most one underscore if the underscore is between two digits + if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { + n-- + } + + copy(runes[i+1:], runes[i+n+1:]) + runes = runes[:len(runes)-n] + case unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]): + // lower->non-lower + eow = true + } + i++ + if !eow { + continue + } + + // [w,i) is a word. + word := string(runes[w:i]) + ignoreInitWarnings := map[string]bool{} + for _, i := range allowlist { + ignoreInitWarnings[i] = true + } + + extraInits := map[string]bool{} + for _, i := range blocklist { + extraInits[i] = true + } + + if u := strings.ToUpper(word); !skipInitialismNameChecks && (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] { + // Keep consistent case, which is lowercase only at the start. + if w == 0 && unicode.IsLower(runes[w]) { + u = strings.ToLower(u) + } + // Keep lowercase s for IDs + if u == "IDS" { + u = "IDs" + } + // All the common initialisms are ASCII, + // so we can replace the bytes exactly. + copy(runes[w:], []rune(u)) + } else if w > 0 && strings.ToLower(word) == word { + // already all lowercase, and not the first word, so uppercase the first character. + runes[w] = unicode.ToUpper(runes[w]) + } + w = i + } + return string(runes) +} diff --git a/vendor/github.com/mgechev/revive/internal/typeparams/typeparams.go b/vendor/github.com/mgechev/revive/internal/typeparams/typeparams.go index 33c4f203e..e3e0ecd77 100644 --- a/vendor/github.com/mgechev/revive/internal/typeparams/typeparams.go +++ b/vendor/github.com/mgechev/revive/internal/typeparams/typeparams.go @@ -6,12 +6,6 @@ import ( "go/ast" ) -// Enabled reports whether type parameters are enabled in the current build -// environment. -func Enabled() bool { - return enabled -} - // ReceiverType returns the named type of the method receiver, sans "*" and type // parameters, or "invalid-type" if fn.Recv is ill formed. func ReceiverType(fn *ast.FuncDecl) string { @@ -19,11 +13,19 @@ func ReceiverType(fn *ast.FuncDecl) string { if s, ok := e.(*ast.StarExpr); ok { e = s.X } - if enabled { - e = unpackIndexExpr(e) - } + e = unpackIndexExpr(e) if id, ok := e.(*ast.Ident); ok { return id.Name } return "invalid-type" } + +func unpackIndexExpr(e ast.Expr) ast.Expr { + switch e := e.(type) { + case *ast.IndexExpr: + return e.X + case *ast.IndexListExpr: + return e.X + } + return e +} diff --git a/vendor/github.com/mgechev/revive/internal/typeparams/typeparams_go117.go b/vendor/github.com/mgechev/revive/internal/typeparams/typeparams_go117.go deleted file mode 100644 index 913a7316e..000000000 --- a/vendor/github.com/mgechev/revive/internal/typeparams/typeparams_go117.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !go1.18 -// +build !go1.18 - -package typeparams - -import ( - "go/ast" -) - -const enabled = false - -func unpackIndexExpr(e ast.Expr) ast.Expr { return e } diff --git a/vendor/github.com/mgechev/revive/internal/typeparams/typeparams_go118.go b/vendor/github.com/mgechev/revive/internal/typeparams/typeparams_go118.go deleted file mode 100644 index 0f7fd88d3..000000000 --- a/vendor/github.com/mgechev/revive/internal/typeparams/typeparams_go118.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build go1.18 -// +build go1.18 - -package typeparams - -import ( - "go/ast" -) - -const enabled = true - -func unpackIndexExpr(e ast.Expr) ast.Expr { - switch e := e.(type) { - case *ast.IndexExpr: - return e.X - case *ast.IndexListExpr: - return e.X - } - return e -} diff --git a/vendor/github.com/mgechev/revive/lint/config.go b/vendor/github.com/mgechev/revive/lint/config.go index 485f61833..3047fd29d 100644 --- a/vendor/github.com/mgechev/revive/lint/config.go +++ b/vendor/github.com/mgechev/revive/lint/config.go @@ -21,7 +21,7 @@ type RuleConfig struct { excludeFilters []*FileFilter } -// Initialize - should be called after reading from TOML file +// Initialize should be called after reading from TOML file. func (rc *RuleConfig) Initialize() error { for _, f := range rc.Exclude { ff, err := ParseFileFilter(f) @@ -36,7 +36,7 @@ func (rc *RuleConfig) Initialize() error { // RulesConfig defines the config for all rules. type RulesConfig = map[string]RuleConfig -// MustExclude - checks if given filename `name` must be excluded +// MustExclude checks if given filename `name` must be excluded. func (rc *RuleConfig) MustExclude(name string) bool { for _, exclude := range rc.excludeFilters { if exclude.MatchFileName(name) { @@ -56,10 +56,11 @@ type DirectivesConfig = map[string]DirectiveConfig // Config defines the config of the linter. type Config struct { - IgnoreGeneratedHeader bool `toml:"ignoreGeneratedHeader"` - Confidence float64 - Severity Severity + IgnoreGeneratedHeader bool `toml:"ignoreGeneratedHeader"` + Confidence float64 `toml:"confidence"` + Severity Severity `toml:"severity"` EnableAllRules bool `toml:"enableAllRules"` + EnableDefaultRules bool `toml:"enableDefaultRules"` Rules RulesConfig `toml:"rule"` ErrorCode int `toml:"errorCode"` WarningCode int `toml:"warningCode"` @@ -67,5 +68,5 @@ type Config struct { Exclude []string `toml:"exclude"` // If set, overrides the go language version specified in go.mod of // packages being linted, and assumes this specific language version. - GoVersion *goversion.Version + GoVersion *goversion.Version `toml:"goVersion"` } diff --git a/vendor/github.com/mgechev/revive/lint/failure.go b/vendor/github.com/mgechev/revive/lint/failure.go index 48095f9d7..c25df4836 100644 --- a/vendor/github.com/mgechev/revive/lint/failure.go +++ b/vendor/github.com/mgechev/revive/lint/failure.go @@ -11,6 +11,8 @@ const ( // FailureCategoryBadPractice indicates bad practice issues. FailureCategoryBadPractice FailureCategory = "bad practice" // FailureCategoryCodeStyle indicates code style issues. + // + // Deprecated: use FailureCategoryStyle instead. FailureCategoryCodeStyle FailureCategory = "code-style" // FailureCategoryComments indicates comment issues. FailureCategoryComments FailureCategory = "comments" @@ -53,7 +55,7 @@ const ( type FailureCategory string const ( - // SeverityWarning declares failures of type warning + // SeverityWarning declares failures of type warning. SeverityWarning = "warning" // SeverityError declares failures of type error. SeverityError = "error" @@ -62,26 +64,33 @@ const ( // Severity is the type for the failure types. type Severity string -// FailurePosition returns the failure position +// FailurePosition returns the failure position. type FailurePosition struct { - Start token.Position - End token.Position + Start token.Position `json:"Start"` + End token.Position `json:"End"` } // Failure defines a struct for a linting failure. type Failure struct { - Failure string - RuleName string - Category FailureCategory - Position FailurePosition - Node ast.Node `json:"-"` - Confidence float64 + Failure string `json:"Failure"` + RuleName string `json:"RuleName"` + Category FailureCategory `json:"Category"` + Position FailurePosition `json:"Position"` + Node ast.Node `json:"-"` + Confidence float64 `json:"Confidence"` // For future use - ReplacementLine string + ReplacementLine string `json:"ReplacementLine"` } // GetFilename returns the filename. +// +// Deprecated: Use [Filename]. func (f *Failure) GetFilename() string { + return f.Filename() +} + +// Filename returns the filename. +func (f *Failure) Filename() string { return f.Position.Start.Filename } diff --git a/vendor/github.com/mgechev/revive/lint/file.go b/vendor/github.com/mgechev/revive/lint/file.go index 950d756db..bf6aed452 100644 --- a/vendor/github.com/mgechev/revive/lint/file.go +++ b/vendor/github.com/mgechev/revive/lint/file.go @@ -24,12 +24,29 @@ type File struct { // IsTest returns if the file contains tests. func (f *File) IsTest() bool { return strings.HasSuffix(f.Name, "_test.go") } +// IsImportable returns if the symbols defined in this file can be imported in other packages. +// +// Symbols from the package `main` or test files are not exported, so they cannot be imported. +func (f *File) IsImportable() bool { + if f.IsTest() { + // Test files cannot be imported. + return false + } + + if f.Pkg.IsMain() { + // The package `main` cannot be imported. + return false + } + + return true +} + // Content returns the file's content. func (f *File) Content() []byte { return f.content } -// NewFile creates a new file +// NewFile creates a new file. func NewFile(name string, content []byte, pkg *Package) (*File, error) { f, err := parser.ParseFile(pkg.fset, name, content, parser.ParseComments) if err != nil { @@ -73,7 +90,7 @@ var basicTypeKinds = map[types.BasicKind]string{ // IsUntypedConst reports whether expr is an untyped constant, // and indicates what its default type is. -// scope may be nil. +// Scope may be nil. func (f *File) IsUntypedConst(expr ast.Expr) (defType string, ok bool) { // Re-evaluate expr outside its context to see if it's untyped. // (An expr evaluated within, for example, an assignment context will get the type of the LHS.) @@ -222,7 +239,7 @@ func (f *File) disabledIntervals(rules []Rule, mustSpecifyDisableReason bool, fa for _, name := range tempNames { name = strings.Trim(name, "\n") - if len(name) > 0 { + if name != "" { ruleNames = append(ruleNames, name) } } diff --git a/vendor/github.com/mgechev/revive/lint/filefilter.go b/vendor/github.com/mgechev/revive/lint/filefilter.go index 0e81fede6..9978597f3 100644 --- a/vendor/github.com/mgechev/revive/lint/filefilter.go +++ b/vendor/github.com/mgechev/revive/lint/filefilter.go @@ -6,12 +6,12 @@ import ( "strings" ) -// FileFilter - file filter to exclude some files for rule -// supports whole -// 1. file/dir names : pkg/mypkg/my.go, -// 2. globs: **/*.pb.go, -// 3. regexes (~ prefix) ~-tmp\.\d+\.go -// 4. special test marker `TEST` - treats as `~_test\.go` +// FileFilter filters file to exclude some files for a rule. +// Supports the following: +// - File or directory names: pkg/mypkg/my.go +// - Globs: **/*.pb.go, +// - Regexes (with ~ prefix): ~-tmp\.\d+\.go +// - Special test marker `TEST` (treated as `~_test\.go`). type FileFilter struct { // raw definition of filter inside config raw string @@ -23,15 +23,15 @@ type FileFilter struct { matchesNothing bool } -// ParseFileFilter - creates [FileFilter] for given raw filter -// if empty string, it matches nothing -// if `*`, or `~`, it matches everything -// while regexp could be invalid, it could return it's compilation error +// ParseFileFilter creates a [FileFilter] for the given raw filter. +// If the string is empty, it matches nothing. +// If the string is `*` or `~`, it matches everything. +// If the regular expression is invalid, it returns a compilation error. func ParseFileFilter(rawFilter string) (*FileFilter, error) { rawFilter = strings.TrimSpace(rawFilter) result := new(FileFilter) result.raw = rawFilter - result.matchesNothing = len(result.raw) == 0 + result.matchesNothing = result.raw == "" result.matchesAll = result.raw == "*" || result.raw == "~" if !result.matchesAll && !result.matchesNothing { if err := result.prepareRegexp(); err != nil { @@ -43,7 +43,7 @@ func ParseFileFilter(rawFilter string) (*FileFilter, error) { func (ff *FileFilter) String() string { return ff.raw } -// MatchFileName - checks if file name matches filter +// MatchFileName checks if the file name matches the filter. func (ff *FileFilter) MatchFileName(name string) bool { if ff.matchesAll { return true diff --git a/vendor/github.com/mgechev/revive/lint/formatter.go b/vendor/github.com/mgechev/revive/lint/formatter.go index 7c19af278..c770fdf2d 100644 --- a/vendor/github.com/mgechev/revive/lint/formatter.go +++ b/vendor/github.com/mgechev/revive/lint/formatter.go @@ -1,13 +1,13 @@ package lint -// FormatterMetadata configuration of a formatter +// FormatterMetadata configuration of a formatter. type FormatterMetadata struct { Name string Description string Sample string } -// Formatter defines an interface for failure formatters +// Formatter defines an interface for failure formatters. type Formatter interface { Format(<-chan Failure, Config) (string, error) Name() string diff --git a/vendor/github.com/mgechev/revive/lint/linter.go b/vendor/github.com/mgechev/revive/lint/linter.go index 38f4ae752..2abbb699d 100644 --- a/vendor/github.com/mgechev/revive/lint/linter.go +++ b/vendor/github.com/mgechev/revive/lint/linter.go @@ -25,7 +25,7 @@ type Linter struct { fileReadTokens chan struct{} } -// New creates a new Linter +// New creates a new Linter. func New(reader ReadFile, maxOpenFiles int) Linter { var fileReadTokens chan struct{} if maxOpenFiles > 0 { @@ -215,7 +215,7 @@ func isGenerated(src []byte) bool { return false } -// addInvalidFileFailure adds a failure for an invalid formatted file +// addInvalidFileFailure adds a failure for an invalid formatted file. func addInvalidFileFailure(filename, errStr string, failures chan Failure) { position := getPositionInvalidFile(filename, errStr) failures <- Failure{ @@ -226,12 +226,14 @@ func addInvalidFileFailure(filename, errStr string, failures chan Failure) { } } -// errPosRegexp matches with an NewFile error message -// i.e. : corrupted.go:10:4: expected '}', found 'EOF -// first group matches the line and the second group, the column +// errPosRegexp matches with a NewFile error message: +// +// corrupted.go:10:4: expected '}', found 'EOF +// +// The first group matches the line, and the second group matches the column. var errPosRegexp = regexp.MustCompile(`.*:(\d*):(\d*):.*$`) -// getPositionInvalidFile gets the position of the error in an invalid file +// getPositionInvalidFile gets the position of the error in an invalid file. func getPositionInvalidFile(filename, s string) FailurePosition { pos := errPosRegexp.FindStringSubmatch(s) if len(pos) < 3 { diff --git a/vendor/github.com/mgechev/revive/lint/name.go b/vendor/github.com/mgechev/revive/lint/name.go index 6ccfb0ef2..23ca06c22 100644 --- a/vendor/github.com/mgechev/revive/lint/name.go +++ b/vendor/github.com/mgechev/revive/lint/name.go @@ -1,133 +1,10 @@ package lint -import ( - "strings" - "unicode" -) +import "github.com/mgechev/revive/internal/rule" // Name returns a different name if it should be different. -func Name(name string, allowlist, blocklist []string) (should string) { - // Fast path for simple cases: "_" and all lowercase. - if name == "_" { - return name - } - allLower := true - for _, r := range name { - if !unicode.IsLower(r) { - allLower = false - break - } - } - if allLower { - return name - } - - // Split camelCase at any lower->upper transition, and split on underscores. - // Check each word for common initialisms. - runes := []rune(name) - w, i := 0, 0 // index of start of word, scan - for i+1 <= len(runes) { - eow := false // whether we hit the end of a word - if i+1 == len(runes) { - eow = true - } else if runes[i+1] == '_' { - // underscore; shift the remainder forward over any run of underscores - eow = true - n := 1 - for i+n+1 < len(runes) && runes[i+n+1] == '_' { - n++ - } - - // Leave at most one underscore if the underscore is between two digits - if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { - n-- - } - - copy(runes[i+1:], runes[i+n+1:]) - runes = runes[:len(runes)-n] - } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { - // lower->non-lower - eow = true - } - i++ - if !eow { - continue - } - - // [w,i) is a word. - word := string(runes[w:i]) - ignoreInitWarnings := map[string]bool{} - for _, i := range allowlist { - ignoreInitWarnings[i] = true - } - - extraInits := map[string]bool{} - for _, i := range blocklist { - extraInits[i] = true - } - - if u := strings.ToUpper(word); (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] { - // Keep consistent case, which is lowercase only at the start. - if w == 0 && unicode.IsLower(runes[w]) { - u = strings.ToLower(u) - } - // Keep lowercase s for IDs - if u == "IDS" { - u = "IDs" - } - // All the common initialisms are ASCII, - // so we can replace the bytes exactly. - copy(runes[w:], []rune(u)) - } else if w > 0 && strings.ToLower(word) == word { - // already all lowercase, and not the first word, so uppercase the first character. - runes[w] = unicode.ToUpper(runes[w]) - } - w = i - } - return string(runes) -} - -// commonInitialisms is a set of common initialisms. -// Only add entries that are highly unlikely to be non-initialisms. -// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. -var commonInitialisms = map[string]bool{ - "ACL": true, - "API": true, - "ASCII": true, - "CPU": true, - "CSS": true, - "DNS": true, - "EOF": true, - "GUID": true, - "HTML": true, - "HTTP": true, - "HTTPS": true, - "ID": true, - "IDS": true, - "IP": true, - "JSON": true, - "LHS": true, - "QPS": true, - "RAM": true, - "RHS": true, - "RPC": true, - "SLA": true, - "SMTP": true, - "SQL": true, - "SSH": true, - "TCP": true, - "TLS": true, - "TTL": true, - "UDP": true, - "UI": true, - "UID": true, - "UUID": true, - "URI": true, - "URL": true, - "UTF8": true, - "VM": true, - "XML": true, - "XMPP": true, - "XSRF": true, - "XSS": true, +// +// Deprecated: Do not use this function, it will be removed in the next major release. +func Name(name string, allowlist, blocklist []string) string { + return rule.Name(name, allowlist, blocklist, false) } diff --git a/vendor/github.com/mgechev/revive/lint/package.go b/vendor/github.com/mgechev/revive/lint/package.go index f0c249e60..cb78cb452 100644 --- a/vendor/github.com/mgechev/revive/lint/package.go +++ b/vendor/github.com/mgechev/revive/lint/package.go @@ -17,50 +17,52 @@ import ( // Package represents a package in the project. type Package struct { - fset *token.FileSet + fset *token.FileSet + + mu sync.RWMutex files map[string]*File goVersion *goversion.Version - typesPkg *types.Package typesInfo *types.Info - // sortable is the set of types in the package that implement sort.Interface. sortable map[string]bool // main is whether this is a "main" package. main int - sync.RWMutex } var ( trueValue = 1 falseValue = 2 - // Go115 is a constant representing the Go version 1.15 + // Go115 is a constant representing the Go version 1.15. Go115 = goversion.Must(goversion.NewVersion("1.15")) - // Go121 is a constant representing the Go version 1.21 + // Go121 is a constant representing the Go version 1.21. Go121 = goversion.Must(goversion.NewVersion("1.21")) - // Go122 is a constant representing the Go version 1.22 + // Go122 is a constant representing the Go version 1.22. Go122 = goversion.Must(goversion.NewVersion("1.22")) - // Go124 is a constant representing the Go version 1.24 + // Go124 is a constant representing the Go version 1.24. Go124 = goversion.Must(goversion.NewVersion("1.24")) + // Go125 is a constant representing the Go version 1.25. + Go125 = goversion.Must(goversion.NewVersion("1.25")) ) // Files return package's files. func (p *Package) Files() map[string]*File { - p.RLock() - defer p.RUnlock() + p.mu.RLock() + defer p.mu.RUnlock() return p.files } // IsMain returns if that's the main package. func (p *Package) IsMain() bool { - p.Lock() - defer p.Unlock() + p.mu.Lock() + defer p.mu.Unlock() - if p.main == trueValue { + switch p.main { + case trueValue: return true - } else if p.main == falseValue { + case falseValue: return false } for _, f := range p.files { @@ -73,34 +75,34 @@ func (p *Package) IsMain() bool { return false } -// TypesPkg yields information on this package +// TypesPkg yields information on this package. func (p *Package) TypesPkg() *types.Package { - p.RLock() - defer p.RUnlock() + p.mu.RLock() + defer p.mu.RUnlock() return p.typesPkg } -// TypesInfo yields type information of this package identifiers +// TypesInfo yields type information of this package identifiers. func (p *Package) TypesInfo() *types.Info { - p.RLock() - defer p.RUnlock() + p.mu.RLock() + defer p.mu.RUnlock() return p.typesInfo } -// Sortable yields a map of sortable types in this package +// Sortable yields a map of sortable types in this package. func (p *Package) Sortable() map[string]bool { - p.RLock() - defer p.RUnlock() + p.mu.RLock() + defer p.mu.RUnlock() return p.sortable } // TypeCheck performs type checking for given package. func (p *Package) TypeCheck() error { - p.Lock() - defer p.Unlock() + p.mu.Lock() + defer p.mu.Unlock() alreadyTypeChecked := p.typesInfo != nil || p.typesPkg != nil if alreadyTypeChecked { @@ -141,7 +143,7 @@ func (p *Package) TypeCheck() error { } // check function encapsulates the call to go/types.Config.Check method and -// recovers if the called method panics (see issue #59) +// recovers if the called method panics (see issue #59). func check(config *types.Config, n string, fset *token.FileSet, astFiles []*ast.File, info *types.Info) (p *types.Package, err error) { defer func() { if r := recover(); r != nil { @@ -156,8 +158,8 @@ func check(config *types.Config, n string, fset *token.FileSet, astFiles []*ast. // TypeOf returns the type of expression. func (p *Package) TypeOf(expr ast.Expr) types.Type { - p.RLock() - defer p.RUnlock() + p.mu.RLock() + defer p.mu.RUnlock() if p.typesInfo == nil { return nil @@ -176,8 +178,8 @@ const ( ) func (p *Package) scanSortable() { - p.Lock() - defer p.Unlock() + p.mu.Lock() + defer p.mu.Unlock() sortableFlags := map[string]sortableMethodsFlags{} for _, f := range p.files { @@ -213,10 +215,10 @@ func (p *Package) lint(rules []Rule, config Config, failures chan Failure) error return eg.Wait() } -// IsAtLeastGoVersion returns true if the Go version for this package is v or higher, false otherwise +// IsAtLeastGoVersion returns true if the Go version for this package is v or higher, false otherwise. func (p *Package) IsAtLeastGoVersion(v *goversion.Version) bool { - p.RLock() - defer p.RUnlock() + p.mu.RLock() + defer p.mu.RUnlock() return p.goVersion.GreaterThanOrEqual(v) } diff --git a/vendor/github.com/mgechev/revive/lint/rule.go b/vendor/github.com/mgechev/revive/lint/rule.go index cc424e96a..e682c1c80 100644 --- a/vendor/github.com/mgechev/revive/lint/rule.go +++ b/vendor/github.com/mgechev/revive/lint/rule.go @@ -11,7 +11,7 @@ type DisabledInterval struct { RuleName string } -// Rule defines an abstract rule interface +// Rule defines an abstract rule interface. type Rule interface { Name() string Apply(*File, Arguments) []Failure diff --git a/vendor/github.com/mgechev/revive/logging/logger.go b/vendor/github.com/mgechev/revive/logging/logger.go new file mode 100644 index 000000000..212419f27 --- /dev/null +++ b/vendor/github.com/mgechev/revive/logging/logger.go @@ -0,0 +1,37 @@ +// Package logging provides a logger and related methods. +package logging + +import ( + "io" + "log/slog" + "os" +) + +const logFile = "revive.log" + +var logger *slog.Logger + +// GetLogger retrieves an instance of an application logger which outputs +// to a file if the debug flag is enabled. +func GetLogger() (*slog.Logger, error) { + if logger != nil { + return logger, nil + } + + debugModeEnabled := os.Getenv("DEBUG") != "" + if !debugModeEnabled { + // by default, suppress all logging output + return slog.New(slog.NewTextHandler(io.Discard, nil)), nil // TODO: change to slog.New(slog.DiscardHandler) when we switch to Go 1.24 + } + + fileWriter, err := os.Create(logFile) + if err != nil { + return nil, err + } + + logger = slog.New(slog.NewTextHandler(io.MultiWriter(os.Stderr, fileWriter), nil)) + + logger.Info("Logger initialized", "logFile", logFile) + + return logger, nil +} diff --git a/vendor/github.com/mgechev/revive/rule/atomic.go b/vendor/github.com/mgechev/revive/rule/atomic.go index 61219765f..83a7daeae 100644 --- a/vendor/github.com/mgechev/revive/rule/atomic.go +++ b/vendor/github.com/mgechev/revive/rule/atomic.go @@ -5,6 +5,7 @@ import ( "go/token" "go/types" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -76,9 +77,9 @@ func (w atomic) Visit(node ast.Node) ast.Visitor { broken := false if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND { - broken = gofmt(left) == gofmt(uarg.X) + broken = astutils.GoFmt(left) == astutils.GoFmt(uarg.X) } else if star, ok := left.(*ast.StarExpr); ok { - broken = gofmt(star.X) == gofmt(arg) + broken = astutils.GoFmt(star.X) == astutils.GoFmt(arg) } if broken { diff --git a/vendor/github.com/mgechev/revive/rule/banned_characters.go b/vendor/github.com/mgechev/revive/rule/banned_characters.go index 7eb026b03..228156bb4 100644 --- a/vendor/github.com/mgechev/revive/rule/banned_characters.go +++ b/vendor/github.com/mgechev/revive/rule/banned_characters.go @@ -50,12 +50,12 @@ func (r *BannedCharsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failur return failures } -// Name returns the rule name +// Name returns the rule name. func (*BannedCharsRule) Name() string { return bannedCharsRuleName } -// getBannedCharsList converts arguments into the banned characters list +// getBannedCharsList converts arguments into the banned characters list. func (r *BannedCharsRule) getBannedCharsList(args lint.Arguments) ([]string, error) { var bannedChars []string for _, char := range args { @@ -74,7 +74,7 @@ type lintBannedCharsRule struct { onFailure func(lint.Failure) } -// Visit checks for each node if an identifier contains banned characters +// Visit checks for each node if an identifier contains banned characters. func (w lintBannedCharsRule) Visit(node ast.Node) ast.Visitor { n, ok := node.(*ast.Ident) if !ok { diff --git a/vendor/github.com/mgechev/revive/rule/bare_return.go b/vendor/github.com/mgechev/revive/rule/bare_return.go index c5a9441f6..f2c907405 100644 --- a/vendor/github.com/mgechev/revive/rule/bare_return.go +++ b/vendor/github.com/mgechev/revive/rule/bare_return.go @@ -42,7 +42,7 @@ func (w lintBareReturnRule) Visit(node ast.Node) ast.Visitor { return w } -// checkFunc will verify if the given function has named result and bare returns +// checkFunc will verify if the given function has named result and bare returns. func (w lintBareReturnRule) checkFunc(results *ast.FieldList, body *ast.BlockStmt) { hasNamedResults := results != nil && len(results.List) > 0 && results.List[0].Names != nil if !hasNamedResults || body == nil { diff --git a/vendor/github.com/mgechev/revive/rule/bool_literal_in_expr.go b/vendor/github.com/mgechev/revive/rule/bool_literal_in_expr.go index dd1e9be87..c510ecc3e 100644 --- a/vendor/github.com/mgechev/revive/rule/bool_literal_in_expr.go +++ b/vendor/github.com/mgechev/revive/rule/bool_literal_in_expr.go @@ -36,8 +36,7 @@ type lintBoolLiteral struct { } func (w *lintBoolLiteral) Visit(node ast.Node) ast.Visitor { - switch n := node.(type) { - case *ast.BinaryExpr: + if n, ok := node.(*ast.BinaryExpr); ok { if !isBoolOp(n.Op) { return w } diff --git a/vendor/github.com/mgechev/revive/rule/call_to_gc.go b/vendor/github.com/mgechev/revive/rule/call_to_gc.go index c3eb1bb71..b0bc8bbd4 100644 --- a/vendor/github.com/mgechev/revive/rule/call_to_gc.go +++ b/vendor/github.com/mgechev/revive/rule/call_to_gc.go @@ -3,6 +3,7 @@ package rule import ( "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -16,11 +17,7 @@ func (*CallToGCRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { failures = append(failures, failure) } - gcTriggeringFunctions := map[string]map[string]bool{ - "runtime": {"GC": true}, - } - - w := lintCallToGC{onFailure, gcTriggeringFunctions} + w := lintCallToGC{onFailure} ast.Walk(w, file.AST) return failures @@ -32,31 +29,17 @@ func (*CallToGCRule) Name() string { } type lintCallToGC struct { - onFailure func(lint.Failure) - gcTriggeringFunctions map[string]map[string]bool + onFailure func(lint.Failure) } func (w lintCallToGC) Visit(node ast.Node) ast.Visitor { ce, ok := node.(*ast.CallExpr) if !ok { - return w // nothing to do, the node is not a call - } - - fc, ok := ce.Fun.(*ast.SelectorExpr) - if !ok { - return nil // nothing to do, the call is not of the form pkg.func(...) - } - - id, ok := fc.X.(*ast.Ident) - - if !ok { - return nil // in case X is not an id (it should be!) + return w // nothing to do, the node is not a function call } - fn := fc.Sel.Name - pkg := id.Name - if !w.gcTriggeringFunctions[pkg][fn] { - return nil // it isn't a call to a GC triggering function + if !astutils.IsPkgDotName(ce.Fun, "runtime", "GC") { + return nil // nothing to do, the call is not a call to the Garbage Collector } w.onFailure(lint.Failure{ diff --git a/vendor/github.com/mgechev/revive/rule/cognitive_complexity.go b/vendor/github.com/mgechev/revive/rule/cognitive_complexity.go index 53aeae195..901fc60be 100644 --- a/vendor/github.com/mgechev/revive/rule/cognitive_complexity.go +++ b/vendor/github.com/mgechev/revive/rule/cognitive_complexity.go @@ -5,8 +5,9 @@ import ( "go/ast" "go/token" - "github.com/mgechev/revive/lint" "golang.org/x/tools/go/ast/astutil" + + "github.com/mgechev/revive/lint" ) // CognitiveComplexityRule sets restriction for maximum cognitive complexity. diff --git a/vendor/github.com/mgechev/revive/rule/comment_spacings.go b/vendor/github.com/mgechev/revive/rule/comment_spacings.go index 5187bb218..0c35fe392 100644 --- a/vendor/github.com/mgechev/revive/rule/comment_spacings.go +++ b/vendor/github.com/mgechev/revive/rule/comment_spacings.go @@ -8,7 +8,7 @@ import ( ) // CommentSpacingsRule check whether there is a space between -// the comment symbol( // ) and the start of the comment text +// the comment symbol( // ) and the start of the comment text. type CommentSpacingsRule struct { allowList []string } diff --git a/vendor/github.com/mgechev/revive/rule/confusing_naming.go b/vendor/github.com/mgechev/revive/rule/confusing_naming.go index 8a8ea13f8..83f53a596 100644 --- a/vendor/github.com/mgechev/revive/rule/confusing_naming.go +++ b/vendor/github.com/mgechev/revive/rule/confusing_naming.go @@ -6,6 +6,7 @@ import ( "strings" "sync" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -43,7 +44,7 @@ func (ps *packages) methodNames(lp *lint.Package) pkgMethods { var allPkgs = packages{pkgs: make([]pkgMethods, 1)} -// ConfusingNamingRule lints method names that differ only by capitalization +// ConfusingNamingRule lints method names that differ only by capitalization. type ConfusingNamingRule struct{} // Apply applies the rule to given file. @@ -112,9 +113,6 @@ func checkMethodName(holder string, id *ast.Ident, w *lintConfusingNames) { } // update the block list - if pkgm.methods[holder] == nil { - println("no entry for '", holder, "'") - } pkgm.methods[holder][name] = &referenceMethod{fileName: w.fileName, id: id} } @@ -126,7 +124,7 @@ type lintConfusingNames struct { const defaultStructName = "_" // used to map functions -// getStructName of a function receiver. Defaults to defaultStructName +// getStructName of a function receiver. Defaults to defaultStructName. func getStructName(r *ast.FieldList) string { result := defaultStructName @@ -159,8 +157,7 @@ func extractFromStarExpr(expr *ast.StarExpr) string { } func extractFromIndexExpr(expr *ast.IndexExpr) string { - switch v := expr.X.(type) { - case *ast.Ident: + if v, ok := expr.X.(*ast.Ident); ok { return v.Name } return defaultStructName @@ -170,6 +167,11 @@ func checkStructFields(fields *ast.FieldList, structName string, w *lintConfusin bl := make(map[string]bool, len(fields.List)) for _, f := range fields.List { for _, id := range f.Names { + // Skip blank identifiers + if id.Name == "_" { + continue + } + normName := strings.ToUpper(id.Name) if bl[normName] { w.onFailure(lint.Failure{ @@ -191,7 +193,7 @@ func (w *lintConfusingNames) Visit(n ast.Node) ast.Visitor { // Exclude naming warnings for functions that are exported to C but // not exported in the Go API. // See https://github.com/golang/lint/issues/144. - if ast.IsExported(v.Name.Name) || !isCgoExported(v) { + if ast.IsExported(v.Name.Name) || !astutils.IsCgoExported(v) { checkMethodName(getStructName(v.Recv), v.Name, w) } case *ast.TypeSpec: diff --git a/vendor/github.com/mgechev/revive/rule/confusing_results.go b/vendor/github.com/mgechev/revive/rule/confusing_results.go index 1be16f399..559c357f9 100644 --- a/vendor/github.com/mgechev/revive/rule/confusing_results.go +++ b/vendor/github.com/mgechev/revive/rule/confusing_results.go @@ -3,10 +3,11 @@ package rule import ( "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) -// ConfusingResultsRule lints given function declarations +// ConfusingResultsRule lints given function declarations. type ConfusingResultsRule struct{} // Apply applies the rule to given file. @@ -28,7 +29,7 @@ func (*ConfusingResultsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fai lastType := "" for _, result := range funcDecl.Type.Results.List { - resultTypeName := gofmt(result.Type) + resultTypeName := astutils.GoFmt(result.Type) if resultTypeName == lastType { failures = append(failures, lint.Failure{ diff --git a/vendor/github.com/mgechev/revive/rule/constant_logical_expr.go b/vendor/github.com/mgechev/revive/rule/constant_logical_expr.go index cb5dd746d..9bee07e02 100644 --- a/vendor/github.com/mgechev/revive/rule/constant_logical_expr.go +++ b/vendor/github.com/mgechev/revive/rule/constant_logical_expr.go @@ -4,6 +4,7 @@ import ( "go/ast" "go/token" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -35,13 +36,12 @@ type lintConstantLogicalExpr struct { } func (w *lintConstantLogicalExpr) Visit(node ast.Node) ast.Visitor { - switch n := node.(type) { - case *ast.BinaryExpr: + if n, ok := node.(*ast.BinaryExpr); ok { if !w.isOperatorWithLogicalResult(n.Op) { return w } - subExpressionsAreNotEqual := gofmt(n.X) != gofmt(n.Y) + subExpressionsAreNotEqual := astutils.GoFmt(n.X) != astutils.GoFmt(n.Y) if subExpressionsAreNotEqual { return w // nothing to say } diff --git a/vendor/github.com/mgechev/revive/rule/context_as_argument.go b/vendor/github.com/mgechev/revive/rule/context_as_argument.go index 273d96954..5a3e2cf69 100644 --- a/vendor/github.com/mgechev/revive/rule/context_as_argument.go +++ b/vendor/github.com/mgechev/revive/rule/context_as_argument.go @@ -5,6 +5,7 @@ import ( "go/ast" "strings" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -28,7 +29,7 @@ func (r *ContextAsArgumentRule) Apply(file *lint.File, _ lint.Arguments) []lint. // Flag any that show up after the first. isCtxStillAllowed := true for _, arg := range fnArgs { - argIsCtx := isPkgDot(arg.Type, "context", "Context") + argIsCtx := astutils.IsPkgDotName(arg.Type, "context", "Context") if argIsCtx && !isCtxStillAllowed { failures = append(failures, lint.Failure{ Node: arg, @@ -40,7 +41,7 @@ func (r *ContextAsArgumentRule) Apply(file *lint.File, _ lint.Arguments) []lint. break // only flag one } - typeName := gofmt(arg.Type) + typeName := astutils.GoFmt(arg.Type) // a parameter of type context.Context is still allowed if the current arg type is in the allow types LookUpTable _, isCtxStillAllowed = r.allowTypes[typeName] } diff --git a/vendor/github.com/mgechev/revive/rule/context_keys_type.go b/vendor/github.com/mgechev/revive/rule/context_keys_type.go index 02e1f9fa8..562f31b22 100644 --- a/vendor/github.com/mgechev/revive/rule/context_keys_type.go +++ b/vendor/github.com/mgechev/revive/rule/context_keys_type.go @@ -5,6 +5,7 @@ import ( "go/ast" "go/types" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -42,8 +43,7 @@ type lintContextKeyTypes struct { } func (w lintContextKeyTypes) Visit(n ast.Node) ast.Visitor { - switch n := n.(type) { - case *ast.CallExpr: + if n, ok := n.(*ast.CallExpr); ok { checkContextKeyType(w, n) } @@ -52,15 +52,7 @@ func (w lintContextKeyTypes) Visit(n ast.Node) ast.Visitor { func checkContextKeyType(w lintContextKeyTypes, x *ast.CallExpr) { f := w.file - sel, ok := x.Fun.(*ast.SelectorExpr) - if !ok { - return - } - pkg, ok := sel.X.(*ast.Ident) - if !ok || pkg.Name != "context" { - return - } - if sel.Sel.Name != "WithValue" { + if !astutils.IsPkgDotName(x.Fun, "context", "WithValue") { return } diff --git a/vendor/github.com/mgechev/revive/rule/datarace.go b/vendor/github.com/mgechev/revive/rule/datarace.go index 4092c06c8..de63c068d 100644 --- a/vendor/github.com/mgechev/revive/rule/datarace.go +++ b/vendor/github.com/mgechev/revive/rule/datarace.go @@ -4,9 +4,13 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) +//nolint:staticcheck // TODO: ast.Object is deprecated +type nodeUID *ast.Object // type of the unique id for AST nodes + // DataRaceRule lints assignments to value method-receivers. type DataRaceRule struct{} @@ -22,8 +26,7 @@ func (r *DataRaceRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { funcResults := funcDecl.Type.Results - // TODO: ast.Object is deprecated - returnIDs := map[*ast.Object]struct{}{} + returnIDs := map[nodeUID]struct{}{} if funcResults != nil { returnIDs = r.extractReturnIDs(funcResults.List) } @@ -35,7 +38,7 @@ func (r *DataRaceRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { fl := &lintFunctionForDataRaces{ onFailure: onFailure, returnIDs: returnIDs, - rangeIDs: map[*ast.Object]struct{}{}, // TODO: ast.Object is deprecated + rangeIDs: map[nodeUID]struct{}{}, go122for: isGo122, } @@ -50,9 +53,8 @@ func (*DataRaceRule) Name() string { return "datarace" } -// TODO: ast.Object is deprecated -func (*DataRaceRule) extractReturnIDs(fields []*ast.Field) map[*ast.Object]struct{} { - r := map[*ast.Object]struct{}{} +func (*DataRaceRule) extractReturnIDs(fields []*ast.Field) map[nodeUID]struct{} { + r := map[nodeUID]struct{}{} for _, f := range fields { for _, id := range f.Names { r[id.Obj] = struct{}{} @@ -65,8 +67,8 @@ func (*DataRaceRule) extractReturnIDs(fields []*ast.Field) map[*ast.Object]struc type lintFunctionForDataRaces struct { _ struct{} onFailure func(failure lint.Failure) - returnIDs map[*ast.Object]struct{} // TODO: ast.Object is deprecated - rangeIDs map[*ast.Object]struct{} // TODO: ast.Object is deprecated + returnIDs map[nodeUID]struct{} + rangeIDs map[nodeUID]struct{} go122for bool } @@ -111,7 +113,7 @@ func (w lintFunctionForDataRaces) Visit(node ast.Node) ast.Visitor { return ok } - ids := pick(funcLit.Body, selectIDs) + ids := astutils.PickNodes(funcLit.Body, selectIDs) for _, id := range ids { id := id.(*ast.Ident) _, isRangeID := w.rangeIDs[id.Obj] diff --git a/vendor/github.com/mgechev/revive/rule/deep_exit.go b/vendor/github.com/mgechev/revive/rule/deep_exit.go index 6f7acd305..ed3e34b53 100644 --- a/vendor/github.com/mgechev/revive/rule/deep_exit.go +++ b/vendor/github.com/mgechev/revive/rule/deep_exit.go @@ -7,6 +7,7 @@ import ( "unicode" "unicode/utf8" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -64,12 +65,18 @@ func (w *lintDeepExit) Visit(node ast.Node) ast.Visitor { pkg := id.Name fn := fc.Sel.Name - if isCallToExitFunction(pkg, fn) { + if isCallToExitFunction(pkg, fn, ce.Args) { + msg := fmt.Sprintf("calls to %s.%s only in main() or init() functions", pkg, fn) + + if pkg == "flag" && fn == "NewFlagSet" && + len(ce.Args) == 2 && astutils.IsPkgDotName(ce.Args[1], "flag", "ExitOnError") { + msg = "calls to flag.NewFlagSet with flag.ExitOnError only in main() or init() functions" + } w.onFailure(lint.Failure{ Confidence: 1, Node: ce, Category: lint.FailureCategoryBadPractice, - Failure: fmt.Sprintf("calls to %s.%s only in main() or init() functions", pkg, fn), + Failure: msg, }) } diff --git a/vendor/github.com/mgechev/revive/rule/defer.go b/vendor/github.com/mgechev/revive/rule/defer.go index 70213aed1..a85336846 100644 --- a/vendor/github.com/mgechev/revive/rule/defer.go +++ b/vendor/github.com/mgechev/revive/rule/defer.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -86,7 +87,7 @@ type lintDeferRule struct { onFailure func(lint.Failure) inALoop bool inADefer bool - inAFuncLit bool + inAFuncLit byte // 0 = not in func lit, 1 = in top-level func lit, >1 = nested func lit allow map[string]bool } @@ -99,21 +100,21 @@ func (w lintDeferRule) Visit(node ast.Node) ast.Visitor { w.visitSubtree(n.Body, w.inADefer, true, w.inAFuncLit) return nil case *ast.FuncLit: - w.visitSubtree(n.Body, w.inADefer, false, true) + w.visitSubtree(n.Body, w.inADefer, false, w.inAFuncLit+1) return nil case *ast.ReturnStmt: - if len(n.Results) != 0 && w.inADefer && w.inAFuncLit { + if len(n.Results) != 0 && w.inADefer && w.inAFuncLit == 1 { w.newFailure("return in a defer function has no effect", n, 1.0, lint.FailureCategoryLogic, deferOptionReturn) } case *ast.CallExpr: - isCallToRecover := isIdent(n.Fun, "recover") + isCallToRecover := astutils.IsIdent(n.Fun, "recover") switch { case !w.inADefer && isCallToRecover: // func fn() { recover() } // // confidence is not 1 because recover can be in a function that is deferred elsewhere w.newFailure("recover must be called inside a deferred function", n, 0.8, lint.FailureCategoryLogic, deferOptionRecover) - case w.inADefer && !w.inAFuncLit && isCallToRecover: + case w.inADefer && w.inAFuncLit == 0 && isCallToRecover: // defer helper(recover()) // // confidence is not truly 1 because this could be in a correctly-deferred func, @@ -122,20 +123,20 @@ func (w lintDeferRule) Visit(node ast.Node) ast.Visitor { } return nil // no need to analyze the arguments of the function call case *ast.DeferStmt: - if isIdent(n.Call.Fun, "recover") { + if astutils.IsIdent(n.Call.Fun, "recover") { // defer recover() // // confidence is not truly 1 because this could be in a correctly-deferred func, // but normally this doesn't suppress a panic, and even if it did it would silently discard the value. w.newFailure("recover must be called inside a deferred function, this is executing recover immediately", n, 1, lint.FailureCategoryLogic, deferOptionImmediateRecover) } - w.visitSubtree(n.Call.Fun, true, false, false) + w.visitSubtree(n.Call.Fun, true, false, 0) for _, a := range n.Call.Args { switch a.(type) { case *ast.FuncLit: continue // too hard to analyze deferred calls with func literals args default: - w.visitSubtree(a, true, false, false) // check arguments, they should not contain recover() + w.visitSubtree(a, true, false, 0) // check arguments, they should not contain recover() } } @@ -161,7 +162,7 @@ func (w lintDeferRule) Visit(node ast.Node) ast.Visitor { return w } -func (w lintDeferRule) visitSubtree(n ast.Node, inADefer, inALoop, inAFuncLit bool) { +func (w lintDeferRule) visitSubtree(n ast.Node, inADefer, inALoop bool, inAFuncLit byte) { nw := lintDeferRule{ onFailure: w.onFailure, inADefer: inADefer, diff --git a/vendor/github.com/mgechev/revive/rule/dot_imports.go b/vendor/github.com/mgechev/revive/rule/dot_imports.go index bb86a733b..a5f2210c5 100644 --- a/vendor/github.com/mgechev/revive/rule/dot_imports.go +++ b/vendor/github.com/mgechev/revive/rule/dot_imports.go @@ -3,6 +3,7 @@ package rule import ( "fmt" "go/ast" + "strconv" "github.com/mgechev/revive/lint" ) @@ -94,7 +95,7 @@ func (w lintImports) Visit(_ ast.Node) ast.Visitor { type allowPackages map[string]struct{} func (ap allowPackages) add(pkg string) { - ap[fmt.Sprintf(`"%s"`, pkg)] = struct{}{} // import path strings are with double quotes + ap[strconv.Quote(pkg)] = struct{}{} // import path strings are with double quotes } func (ap allowPackages) isAllowedPackage(pkg string) bool { diff --git a/vendor/github.com/mgechev/revive/rule/early_return.go b/vendor/github.com/mgechev/revive/rule/early_return.go index 95ba0676a..2c2b67f4d 100644 --- a/vendor/github.com/mgechev/revive/rule/early_return.go +++ b/vendor/github.com/mgechev/revive/rule/early_return.go @@ -52,7 +52,7 @@ func (*EarlyReturnRule) Name() string { func (e *EarlyReturnRule) checkIfElse(chain ifelse.Chain) (string, bool) { if chain.HasElse { - if !chain.Else.BranchKind.Deviates() { + if !chain.Else.Deviates() { // this rule only applies if the else-block deviates control flow return "", false } diff --git a/vendor/github.com/mgechev/revive/rule/enforce_map_style.go b/vendor/github.com/mgechev/revive/rule/enforce_map_style.go index df9793bb6..3292db0ba 100644 --- a/vendor/github.com/mgechev/revive/rule/enforce_map_style.go +++ b/vendor/github.com/mgechev/revive/rule/enforce_map_style.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -101,8 +102,7 @@ func (r *EnforceMapStyleRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fa return true } - ident, ok := v.Fun.(*ast.Ident) - if !ok || ident.Name != "make" { + if !astutils.IsIdent(v.Fun, "make") { return true } diff --git a/vendor/github.com/mgechev/revive/rule/enforce_repeated_arg_type_style.go b/vendor/github.com/mgechev/revive/rule/enforce_repeated_arg_type_style.go index 8a5d9b362..9def128aa 100644 --- a/vendor/github.com/mgechev/revive/rule/enforce_repeated_arg_type_style.go +++ b/vendor/github.com/mgechev/revive/rule/enforce_repeated_arg_type_style.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -111,8 +112,7 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, _ lint.Argument astFile := file.AST ast.Inspect(astFile, func(n ast.Node) bool { - switch fn := n.(type) { - case *ast.FuncDecl: + if fn, ok := n.(*ast.FuncDecl); ok { switch r.funcArgStyle { case enforceRepeatedArgTypeStyleTypeFull: if fn.Type.Params != nil { @@ -131,8 +131,8 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, _ lint.Argument if fn.Type.Params != nil { var prevType ast.Expr for _, field := range fn.Type.Params.List { - prevTypeStr := gofmt(prevType) - currentTypeStr := gofmt(field.Type) + prevTypeStr := astutils.GoFmt(prevType) + currentTypeStr := astutils.GoFmt(field.Type) if currentTypeStr == prevTypeStr { failures = append(failures, lint.Failure{ Confidence: 1, @@ -164,8 +164,8 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, _ lint.Argument if fn.Type.Results != nil { var prevType ast.Expr for _, field := range fn.Type.Results.List { - prevTypeStr := gofmt(prevType) - currentTypeStr := gofmt(field.Type) + prevTypeStr := astutils.GoFmt(prevType) + currentTypeStr := astutils.GoFmt(field.Type) if field.Names != nil && currentTypeStr == prevTypeStr { failures = append(failures, lint.Failure{ Confidence: 1, diff --git a/vendor/github.com/mgechev/revive/rule/enforce_slice_style.go b/vendor/github.com/mgechev/revive/rule/enforce_slice_style.go index ab503094f..9bc26a6a4 100644 --- a/vendor/github.com/mgechev/revive/rule/enforce_slice_style.go +++ b/vendor/github.com/mgechev/revive/rule/enforce_slice_style.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -117,8 +118,7 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, _ lint.Arguments) []lint. return true } - ident, ok := v.Fun.(*ast.Ident) - if !ok || ident.Name != "make" { + if !astutils.IsIdent(v.Fun, "make") { return true } diff --git a/vendor/github.com/mgechev/revive/rule/enforce_switch_style.go b/vendor/github.com/mgechev/revive/rule/enforce_switch_style.go new file mode 100644 index 000000000..96093d620 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/enforce_switch_style.go @@ -0,0 +1,134 @@ +package rule + +import ( + "fmt" + "go/ast" + "go/token" + + "github.com/mgechev/revive/lint" +) + +// EnforceSwitchStyleRule implements a rule to enforce default clauses use and/or position. +type EnforceSwitchStyleRule struct { + allowNoDefault bool // allow absence of default + allowDefaultNotLast bool // allow default, if present, not being the last case +} + +// Configure validates the rule configuration, and configures the rule accordingly. +// +// Configuration implements the [lint.ConfigurableRule] interface. +func (r *EnforceSwitchStyleRule) Configure(arguments lint.Arguments) error { + if len(arguments) < 1 { + return nil + } + + for _, arg := range arguments { + argStr, ok := arg.(string) + if !ok { + return fmt.Errorf("invalid argument for rule %s; expected string but got %T", r.Name(), arg) + } + switch { + case isRuleOption(argStr, "allowNoDefault"): + r.allowNoDefault = true + case isRuleOption(argStr, "allowDefaultNotLast"): + r.allowDefaultNotLast = true + default: + return fmt.Errorf(`invalid argument %q for rule %s; expected "allowNoDefault" or "allowDefaultNotLast"`, argStr, r.Name()) + } + } + + return nil +} + +// Apply applies the rule to given file. +func (r *EnforceSwitchStyleRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + astFile := file.AST + ast.Inspect(astFile, func(n ast.Node) bool { + switchNode, ok := n.(*ast.SwitchStmt) + if !ok { + return true // not a switch statement + } + + defaultClause, isLast := r.seekDefaultCase(switchNode.Body) + hasDefault := defaultClause != nil + + if !hasDefault && r.allowNoDefault { + return true // switch without default but the rule is configured to don´t care + } + + if !hasDefault && !r.allowNoDefault { + // switch without default + if !r.allBranchesEndWithJumpStmt(switchNode) { + failures = append(failures, lint.Failure{ + Confidence: 1, + Node: switchNode, + Category: lint.FailureCategoryStyle, + Failure: "switch must have a default case clause", + }) + } + + return true + } + + // the switch has a default + + if r.allowDefaultNotLast || isLast { + return true + } + + failures = append(failures, lint.Failure{ + Confidence: 1, + Node: defaultClause, + Category: lint.FailureCategoryStyle, + Failure: "default case clause must be the last one", + }) + + return true + }) + + return failures +} + +func (*EnforceSwitchStyleRule) seekDefaultCase(body *ast.BlockStmt) (defaultClause *ast.CaseClause, isLast bool) { + var last *ast.CaseClause + for _, stmt := range body.List { + cc, _ := stmt.(*ast.CaseClause) // no need to check for ok + last = cc + if cc.List == nil { // a nil List means "default" + defaultClause = cc + } + } + + return defaultClause, defaultClause == last +} + +func (*EnforceSwitchStyleRule) allBranchesEndWithJumpStmt(switchStmt *ast.SwitchStmt) bool { + for _, stmt := range switchStmt.Body.List { + caseClause := stmt.(*ast.CaseClause) // safe to assume stmt is a case clause + + caseBody := caseClause.Body + if caseBody == nil { + return false + } + + lastStmt := caseBody[len(caseBody)-1] + + if _, ok := lastStmt.(*ast.ReturnStmt); ok { + continue + } + + if jump, ok := lastStmt.(*ast.BranchStmt); ok && jump.Tok == token.BREAK { + continue + } + + return false + } + + return true +} + +// Name returns the rule name. +func (*EnforceSwitchStyleRule) Name() string { + return "enforce-switch-style" +} diff --git a/vendor/github.com/mgechev/revive/rule/error_naming.go b/vendor/github.com/mgechev/revive/rule/error_naming.go index 5ae490813..6de9c3116 100644 --- a/vendor/github.com/mgechev/revive/rule/error_naming.go +++ b/vendor/github.com/mgechev/revive/rule/error_naming.go @@ -6,6 +6,7 @@ import ( "go/token" "strings" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -56,11 +57,22 @@ func (w lintErrors) Visit(_ ast.Node) ast.Visitor { if !ok { continue } - if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") { + if !astutils.IsPkgDotName(ce.Fun, "errors", "New") && !astutils.IsPkgDotName(ce.Fun, "fmt", "Errorf") { continue } id := spec.Names[0] + if id.Name == "_" { + // avoid false positive for blank identifier + + // The fact that the error variable is not used + // is out of the scope of the rule + + // This pattern that can be found in benchmarks and examples + // should be allowed. + continue + } + prefix := "err" if id.IsExported() { prefix = "Err" diff --git a/vendor/github.com/mgechev/revive/rule/error_return.go b/vendor/github.com/mgechev/revive/rule/error_return.go index 19f10a661..812ca753c 100644 --- a/vendor/github.com/mgechev/revive/rule/error_return.go +++ b/vendor/github.com/mgechev/revive/rule/error_return.go @@ -3,6 +3,7 @@ package rule import ( "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -21,7 +22,7 @@ func (*ErrorReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure } funcResults := funcDecl.Type.Results.List - isLastResultError := isIdent(funcResults[len(funcResults)-1].Type, "error") + isLastResultError := astutils.IsIdent(funcResults[len(funcResults)-1].Type, "error") if isLastResultError { continue } @@ -29,7 +30,7 @@ func (*ErrorReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure // An error return parameter should be the last parameter. // Flag any error parameters found before the last. for _, r := range funcResults[:len(funcResults)-1] { - if isIdent(r.Type, "error") { + if astutils.IsIdent(r.Type, "error") { failures = append(failures, lint.Failure{ Category: lint.FailureCategoryStyle, Confidence: 0.9, diff --git a/vendor/github.com/mgechev/revive/rule/error_strings.go b/vendor/github.com/mgechev/revive/rule/error_strings.go index ea295f8d1..53a585bfb 100644 --- a/vendor/github.com/mgechev/revive/rule/error_strings.go +++ b/vendor/github.com/mgechev/revive/rule/error_strings.go @@ -88,7 +88,7 @@ type lintErrorStrings struct { onFailure func(lint.Failure) } -// Visit browses the AST +// Visit browses the AST. func (w lintErrorStrings) Visit(n ast.Node) ast.Visitor { ce, ok := n.(*ast.CallExpr) if !ok { @@ -126,8 +126,8 @@ func (w lintErrorStrings) Visit(n ast.Node) ast.Visitor { return w } -// match returns true if the expression corresponds to the known pkg.function -// i.e.: errors.Wrap +// match returns true if the expression corresponds to the known pkg.function, +// i.e.: errors.Wrap. func (w lintErrorStrings) match(expr *ast.CallExpr) bool { sel, ok := expr.Fun.(*ast.SelectorExpr) if !ok { @@ -147,8 +147,8 @@ func (w lintErrorStrings) match(expr *ast.CallExpr) bool { return ok } -// getMessage returns the message depending on its position -// returns false if the cast is unsuccessful +// getMessage returns the message depending on its position. +// Returns false if the cast is unsuccessful. func (w lintErrorStrings) getMessage(expr *ast.CallExpr) (s *ast.BasicLit, success bool) { str, ok := w.checkArg(expr, 0) if ok { diff --git a/vendor/github.com/mgechev/revive/rule/errorf.go b/vendor/github.com/mgechev/revive/rule/errorf.go index cd56fe29c..a7c115944 100644 --- a/vendor/github.com/mgechev/revive/rule/errorf.go +++ b/vendor/github.com/mgechev/revive/rule/errorf.go @@ -6,6 +6,7 @@ import ( "regexp" "strings" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -47,7 +48,7 @@ func (w lintErrorf) Visit(n ast.Node) ast.Visitor { if !ok || len(ce.Args) != 1 { return w } - isErrorsNew := isPkgDot(ce.Fun, "errors", "New") + isErrorsNew := astutils.IsPkgDotName(ce.Fun, "errors", "New") var isTestingError bool se, ok := ce.Fun.(*ast.SelectorExpr) if ok && se.Sel.Name == "Error" { @@ -60,7 +61,7 @@ func (w lintErrorf) Visit(n ast.Node) ast.Visitor { } arg := ce.Args[0] ce, ok = arg.(*ast.CallExpr) - if !ok || !isPkgDot(ce.Fun, "fmt", "Sprintf") { + if !ok || !astutils.IsPkgDotName(ce.Fun, "fmt", "Sprintf") { return w } errorfPrefix := "fmt" diff --git a/vendor/github.com/mgechev/revive/rule/exported.go b/vendor/github.com/mgechev/revive/rule/exported.go index 2bcc458af..eb351cf4d 100644 --- a/vendor/github.com/mgechev/revive/rule/exported.go +++ b/vendor/github.com/mgechev/revive/rule/exported.go @@ -12,7 +12,7 @@ import ( "github.com/mgechev/revive/lint" ) -// disabledChecks store ignored warnings types +// disabledChecks store ignored warnings types. type disabledChecks struct { Const bool Function bool @@ -30,7 +30,7 @@ const ( checkNameStuttering = "stuttering" ) -// isDisabled returns true if the given check is disabled, false otherwise +// isDisabled returns true if the given check is disabled, false otherwise. func (dc *disabledChecks) isDisabled(checkName string) bool { switch checkName { case "var": @@ -110,11 +110,11 @@ func (r *ExportedRule) Configure(arguments lint.Arguments) error { // Apply applies the rule to given file. func (r *ExportedRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { - var failures []lint.Failure - if file.IsTest() { - return failures + if !file.IsImportable() { + return nil } + var failures []lint.Failure walker := lintExported{ file: file, onFailure: func(failure lint.Failure) { @@ -165,21 +165,36 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { return } - firstCommentLine := firstCommentLine(fn.Doc) - - if firstCommentLine == "" { - w.addFailuref(fn, 1, lint.FailureCategoryComments, + status := w.checkGoDocStatus(fn.Doc, fn.Name.Name) + switch status { + case exportedGoDocStatusOK: + return // comment is fine + case exportedGoDocStatusMissing: + w.addFailuref(fn, status.Confidence(), lint.FailureCategoryComments, "exported %s %s should have comment or be unexported", kind, name, ) return } - prefix := fn.Name.Name + " " - if !strings.HasPrefix(firstCommentLine, prefix) { - w.addFailuref(fn.Doc, 0.8, lint.FailureCategoryComments, - `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix, - ) + firstCommentLine := w.firstCommentLine(fn.Doc) + w.addFailuref(fn.Doc, status.Confidence(), lint.FailureCategoryComments, + `comment on exported %s %s should be of the form "%s ..."%s`, kind, name, fn.Name.Name, status.CorrectionHint(firstCommentLine), + ) +} + +func (*lintExported) hasPrefixInsensitive(s, prefix string) bool { + return strings.HasPrefix(strings.ToLower(s), strings.ToLower(prefix)) +} + +func (*lintExported) stripFirstRune(s string) string { + // Decode the first rune to handle multi-byte characters. + firstRune, size := utf8.DecodeRuneInString(s) + if firstRune == utf8.RuneError { + return s // no valid first rune found } + + // Return the string without the first rune. + return s[size:] } func (w *lintExported) checkRepetitiveNames(id *ast.Ident, thing string) { @@ -233,28 +248,28 @@ func (w *lintExported) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup, first return } + expectedPrefix := typeName for _, a := range articles { if typeName == a { continue } var found bool if firstCommentLine, found = strings.CutPrefix(firstCommentLine, a+" "); found { + expectedPrefix = a + " " + typeName break } } - // if comment starts with name of type and has some text after - it's ok - expectedPrefix := typeName + " " - if strings.HasPrefix(firstCommentLine, expectedPrefix) { + status := w.checkGoDocStatus(doc, expectedPrefix) + if status == exportedGoDocStatusOK { return } - - w.addFailuref(doc, 1, lint.FailureCategoryComments, - `comment on exported type %v should be of the form "%s..." (with optional leading article)`, t.Name, expectedPrefix, + w.addFailuref(doc, status.Confidence(), lint.FailureCategoryComments, + `comment on exported type %v should be of the form "%s ..." (with optional leading article)%s`, t.Name, typeName, status.CorrectionHint(firstCommentLine), ) } -// checkValueNames returns true if names check, false otherwise +// checkValueNames returns true if names check, false otherwise. func (w *lintExported) checkValueNames(names []*ast.Ident, nodeToBlame ast.Node, kind string) bool { // Check that none are exported except for the first. if len(names) < 2 { @@ -272,6 +287,7 @@ func (w *lintExported) checkValueNames(names []*ast.Ident, nodeToBlame ast.Node, return true } + func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genDeclMissingComments map[*ast.GenDecl]bool) { kind := "var" if gd.Tok == token.CONST { @@ -292,8 +308,8 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD return } - vsFirstCommentLine := firstCommentLine(vs.Doc) - gdFirstCommentLine := firstCommentLine(gd.Doc) + vsFirstCommentLine := w.firstCommentLine(vs.Doc) + gdFirstCommentLine := w.firstCommentLine(gd.Doc) if vsFirstCommentLine == "" && gdFirstCommentLine == "" { if genDeclMissingComments[gd] { return @@ -325,20 +341,77 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD default: doc = gd.Doc } + firstCommentLine := w.firstCommentLine(doc) - prefix := name + " " - if !strings.HasPrefix(firstCommentLine(doc), prefix) { - w.addFailuref(doc, 1, lint.FailureCategoryComments, - `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix, - ) + status := w.checkGoDocStatus(doc, name) + if status == exportedGoDocStatusOK { + return + } + w.addFailuref(doc, status.Confidence(), lint.FailureCategoryComments, + `comment on exported %s %s should be of the form "%s ..."%s`, kind, name, name, status.CorrectionHint(firstCommentLine), + ) +} + +type exportedGoDocStatus int + +const ( + exportedGoDocStatusOK exportedGoDocStatus = iota + exportedGoDocStatusMissing + exportedGoDocStatusCaseMismatch + exportedGoDocStatusFirstLetterMismatch + exportedGoDocStatusUnexpected +) + +func (gds exportedGoDocStatus) Confidence() float64 { + if gds == exportedGoDocStatusUnexpected { + return 0.8 + } + return 1 +} + +func (gds exportedGoDocStatus) CorrectionHint(firstCommentLine string) string { + firstWord := strings.Split(firstCommentLine, " ")[0] + switch gds { + case exportedGoDocStatusCaseMismatch: + return ` by using its correct casing, not "` + firstWord + ` ..."` + case exportedGoDocStatusFirstLetterMismatch: + return ` to match its exported status, not "` + firstWord + ` ..."` } + + return "" +} + +func (w *lintExported) checkGoDocStatus(comment *ast.CommentGroup, name string) exportedGoDocStatus { + firstCommentLine := w.firstCommentLine(comment) + if firstCommentLine == "" { + return exportedGoDocStatusMissing + } + + name = strings.TrimSpace(name) + // Make sure the expected prefix has a space at the end. + expectedPrefix := name + " " + if strings.HasPrefix(firstCommentLine, expectedPrefix) { + return exportedGoDocStatusOK + } + + if !w.hasPrefixInsensitive(firstCommentLine, expectedPrefix) { + return exportedGoDocStatusUnexpected + } + + if strings.HasPrefix(w.stripFirstRune(firstCommentLine), w.stripFirstRune(expectedPrefix)) { + // Only the first character differs, such as "sendJSON" became "SendJSON". + // so we consider the scope has changed. + return exportedGoDocStatusFirstLetterMismatch + } + + return exportedGoDocStatusCaseMismatch } // firstCommentLine yields the first line of interest in comment group or "" if there is nothing of interest. // An "interesting line" is a comment line that is neither a directive (e.g. //go:...) or a deprecation comment // (lines from the first line with a prefix // Deprecated: to the end of the comment group) // Empty or spaces-only lines are discarded. -func firstCommentLine(comment *ast.CommentGroup) (result string) { +func (lintExported) firstCommentLine(comment *ast.CommentGroup) (result string) { if comment == nil { return "" } @@ -384,10 +457,10 @@ func (w *lintExported) Visit(n ast.Node) ast.Visitor { // inside a GenDecl, which usually has the doc doc := v.Doc - fcl := firstCommentLine(doc) + fcl := w.firstCommentLine(doc) if fcl == "" { doc = w.lastGenDecl.Doc - fcl = firstCommentLine(doc) + fcl = w.firstCommentLine(doc) } w.lintTypeDoc(v, doc, fcl) w.checkRepetitiveNames(v.Name, "type") @@ -421,24 +494,26 @@ func (w *lintExported) lintInterfaceMethod(typeName string, m *ast.Field) { if !ast.IsExported(m.Names[0].Name) { return } + name := m.Names[0].Name - firstCommentLine := firstCommentLine(m.Doc) - if firstCommentLine == "" { - w.addFailuref(m, 1, lint.FailureCategoryComments, + status := w.checkGoDocStatus(m.Doc, name) + switch status { + case exportedGoDocStatusOK: + return // comment is fine + case exportedGoDocStatusMissing: + w.addFailuref(m, status.Confidence(), lint.FailureCategoryComments, "public interface method %s.%s should be commented", typeName, name, ) return } - expectedPrefix := m.Names[0].Name + " " - if !strings.HasPrefix(firstCommentLine, expectedPrefix) { - w.addFailuref(m.Doc, 0.8, lint.FailureCategoryComments, - `comment on exported interface method %s.%s should be of the form "%s..."`, typeName, name, expectedPrefix, - ) - } + firstCommentLine := w.firstCommentLine(m.Doc) + w.addFailuref(m.Doc, status.Confidence(), lint.FailureCategoryComments, + `comment on exported interface method %s.%s should be of the form "%s ..."%s`, typeName, name, name, status.CorrectionHint(firstCommentLine), + ) } -// mustCheckMethod returns true if the method must be checked by this rule, false otherwise +// mustCheckMethod returns true if the method must be checked by this rule, false otherwise. func (w *lintExported) mustCheckMethod(fn *ast.FuncDecl) bool { recv := typeparams.ReceiverType(fn) diff --git a/vendor/github.com/mgechev/revive/rule/file_length_limit.go b/vendor/github.com/mgechev/revive/rule/file_length_limit.go index a9b4e8da9..c24db4353 100644 --- a/vendor/github.com/mgechev/revive/rule/file_length_limit.go +++ b/vendor/github.com/mgechev/revive/rule/file_length_limit.go @@ -57,7 +57,7 @@ func (r *FileLengthLimitRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fa return []lint.Failure{ { - Category: lint.FailureCategoryCodeStyle, + Category: lint.FailureCategoryStyle, Confidence: 1, Position: lint.FailurePosition{ Start: token.Position{ diff --git a/vendor/github.com/mgechev/revive/rule/filename_format.go b/vendor/github.com/mgechev/revive/rule/filename_format.go index 6d4905f18..200ffbde0 100644 --- a/vendor/github.com/mgechev/revive/rule/filename_format.go +++ b/vendor/github.com/mgechev/revive/rule/filename_format.go @@ -9,7 +9,7 @@ import ( "github.com/mgechev/revive/lint" ) -// FilenameFormatRule lints source filenames according to a set of regular expressions given as arguments +// FilenameFormatRule lints source filenames according to a set of regular expressions given as arguments. type FilenameFormatRule struct { format *regexp.Regexp } diff --git a/vendor/github.com/mgechev/revive/rule/flag_param.go b/vendor/github.com/mgechev/revive/rule/flag_param.go index 2f69503ca..54edcadc6 100644 --- a/vendor/github.com/mgechev/revive/rule/flag_param.go +++ b/vendor/github.com/mgechev/revive/rule/flag_param.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -26,7 +27,7 @@ func (*FlagParamRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { boolParams := map[string]struct{}{} for _, param := range fd.Type.Params.List { - if !isIdent(param.Type, "bool") { + if !astutils.IsIdent(param.Type, "bool") { continue } @@ -77,9 +78,8 @@ func (w conditionVisitor) Visit(node ast.Node) ast.Visitor { return w.idents[ident.Name] == struct{}{} } - uses := pick(ifStmt.Cond, findUsesOfIdents) - - if len(uses) < 1 { + uses := astutils.SeekNode[*ast.Ident](ifStmt.Cond, findUsesOfIdents) + if uses == nil { return w } @@ -87,7 +87,7 @@ func (w conditionVisitor) Visit(node ast.Node) ast.Visitor { Confidence: 1, Node: w.fd.Type.Params, Category: lint.FailureCategoryBadPractice, - Failure: fmt.Sprintf("parameter '%s' seems to be a control flag, avoid control coupling", uses[0]), + Failure: fmt.Sprintf("parameter '%s' seems to be a control flag, avoid control coupling", uses.Name), }) return nil diff --git a/vendor/github.com/mgechev/revive/rule/forbidden_call_in_wg_go.go b/vendor/github.com/mgechev/revive/rule/forbidden_call_in_wg_go.go new file mode 100644 index 000000000..63088e554 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/forbidden_call_in_wg_go.go @@ -0,0 +1,113 @@ +package rule + +import ( + "fmt" + "go/ast" + "strings" + + "github.com/mgechev/revive/internal/astutils" + "github.com/mgechev/revive/lint" +) + +// ForbiddenCallInWgGoRule spots calls to panic or wg.Done when using WaitGroup.Go. +type ForbiddenCallInWgGoRule struct{} + +// Apply applies the rule to given file. +func (*ForbiddenCallInWgGoRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + if !file.Pkg.IsAtLeastGoVersion(lint.Go125) { + return nil // skip analysis if Go version < 1.25 + } + + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + w := &lintForbiddenCallInWgGo{ + onFailure: onFailure, + } + + // Iterate over declarations looking for function declarations + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok { + continue // not a function + } + + if fn.Body == nil { + continue // external (no-Go) function + } + + // Analyze the function body + ast.Walk(w, fn.Body) + } + + return failures +} + +// Name returns the rule name. +func (*ForbiddenCallInWgGoRule) Name() string { + return "forbidden-call-in-wg-go" +} + +type lintForbiddenCallInWgGo struct { + onFailure func(lint.Failure) +} + +func (w *lintForbiddenCallInWgGo) Visit(node ast.Node) ast.Visitor { + call, ok := node.(*ast.CallExpr) + if !ok { + return w // not a call of statements + } + + if !astutils.IsPkgDotName(call.Fun, "wg", "Go") { + return w // not a call to wg.Go + } + + if len(call.Args) != 1 { + return nil // no argument (impossible) + } + + funcLit, ok := call.Args[0].(*ast.FuncLit) + if !ok { + return nil // the argument is not a function literal + } + + var callee string + + forbiddenCallPicker := func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok { + return false + } + + if astutils.IsPkgDotName(call.Fun, "wg", "Done") || + astutils.IsIdent(call.Fun, "panic") || + astutils.IsPkgDotName(call.Fun, "log", "Panic") || + astutils.IsPkgDotName(call.Fun, "log", "Panicf") || + astutils.IsPkgDotName(call.Fun, "log", "Panicln") { + callee = astutils.GoFmt(n) + callee, _, _ = strings.Cut(callee, "(") + return true + } + + return false + } + + // search a forbidden call in the body of the function literal + forbiddenCall := astutils.SeekNode[*ast.CallExpr](funcLit.Body, forbiddenCallPicker) + if forbiddenCall == nil { + return nil // there is no forbidden call in the call to wg.Go + } + + msg := fmt.Sprintf("do not call %s inside wg.Go", callee) + w.onFailure(lint.Failure{ + Confidence: 1, + Node: forbiddenCall, + Category: lint.FailureCategoryErrors, + Failure: msg, + }) + + return nil +} diff --git a/vendor/github.com/mgechev/revive/rule/get_return.go b/vendor/github.com/mgechev/revive/rule/get_return.go index cf58a687c..a6230e082 100644 --- a/vendor/github.com/mgechev/revive/rule/get_return.go +++ b/vendor/github.com/mgechev/revive/rule/get_return.go @@ -5,6 +5,7 @@ import ( "go/ast" "strings" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -29,6 +30,10 @@ func (*GetReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { continue } + if isHTTPHandler(fd.Type.Params) { + continue // the Get prefix in the function name refers to HTTP GET + } + failures = append(failures, lint.Failure{ Confidence: 0.8, Node: fd, @@ -69,3 +74,15 @@ func isGetter(name string) bool { func hasResults(rs *ast.FieldList) bool { return rs != nil && len(rs.List) > 0 } + +// isHTTPHandler returns true if the given params match with the signature of an HTTP handler, false otherwise +// A params list is considered to be an HTTP handler if the first two parameters are +// http.ResponseWriter, *http.Request in that order. +func isHTTPHandler(params *ast.FieldList) bool { + typeNames := astutils.GetTypeNames(params) + if len(typeNames) < 2 { + return false + } + + return typeNames[0] == "http.ResponseWriter" && typeNames[1] == "*http.Request" +} diff --git a/vendor/github.com/mgechev/revive/rule/identical_branches.go b/vendor/github.com/mgechev/revive/rule/identical_branches.go index 044b04147..22895cde6 100644 --- a/vendor/github.com/mgechev/revive/rule/identical_branches.go +++ b/vendor/github.com/mgechev/revive/rule/identical_branches.go @@ -3,10 +3,11 @@ package rule import ( "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) -// IdenticalBranchesRule warns on constant logical expressions. +// IdenticalBranchesRule warns on if...else statements with both branches being the same. type IdenticalBranchesRule struct{} // Apply applies the rule to given file. @@ -17,9 +18,16 @@ func (*IdenticalBranchesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fa failures = append(failures, failure) } - astFile := file.AST - w := &lintIdenticalBranches{astFile, onFailure} - ast.Walk(w, astFile) + w := &lintIdenticalBranches{onFailure: onFailure} + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Body == nil { + continue + } + + ast.Walk(w, fn.Body) + } + return failures } @@ -29,59 +37,45 @@ func (*IdenticalBranchesRule) Name() string { } type lintIdenticalBranches struct { - file *ast.File onFailure func(lint.Failure) } func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor { - n, ok := node.(*ast.IfStmt) + ifStmt, ok := node.(*ast.IfStmt) if !ok { return w } - noElseBranch := n.Else == nil - if noElseBranch { - return w + if ifStmt.Else == nil { + return w // if without else } - branches := []*ast.BlockStmt{n.Body} - - elseBranch, ok := n.Else.(*ast.BlockStmt) - if !ok { // if-else-if construction + elseBranch, ok := ifStmt.Else.(*ast.BlockStmt) + if !ok { // if-else-if construction, the rule only copes with single if...else statements return w } - branches = append(branches, elseBranch) - if w.identicalBranches(branches) { - w.newFailure(n, "both branches of the if are identical") + if w.identicalBranches(ifStmt.Body, elseBranch) { + w.onFailure(lint.Failure{ + Confidence: 1.0, + Node: ifStmt, + Category: lint.FailureCategoryLogic, + Failure: "both branches of the if are identical", + }) } - return w + ast.Walk(w, ifStmt.Body) + ast.Walk(w, ifStmt.Else) + return nil } -func (*lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool { - if len(branches) < 2 { - return false // only one branch to compare thus we return +func (*lintIdenticalBranches) identicalBranches(body, elseBranch *ast.BlockStmt) bool { + if len(body.List) != len(elseBranch.List) { + return false // branches don't have the same number of statements } - referenceBranch := gofmt(branches[0]) - referenceBranchSize := len(branches[0].List) - for i := 1; i < len(branches); i++ { - currentBranch := branches[i] - currentBranchSize := len(currentBranch.List) - if currentBranchSize != referenceBranchSize || gofmt(currentBranch) != referenceBranch { - return false - } - } - - return true -} + bodyStr := astutils.GoFmt(body) + elseStr := astutils.GoFmt(elseBranch) -func (w *lintIdenticalBranches) newFailure(node ast.Node, msg string) { - w.onFailure(lint.Failure{ - Confidence: 1, - Node: node, - Category: lint.FailureCategoryLogic, - Failure: msg, - }) + return bodyStr == elseStr } diff --git a/vendor/github.com/mgechev/revive/rule/identical_ifelseif_branches.go b/vendor/github.com/mgechev/revive/rule/identical_ifelseif_branches.go new file mode 100644 index 000000000..b661e44f8 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/identical_ifelseif_branches.go @@ -0,0 +1,186 @@ +package rule + +import ( + "fmt" + "go/ast" + + "github.com/mgechev/revive/internal/astutils" + "github.com/mgechev/revive/lint" +) + +// IdenticalIfElseIfBranchesRule warns on if...else if chains with identical branches. +type IdenticalIfElseIfBranchesRule struct{} + +// Apply applies the rule to given file. +func (*IdenticalIfElseIfBranchesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + getStmtLine := func(s ast.Stmt) int { + return file.ToPosition(s.Pos()).Line + } + + w := &rootWalkerIfElseIfIdenticalBranches{getStmtLine: getStmtLine, onFailure: onFailure} + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Body == nil { + continue + } + + ast.Walk(w, fn.Body) + } + + return failures +} + +// Name returns the rule name. +func (*IdenticalIfElseIfBranchesRule) Name() string { + return "identical-ifelseif-branches" +} + +type rootWalkerIfElseIfIdenticalBranches struct { + getStmtLine func(ast.Stmt) int + onFailure func(lint.Failure) +} + +func (w *rootWalkerIfElseIfIdenticalBranches) Visit(node ast.Node) ast.Visitor { + n, ok := node.(*ast.IfStmt) + if !ok { + return w + } + + _, isIfElseIf := n.Else.(*ast.IfStmt) + if isIfElseIf { + walker := &lintIfChainIdenticalBranches{ + onFailure: w.onFailure, + getStmtLine: w.getStmtLine, + rootWalker: w, + } + + ast.Walk(walker, n) + return nil // the walker already analyzed inner branches + } + + return w +} + +// walkBranch analyzes the given branch. +func (w *rootWalkerIfElseIfIdenticalBranches) walkBranch(branch ast.Stmt) { + if branch == nil { + return + } + + walker := &rootWalkerIfElseIfIdenticalBranches{ + onFailure: w.onFailure, + getStmtLine: w.getStmtLine, + } + + ast.Walk(walker, branch) +} + +type lintIfChainIdenticalBranches struct { + getStmtLine func(ast.Stmt) int + onFailure func(lint.Failure) + branches []ast.Stmt // hold branches to compare + rootWalker *rootWalkerIfElseIfIdenticalBranches // the walker to use to recursively analyze inner branches + hasComplexCondition bool // indicates if one of the if conditions is "complex" +} + +// addBranch adds a branch to the list of branches to be compared. +func (w *lintIfChainIdenticalBranches) addBranch(branch ast.Stmt) { + if branch == nil { + return + } + + if w.branches == nil { + w.resetBranches() + } + + w.branches = append(w.branches, branch) +} + +// resetBranches resets (clears) the list of branches to compare. +func (w *lintIfChainIdenticalBranches) resetBranches() { + w.branches = []ast.Stmt{} + w.hasComplexCondition = false +} + +func (w *lintIfChainIdenticalBranches) Visit(node ast.Node) ast.Visitor { + n, ok := node.(*ast.IfStmt) + if !ok { + return w + } + + // recursively analyze the then-branch + w.rootWalker.walkBranch(n.Body) + + if n.Init == nil { // only check if without initialization to avoid false positives + w.addBranch(n.Body) + } + + if w.isComplexCondition(n.Cond) { + w.hasComplexCondition = true + } + + if n.Else != nil { + if chainedIf, ok := n.Else.(*ast.IfStmt); ok { + w.Visit(chainedIf) + } else { + w.addBranch(n.Else) + w.rootWalker.walkBranch(n.Else) + } + } + + identicalBranches := w.identicalBranches(w.branches) + for _, branchPair := range identicalBranches { + msg := fmt.Sprintf(`"if...else if" chain with identical branches (lines %d and %d)`, branchPair[0], branchPair[1]) + confidence := 1.0 + if w.hasComplexCondition { + confidence = 0.8 + } + w.onFailure(lint.Failure{ + Confidence: confidence, + Node: w.branches[0], + Category: lint.FailureCategoryLogic, + Failure: msg, + }) + } + + w.resetBranches() + return nil +} + +// isComplexCondition returns true if the given expression is "complex", false otherwise. +// An expression is considered complex if it has a function call. +func (*lintIfChainIdenticalBranches) isComplexCondition(expr ast.Expr) bool { + call := astutils.SeekNode[*ast.CallExpr](expr, func(n ast.Node) bool { + _, ok := n.(*ast.CallExpr) + return ok + }) + + return call != nil +} + +// identicalBranches yields pairs of (line numbers) of identical branches from the given branches. +func (w *lintIfChainIdenticalBranches) identicalBranches(branches []ast.Stmt) [][]int { + result := [][]int{} + if len(branches) < 2 { + return result // no other branch to compare thus we return + } + + hashes := map[string]int{} // branch code hash -> branch line + for _, branch := range branches { + hash := astutils.NodeHash(branch) + branchLine := w.getStmtLine(branch) + if match, ok := hashes[hash]; ok { + result = append(result, []int{match, branchLine}) + } + + hashes[hash] = branchLine + } + + return result +} diff --git a/vendor/github.com/mgechev/revive/rule/identical_ifelseif_condition.go b/vendor/github.com/mgechev/revive/rule/identical_ifelseif_condition.go new file mode 100644 index 000000000..0ba9d68c9 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/identical_ifelseif_condition.go @@ -0,0 +1,148 @@ +package rule + +import ( + "fmt" + "go/ast" + + "github.com/mgechev/revive/internal/astutils" + "github.com/mgechev/revive/lint" +) + +// IdenticalIfElseIfConditionsRule warns on if...else if chains with identical conditions. +type IdenticalIfElseIfConditionsRule struct{} + +// Apply applies the rule to given file. +func (*IdenticalIfElseIfConditionsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + getStmtLine := func(s ast.Stmt) int { + return file.ToPosition(s.Pos()).Line + } + + w := &rootWalkerIfElseIfIdenticalConditions{getStmtLine: getStmtLine, onFailure: onFailure} + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Body == nil { + continue + } + + ast.Walk(w, fn.Body) + } + + return failures +} + +// Name returns the rule name. +func (*IdenticalIfElseIfConditionsRule) Name() string { + return "identical-ifelseif-conditions" +} + +type rootWalkerIfElseIfIdenticalConditions struct { + getStmtLine func(ast.Stmt) int + onFailure func(lint.Failure) +} + +func (w *rootWalkerIfElseIfIdenticalConditions) Visit(node ast.Node) ast.Visitor { + n, ok := node.(*ast.IfStmt) + if !ok { + return w + } + + _, isIfElseIf := n.Else.(*ast.IfStmt) + if isIfElseIf { + walker := &lintIfChainIdenticalConditions{ + onFailure: w.onFailure, + getStmtLine: w.getStmtLine, + rootWalker: w, + } + + ast.Walk(walker, n) + return nil // the walker already analyzed inner branches + } + + return w +} + +// walkBranch analyzes the given branch. +func (w *rootWalkerIfElseIfIdenticalConditions) walkBranch(branch ast.Stmt) { + if branch == nil { + return + } + + walker := &rootWalkerIfElseIfIdenticalConditions{ + onFailure: w.onFailure, + getStmtLine: w.getStmtLine, + } + + ast.Walk(walker, branch) +} + +type lintIfChainIdenticalConditions struct { + getStmtLine func(ast.Stmt) int + onFailure func(lint.Failure) + conditions map[string]int // condition hash -> line of the condition + rootWalker *rootWalkerIfElseIfIdenticalConditions // the walker to use to recursively analyze inner branches +} + +// addCondition adds a condition to the set of if...else if conditions. +// If the set already contains the same condition it returns the line number of the identical condition. +func (w *lintIfChainIdenticalConditions) addCondition(condition ast.Expr, conditionLine int) (line int, match bool) { + if condition == nil { + return 0, false + } + + if w.conditions == nil { + w.resetConditions() + } + + hash := astutils.NodeHash(condition) + identical, ok := w.conditions[hash] + if ok { + return identical, true + } + + w.conditions[hash] = conditionLine + return 0, false +} + +func (w *lintIfChainIdenticalConditions) resetConditions() { + w.conditions = map[string]int{} +} + +func (w *lintIfChainIdenticalConditions) Visit(node ast.Node) ast.Visitor { + n, ok := node.(*ast.IfStmt) + if !ok { + return w + } + + // recursively analyze the then-branch + w.rootWalker.walkBranch(n.Body) + + if n.Init == nil { // only check if without initialization to avoid false positives + currentCondLine := w.rootWalker.getStmtLine(n) + identicalCondLine, match := w.addCondition(n.Cond, currentCondLine) + if match { + w.onFailure(lint.Failure{ + Confidence: 1.0, + Node: n, + Category: lint.FailureCategoryLogic, + Failure: fmt.Sprintf(`"if...else if" chain with identical conditions (lines %d and %d)`, identicalCondLine, currentCondLine), + }) + } + } + + if n.Else != nil { + if chainedIf, ok := n.Else.(*ast.IfStmt); ok { + w.Visit(chainedIf) + } else { + w.rootWalker.walkBranch(n.Else) + } + } + + w.resetConditions() + return nil +} diff --git a/vendor/github.com/mgechev/revive/rule/identical_switch_branches.go b/vendor/github.com/mgechev/revive/rule/identical_switch_branches.go new file mode 100644 index 000000000..fc1d620b3 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/identical_switch_branches.go @@ -0,0 +1,94 @@ +package rule + +import ( + "fmt" + "go/ast" + "go/token" + + "github.com/mgechev/revive/internal/astutils" + "github.com/mgechev/revive/lint" +) + +// IdenticalSwitchBranchesRule warns on identical switch branches. +type IdenticalSwitchBranchesRule struct{} + +// Apply applies the rule to given file. +func (*IdenticalSwitchBranchesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + getStmtLine := func(s ast.Stmt) int { + return file.ToPosition(s.Pos()).Line + } + + w := &lintIdenticalSwitchBranches{getStmtLine: getStmtLine, onFailure: onFailure} + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Body == nil { + continue + } + + ast.Walk(w, fn.Body) + } + + return failures +} + +// Name returns the rule name. +func (*IdenticalSwitchBranchesRule) Name() string { + return "identical-switch-branches" +} + +type lintIdenticalSwitchBranches struct { + getStmtLine func(ast.Stmt) int + onFailure func(lint.Failure) +} + +func (w *lintIdenticalSwitchBranches) Visit(node ast.Node) ast.Visitor { + switchStmt, ok := node.(*ast.SwitchStmt) + if !ok { + return w + } + + if switchStmt.Tag == nil { + return w // do not lint untagged switches (order of case evaluation might be important) + } + + doesFallthrough := func(stmts []ast.Stmt) bool { + if len(stmts) == 0 { + return false + } + + ft, ok := stmts[len(stmts)-1].(*ast.BranchStmt) + return ok && ft.Tok == token.FALLTHROUGH + } + + hashes := map[string]int{} // map hash(branch code) -> branch line + for _, cc := range switchStmt.Body.List { + caseClause := cc.(*ast.CaseClause) + if doesFallthrough(caseClause.Body) { + continue // skip fallthrough branches + } + branch := &ast.BlockStmt{ + List: caseClause.Body, + } + hash := astutils.NodeHash(branch) + branchLine := w.getStmtLine(caseClause) + if matchLine, ok := hashes[hash]; ok { + w.onFailure(lint.Failure{ + Confidence: 1.0, + Node: node, + Category: lint.FailureCategoryLogic, + Failure: fmt.Sprintf(`"switch" with identical branches (lines %d and %d)`, matchLine, branchLine), + }) + } + + hashes[hash] = branchLine + ast.Walk(w, branch) + } + + return nil // switch branches already analyzed +} diff --git a/vendor/github.com/mgechev/revive/rule/identical_switch_conditions.go b/vendor/github.com/mgechev/revive/rule/identical_switch_conditions.go new file mode 100644 index 000000000..15826d9b0 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/identical_switch_conditions.go @@ -0,0 +1,78 @@ +package rule + +import ( + "fmt" + "go/ast" + "go/token" + + "github.com/mgechev/revive/internal/astutils" + "github.com/mgechev/revive/lint" +) + +// IdenticalSwitchConditionsRule warns on switch case clauses with identical conditions. +type IdenticalSwitchConditionsRule struct{} + +// Apply applies the rule to given file. +func (*IdenticalSwitchConditionsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + w := &lintIdenticalSwitchConditions{toPosition: file.ToPosition, onFailure: onFailure} + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Body == nil { + continue + } + + ast.Walk(w, fn.Body) + } + + return failures +} + +// Name returns the rule name. +func (*IdenticalSwitchConditionsRule) Name() string { + return "identical-switch-conditions" +} + +type lintIdenticalSwitchConditions struct { + toPosition func(token.Pos) token.Position + onFailure func(lint.Failure) +} + +func (w *lintIdenticalSwitchConditions) Visit(node ast.Node) ast.Visitor { + switchStmt, ok := node.(*ast.SwitchStmt) + if !ok { // not a switch statement, keep walking the AST + return w + } + + if switchStmt.Tag != nil { + return w // Not interested in tagged switches + } + + hashes := map[string]int{} // map hash(condition code) -> condition line + for _, cc := range switchStmt.Body.List { + caseClause := cc.(*ast.CaseClause) + caseClauseLine := w.toPosition(caseClause.Pos()).Line + for _, expr := range caseClause.List { + hash := astutils.NodeHash(expr) + if matchLine, ok := hashes[hash]; ok { + w.onFailure(lint.Failure{ + Confidence: 1.0, + Node: caseClause, + Category: lint.FailureCategoryLogic, + Failure: fmt.Sprintf(`case clause at line %d has the same condition`, matchLine), + }) + } + + hashes[hash] = caseClauseLine + } + + ast.Walk(w, caseClause) + } + + return nil // switch branches already analyzed +} diff --git a/vendor/github.com/mgechev/revive/rule/if_return.go b/vendor/github.com/mgechev/revive/rule/if_return.go index d0f581f81..15c7ca18a 100644 --- a/vendor/github.com/mgechev/revive/rule/if_return.go +++ b/vendor/github.com/mgechev/revive/rule/if_return.go @@ -36,8 +36,7 @@ type lintElseError struct { } func (w *lintElseError) Visit(node ast.Node) ast.Visitor { - switch v := node.(type) { - case *ast.BlockStmt: + if v, ok := node.(*ast.BlockStmt); ok { for i := range len(v.List) - 1 { // if var := whatever; var != nil { return var } s, ok := v.List[i].(*ast.IfStmt) @@ -45,6 +44,7 @@ func (w *lintElseError) Visit(node ast.Node) ast.Visitor { continue } assign, ok := s.Init.(*ast.AssignStmt) + //nolint:staticcheck // QF1001: it's readable enough if !ok || len(assign.Lhs) != 1 || !(assign.Tok == token.DEFINE || assign.Tok == token.ASSIGN) { continue } diff --git a/vendor/github.com/mgechev/revive/rule/import_alias_naming.go b/vendor/github.com/mgechev/revive/rule/import_alias_naming.go index 94cea78c8..a46c331ef 100644 --- a/vendor/github.com/mgechev/revive/rule/import_alias_naming.go +++ b/vendor/github.com/mgechev/revive/rule/import_alias_naming.go @@ -15,6 +15,7 @@ type ImportAliasNamingRule struct { const defaultImportAliasNamingAllowRule = "^[a-z][a-z0-9]{0,}$" +//nolint:gocritic // regexpSimplify: backward compatibility var defaultImportAliasNamingAllowRegexp = regexp.MustCompile(defaultImportAliasNamingAllowRule) // Configure validates the rule configuration, and configures the rule accordingly. diff --git a/vendor/github.com/mgechev/revive/rule/import_shadowing.go b/vendor/github.com/mgechev/revive/rule/import_shadowing.go index 69d17f2b1..0028d9673 100644 --- a/vendor/github.com/mgechev/revive/rule/import_shadowing.go +++ b/vendor/github.com/mgechev/revive/rule/import_shadowing.go @@ -13,12 +13,12 @@ import ( type ImportShadowingRule struct{} // Apply applies the rule to given file. -func (*ImportShadowingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { +func (r *ImportShadowingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { var failures []lint.Failure importNames := map[string]struct{}{} for _, imp := range file.AST.Imports { - importNames[getName(imp)] = struct{}{} + importNames[r.getName(imp)] = struct{}{} } fileAst := file.AST @@ -28,7 +28,7 @@ func (*ImportShadowingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fail onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, - alreadySeen: map[*ast.Object]struct{}{}, // TODO: ast.Object is deprecated + alreadySeen: map[*ast.Object]struct{}{}, //nolint:staticcheck // TODO: ast.Object is deprecated skipIdents: map[*ast.Ident]struct{}{}, } @@ -42,31 +42,34 @@ func (*ImportShadowingRule) Name() string { return "import-shadowing" } -func getName(imp *ast.ImportSpec) string { +func (r *ImportShadowingRule) getName(imp *ast.ImportSpec) string { const pathSep = "/" const strDelim = `"` if imp.Name != nil { return imp.Name.Name } - path := imp.Path.Value - i := strings.LastIndex(path, pathSep) - if i == -1 { - return strings.Trim(path, strDelim) + path := strings.Trim(imp.Path.Value, strDelim) + parts := strings.Split(path, pathSep) + + lastSegment := parts[len(parts)-1] + if r.isVersion(lastSegment) && len(parts) >= 2 { + // Use the previous segment when current is a version (v1, v2, etc.). + return parts[len(parts)-2] } - return strings.Trim(path[i+1:], strDelim) + return lastSegment } type importShadowing struct { packageNameIdent *ast.Ident importNames map[string]struct{} onFailure func(lint.Failure) - alreadySeen map[*ast.Object]struct{} // TODO: ast.Object is deprecated + alreadySeen map[*ast.Object]struct{} //nolint:staticcheck // TODO: ast.Object is deprecated skipIdents map[*ast.Ident]struct{} } -// Visit visits AST nodes and checks if id nodes (ast.Ident) shadow an import name +// Visit visits AST nodes and checks if id nodes (ast.Ident) shadow an import name. func (w importShadowing) Visit(n ast.Node) ast.Visitor { switch n := n.(type) { case *ast.AssignStmt: @@ -113,3 +116,17 @@ func (w importShadowing) Visit(n ast.Node) ast.Visitor { return w } + +func (*ImportShadowingRule) isVersion(name string) bool { + if len(name) < 2 || (name[0] != 'v' && name[0] != 'V') { + return false + } + + for i := 1; i < len(name); i++ { + if name[i] < '0' || name[i] > '9' { + return false + } + } + + return true +} diff --git a/vendor/github.com/mgechev/revive/rule/imports_blocklist.go b/vendor/github.com/mgechev/revive/rule/imports_blocklist.go index c96382daf..8d3b08693 100644 --- a/vendor/github.com/mgechev/revive/rule/imports_blocklist.go +++ b/vendor/github.com/mgechev/revive/rule/imports_blocklist.go @@ -24,7 +24,7 @@ func (r *ImportsBlocklistRule) Configure(arguments lint.Arguments) error { if !ok { return fmt.Errorf("invalid argument to the imports-blocklist rule. Expecting a string, got %T", arg) } - regStr, err := regexp.Compile(fmt.Sprintf(`(?m)"%s"$`, replaceImportRegexp.ReplaceAllString(argStr, `(\W|\w)*`))) + regStr, err := regexp.Compile(fmt.Sprintf(`(?m)"%s"$`, replaceImportRegexp.ReplaceAllString(argStr, `(\W|\w)*`))) //nolint:gocritic // regexpSimplify: false positive if err != nil { return fmt.Errorf("invalid argument to the imports-blocklist rule. Expecting %q to be a valid regular expression, got: %w", argStr, err) } diff --git a/vendor/github.com/mgechev/revive/rule/inefficient_map_lookup.go b/vendor/github.com/mgechev/revive/rule/inefficient_map_lookup.go new file mode 100644 index 000000000..b6e4bf921 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/inefficient_map_lookup.go @@ -0,0 +1,169 @@ +package rule + +import ( + "fmt" + "go/ast" + "go/token" + "strings" + + "github.com/mgechev/revive/internal/astutils" + "github.com/mgechev/revive/lint" +) + +// InefficientMapLookupRule spots potential inefficient map lookups. +type InefficientMapLookupRule struct{} + +// Apply applies the rule to given file. +func (*InefficientMapLookupRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + w := &lintInefficientMapLookup{ + file: file, + onFailure: onFailure, + } + + if err := file.Pkg.TypeCheck(); err != nil { + return []lint.Failure{ + lint.NewInternalFailure(fmt.Sprintf("Unable to type check file %q: %v", file.Name, err)), + } + } + + // Iterate over declarations looking for function declarations + for _, decl := range file.AST.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok { + continue // not a function + } + + if fn.Body == nil { + continue // external (no-Go) function + } + + // Analyze the function body + ast.Walk(w, fn.Body) + } + + return failures +} + +// Name returns the rule name. +func (*InefficientMapLookupRule) Name() string { + return "inefficient-map-lookup" +} + +type lintInefficientMapLookup struct { + file *lint.File + onFailure func(lint.Failure) +} + +func (w *lintInefficientMapLookup) Visit(node ast.Node) ast.Visitor { + // Only interested in blocks of statements + block, ok := node.(*ast.BlockStmt) + if !ok { + return w // not a block of statements + } + + w.analyzeBlock(block) + + return w +} + +// analyzeBlock searches AST subtrees with the following form +// +// for := range { +// if == { +// ... +// } +func (w *lintInefficientMapLookup) analyzeBlock(b *ast.BlockStmt) { + for _, stmt := range b.List { + if !w.isRangeOverMapKey(stmt) { + continue + } + + rangeOverMap := stmt.(*ast.RangeStmt) + key := rangeOverMap.Key.(*ast.Ident) + + // Here we have identified a range over the keys of a map + // Let's check if the range body is + // { if == { ... } } + // or + // { if != { continue } ... } + if !isKeyLookup(key.Name, rangeOverMap.Body) { + continue + } + + w.onFailure(lint.Failure{ + Confidence: 1, + Node: rangeOverMap, + Category: lint.FailureCategoryStyle, + Failure: "inefficient lookup of map key", + }) + } +} + +func isKeyLookup(keyName string, blockStmt *ast.BlockStmt) bool { + blockLen := len(blockStmt.List) + if blockLen == 0 { + return false // empty + } + + firstStmt := blockStmt.List[0] + ifStmt, ok := firstStmt.(*ast.IfStmt) + if !ok { + return false // the first statement of the body is not an if + } + + binExp, ok := ifStmt.Cond.(*ast.BinaryExpr) + if !ok { + return false // the if condition is not a binary expression + } + + if !astutils.IsIdent(binExp.X, keyName) { + return false // the if condition is not + } + + switch binExp.Op { + case token.EQL: + // if key == ... should be the single statement in the block + return blockLen == 1 + + case token.NEQ: + // if key != ... + ifBodyStmts := ifStmt.Body.List + if len(ifBodyStmts) < 1 { + return false // if key != ... { /* empty */ } + } + + branchStmt, ok := ifBodyStmts[0].(*ast.BranchStmt) + if !ok || branchStmt.Tok != token.CONTINUE { + return false // if key != ... { } + } + + return true + } + + return false +} + +func (w *lintInefficientMapLookup) isRangeOverMapKey(stmt ast.Stmt) bool { + rangeStmt, ok := stmt.(*ast.RangeStmt) + if !ok { + return false // not a range + } + + // Check if we range only on key + // for key := range ... + // for key, _ := range ... + hasValueVariable := rangeStmt.Value != nil && !astutils.IsIdent(rangeStmt.Value, "_") + if hasValueVariable { + return false // range over both key and value + } + + // Check if we range over a map + t := w.file.Pkg.TypeOf(rangeStmt.X) + return t != nil && strings.HasPrefix(t.String(), "map[") +} diff --git a/vendor/github.com/mgechev/revive/rule/line_length_limit.go b/vendor/github.com/mgechev/revive/rule/line_length_limit.go index 0c4c57691..5d0653975 100644 --- a/vendor/github.com/mgechev/revive/rule/line_length_limit.go +++ b/vendor/github.com/mgechev/revive/rule/line_length_limit.go @@ -76,7 +76,7 @@ func (r lintLineLengthNum) check() { c := utf8.RuneCountInString(t) if c > r.max { r.onFailure(lint.Failure{ - Category: lint.FailureCategoryCodeStyle, + Category: lint.FailureCategoryStyle, Position: lint.FailurePosition{ // Offset not set; it is non-trivial, and doesn't appear to be needed. Start: token.Position{ diff --git a/vendor/github.com/mgechev/revive/rule/max_public_structs.go b/vendor/github.com/mgechev/revive/rule/max_public_structs.go index f27edd7e6..c78116d3a 100644 --- a/vendor/github.com/mgechev/revive/rule/max_public_structs.go +++ b/vendor/github.com/mgechev/revive/rule/max_public_structs.go @@ -81,8 +81,7 @@ type lintMaxPublicStructs struct { } func (w *lintMaxPublicStructs) Visit(n ast.Node) ast.Visitor { - switch v := n.(type) { - case *ast.TypeSpec: + if v, ok := n.(*ast.TypeSpec); ok { name := v.Name.Name first := string(name[0]) if strings.ToUpper(first) == first { diff --git a/vendor/github.com/mgechev/revive/rule/modifies_param.go b/vendor/github.com/mgechev/revive/rule/modifies_param.go index da509087d..687ee8446 100644 --- a/vendor/github.com/mgechev/revive/rule/modifies_param.go +++ b/vendor/github.com/mgechev/revive/rule/modifies_param.go @@ -4,12 +4,22 @@ import ( "fmt" "go/ast" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) // ModifiesParamRule warns on assignments to function parameters. type ModifiesParamRule struct{} +// modifyingParamPositions are parameter positions that are modified by a function. +type modifyingParamPositions = []int + +// modifyingFunctions maps function names to the positions of parameters they modify. +var modifyingFunctions = map[string]modifyingParamPositions{ + "slices.Delete": {0}, + "slices.DeleteFunc": {0}, +} + // Apply applies the rule to given file. func (*ModifiesParamRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { var failures []lint.Failure @@ -57,12 +67,19 @@ func (w lintModifiesParamRule) Visit(node ast.Node) ast.Visitor { } case *ast.AssignStmt: lhs := v.Lhs - for _, e := range lhs { + for i, e := range lhs { id, ok := e.(*ast.Ident) - if ok { - checkParam(id, &w) + if !ok { + continue + } + + if i < len(v.Rhs) { + w.checkModifyingFunction(v.Rhs[i]) } + checkParam(id, &w) } + case *ast.ExprStmt: + w.checkModifyingFunction(v.X) } return w @@ -78,3 +95,39 @@ func checkParam(id *ast.Ident, w *lintModifiesParamRule) { }) } } + +func (w *lintModifiesParamRule) checkModifyingFunction(callNode ast.Node) { + callExpr, ok := callNode.(*ast.CallExpr) + if !ok { + return + } + + funcName := astutils.GoFmt(callExpr.Fun) + positions, found := modifyingFunctions[funcName] + if !found { + return + } + + for _, pos := range positions { + if pos >= len(callExpr.Args) { + return + } + + id, ok := callExpr.Args[pos].(*ast.Ident) + if !ok { + continue + } + + _, match := w.params[id.Name] + if !match { + continue + } + + w.onFailure(lint.Failure{ + Confidence: 0.5, // confidence is low because of shadow variables + Node: callExpr, + Category: lint.FailureCategoryBadPractice, + Failure: fmt.Sprintf("parameter '%s' seems to be modified by '%s'", id.Name, funcName), + }) + } +} diff --git a/vendor/github.com/mgechev/revive/rule/modifies_value_receiver.go b/vendor/github.com/mgechev/revive/rule/modifies_value_receiver.go index 9af91099f..d8daace08 100644 --- a/vendor/github.com/mgechev/revive/rule/modifies_value_receiver.go +++ b/vendor/github.com/mgechev/revive/rule/modifies_value_receiver.go @@ -5,6 +5,7 @@ import ( "go/token" "strings" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -34,7 +35,7 @@ func (r *ModifiesValRecRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fai continue // receiver is not modified } - methodReturnsReceiver := len(r.findReturnReceiverStatements(receiverName, funcDecl.Body)) > 0 + methodReturnsReceiver := r.seekReturnReceiverStatement(receiverName, funcDecl.Body) != nil if methodReturnsReceiver { continue // modification seems legit (see issue #1066) } @@ -78,7 +79,7 @@ func (*ModifiesValRecRule) getNameFromExpr(ie ast.Expr) string { return ident.Name } -func (r *ModifiesValRecRule) findReturnReceiverStatements(receiverName string, target ast.Node) []ast.Node { +func (r *ModifiesValRecRule) seekReturnReceiverStatement(receiverName string, target ast.Node) ast.Node { finder := func(n ast.Node) bool { // look for returns with the receiver as value returnStatement, ok := n.(*ast.ReturnStmt) @@ -116,7 +117,7 @@ func (r *ModifiesValRecRule) findReturnReceiverStatements(receiverName string, t return false } - return pick(target, finder) + return astutils.SeekNode[ast.Node](target, finder) } func (r *ModifiesValRecRule) mustSkip(receiver *ast.Field, pkg *lint.Package) bool { @@ -179,5 +180,5 @@ func (r *ModifiesValRecRule) getReceiverModifications(receiverName string, funcB return false } - return pick(funcBody, receiverModificationFinder) + return astutils.PickNodes(funcBody, receiverModificationFinder) } diff --git a/vendor/github.com/mgechev/revive/rule/optimize_operands_order.go b/vendor/github.com/mgechev/revive/rule/optimize_operands_order.go index 6b3143cb6..e384f4876 100644 --- a/vendor/github.com/mgechev/revive/rule/optimize_operands_order.go +++ b/vendor/github.com/mgechev/revive/rule/optimize_operands_order.go @@ -5,6 +5,7 @@ import ( "go/ast" "go/token" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -63,20 +64,20 @@ func (w lintOptimizeOperandsOrderExpr) Visit(node ast.Node) ast.Visitor { } // check if the left sub-expression contains a function call - nodes := pick(binExpr.X, isCaller) - if len(nodes) < 1 { + call := astutils.SeekNode[*ast.CallExpr](binExpr.X, isCaller) + if call == nil { return w } // check if the right sub-expression does not contain a function call - nodes = pick(binExpr.Y, isCaller) - if len(nodes) > 0 { + call = astutils.SeekNode[*ast.CallExpr](binExpr.Y, isCaller) + if call != nil { return w } newExpr := ast.BinaryExpr{X: binExpr.Y, Y: binExpr.X, Op: binExpr.Op} w.onFailure(lint.Failure{ - Failure: fmt.Sprintf("for better performance '%v' might be rewritten as '%v'", gofmt(binExpr), gofmt(&newExpr)), + Failure: fmt.Sprintf("for better performance '%v' might be rewritten as '%v'", astutils.GoFmt(binExpr), astutils.GoFmt(&newExpr)), Node: node, Category: lint.FailureCategoryOptimization, Confidence: 0.3, diff --git a/vendor/github.com/mgechev/revive/rule/package_comments.go b/vendor/github.com/mgechev/revive/rule/package_comments.go index 20afee88e..74af62679 100644 --- a/vendor/github.com/mgechev/revive/rule/package_comments.go +++ b/vendor/github.com/mgechev/revive/rule/package_comments.go @@ -143,7 +143,7 @@ func (l *lintPackageComments) Visit(_ ast.Node) ast.Visitor { } } - if l.fileAst.Doc == nil { + if isEmptyDoc(l.fileAst.Doc) { for _, failure := range l.checkPackageComment() { l.onFailure(failure) } @@ -162,3 +162,7 @@ func (l *lintPackageComments) Visit(_ ast.Node) ast.Visitor { } return nil } + +func isEmptyDoc(commentGroup *ast.CommentGroup) bool { + return commentGroup == nil || commentGroup.Text() == "" +} diff --git a/vendor/github.com/mgechev/revive/rule/package_directory_mismatch.go b/vendor/github.com/mgechev/revive/rule/package_directory_mismatch.go new file mode 100644 index 000000000..717805473 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/package_directory_mismatch.go @@ -0,0 +1,194 @@ +package rule + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/mgechev/revive/lint" +) + +// PackageDirectoryMismatchRule detects when package name doesn't match directory name. +type PackageDirectoryMismatchRule struct { + ignoredDirs *regexp.Regexp +} + +const defaultIgnoredDirs = "testdata" + +// Configure the rule to exclude certain directories. +func (r *PackageDirectoryMismatchRule) Configure(arguments lint.Arguments) error { + if len(arguments) < 1 { + var err error + r.ignoredDirs, err = r.buildIgnoreRegex([]string{defaultIgnoredDirs}) + return err + } + + args, ok := arguments[0].(map[string]any) + if !ok { + return fmt.Errorf("invalid argument type: expected map[string]any, got %T", arguments[0]) + } + + for k, v := range args { + if !isRuleOption(k, "ignoreDirectories") { + return fmt.Errorf("unknown argument %s for %s rule", k, r.Name()) + } + + ignoredAny, ok := v.([]any) + if !ok { + return fmt.Errorf("invalid value %v for argument %s of rule %s, expected []string got %T", v, k, r.Name(), v) + } + + ignoredDirs := make([]string, len(ignoredAny)) + for i, item := range ignoredAny { + str, ok := item.(string) + if !ok { + return fmt.Errorf("invalid value in %s argument of rule %s: expected string, got %T", k, r.Name(), item) + } + ignoredDirs[i] = str + } + + var err error + r.ignoredDirs, err = r.buildIgnoreRegex(ignoredDirs) + return err + } + + return nil +} + +func (*PackageDirectoryMismatchRule) buildIgnoreRegex(ignoredDirs []string) (*regexp.Regexp, error) { + if len(ignoredDirs) == 0 { + return nil, nil + } + + patterns := make([]string, len(ignoredDirs)) + for i, dir := range ignoredDirs { + patterns[i] = regexp.QuoteMeta(dir) + } + pattern := strings.Join(patterns, "|") + + regex, err := regexp.Compile(pattern) + if err != nil { + return nil, fmt.Errorf("failed to compile regex for ignored directories: %w", err) + } + + return regex, nil +} + +// skipDirs contains directory names that should be unconditionally ignored when checking. +// These entries handle edge cases where filepath.Base might return these values. +var skipDirs = map[string]struct{}{ + ".": {}, // Current directory + "/": {}, // Root directory + "": {}, // Empty path +} + +// semanticallyEqual checks if package and directory names are semantically equal to each other. +func (PackageDirectoryMismatchRule) semanticallyEqual(packageName, dirName string) bool { + normDir := normalizePath(dirName) + normPkg := normalizePath(packageName) + return normDir == normPkg || normDir == "go"+normPkg +} + +// Apply applies the rule to the given file. +func (r *PackageDirectoryMismatchRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + if file.Pkg.IsMain() { + return nil + } + + absPath, err := filepath.Abs(file.Name) + if err != nil { + return nil + } + + dirPath := filepath.Dir(absPath) + dirName := filepath.Base(dirPath) + + if r.ignoredDirs != nil && r.ignoredDirs.MatchString(dirPath) { + return nil + } + + // Check if we got an invalid directory. + if _, skipDir := skipDirs[dirName]; skipDir { + return nil + } + + // Files directly in 'internal/' (like 'internal/abcd.go') should not be checked. + // But files in subdirectories of 'internal/' (like 'internal/foo/abcd.go') should be checked. + if dirName == "internal" { + return nil + } + + packageName := file.AST.Name.Name + + if r.semanticallyEqual(packageName, dirName) { + return nil + } + + if isRootDir(dirPath) { + return nil + } + + if file.IsTest() { + // treat main_test differently because it's a common package name for tests + if packageName == "main_test" { + return nil + } + // External test package (directory + '_test' suffix) + if r.semanticallyEqual(packageName, dirName+"_test") { + return nil + } + } + + // define a default failure message + failure := fmt.Sprintf("package name %q does not match directory name %q", packageName, dirName) + + // For version directories (v1, v2, etc.), we need to check also the parent directory + if isVersionPath(dirName) { + parentDirName := filepath.Base(filepath.Dir(dirPath)) + if r.semanticallyEqual(packageName, parentDirName) { + return nil + } + + if file.IsTest() { + // External test package (directory + '_test' suffix) + if r.semanticallyEqual(packageName, parentDirName+"_test") { + return nil + } + } + + failure = fmt.Sprintf("package name %q does not match directory name %q or parent directory name %q", packageName, dirName, parentDirName) + } + + return []lint.Failure{ + { + Failure: failure, + Confidence: 1, + Node: file.AST.Name, + Category: lint.FailureCategoryNaming, + }, + } +} + +// isRootDir checks if the given directory contains go.mod or .git, indicating it's a root directory. +func isRootDir(dirPath string) bool { + entries, err := os.ReadDir(dirPath) + if err != nil { + return false + } + + for _, e := range entries { + switch e.Name() { + case "go.mod", ".git": + return true + } + } + + return false +} + +// Name returns the rule name. +func (*PackageDirectoryMismatchRule) Name() string { + return "package-directory-mismatch" +} diff --git a/vendor/github.com/mgechev/revive/rule/range.go b/vendor/github.com/mgechev/revive/rule/range.go index b54078e4d..2772f11b8 100644 --- a/vendor/github.com/mgechev/revive/rule/range.go +++ b/vendor/github.com/mgechev/revive/rule/range.go @@ -5,6 +5,7 @@ import ( "go/ast" "strings" + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) @@ -43,7 +44,7 @@ func (w *lintRanges) Visit(node ast.Node) ast.Visitor { // for x = range m { ... } return w // single var form } - if !isIdent(rs.Value, "_") { + if !astutils.IsIdent(rs.Value, "_") { // for ?, y = range m { ... } return w } diff --git a/vendor/github.com/mgechev/revive/rule/range_val_address.go b/vendor/github.com/mgechev/revive/rule/range_val_address.go index 669807177..6622cd5a5 100644 --- a/vendor/github.com/mgechev/revive/rule/range_val_address.go +++ b/vendor/github.com/mgechev/revive/rule/range_val_address.go @@ -9,7 +9,7 @@ import ( "github.com/mgechev/revive/lint" ) -// RangeValAddress lints +// RangeValAddress warns if address of range value is used dangerously. type RangeValAddress struct{} // Apply applies the rule to given file. @@ -70,7 +70,7 @@ func (w rangeValAddress) Visit(node ast.Node) ast.Visitor { type rangeBodyVisitor struct { valueIsStarExpr bool - valueID *ast.Object // TODO: ast.Object is deprecated + valueID *ast.Object //nolint:staticcheck // TODO: ast.Object is deprecated onFailure func(lint.Failure) } diff --git a/vendor/github.com/mgechev/revive/rule/redundant_import_alias.go b/vendor/github.com/mgechev/revive/rule/redundant_import_alias.go index 692507a27..9c2edb013 100644 --- a/vendor/github.com/mgechev/revive/rule/redundant_import_alias.go +++ b/vendor/github.com/mgechev/revive/rule/redundant_import_alias.go @@ -23,7 +23,7 @@ func (*RedundantImportAlias) Apply(file *lint.File, _ lint.Arguments) []lint.Fai if getImportPackageName(imp) == imp.Name.Name { failures = append(failures, lint.Failure{ Confidence: 1, - Failure: fmt.Sprintf("Import alias \"%s\" is redundant", imp.Name.Name), + Failure: fmt.Sprintf("Import alias %q is redundant", imp.Name.Name), Node: imp, Category: lint.FailureCategoryImports, }) diff --git a/vendor/github.com/mgechev/revive/rule/redundant_test_main_exit.go b/vendor/github.com/mgechev/revive/rule/redundant_test_main_exit.go index 01a90a47c..717969ef6 100644 --- a/vendor/github.com/mgechev/revive/rule/redundant_test_main_exit.go +++ b/vendor/github.com/mgechev/revive/rule/redundant_test_main_exit.go @@ -66,7 +66,7 @@ func (w *lintRedundantTestMainExit) Visit(node ast.Node) ast.Visitor { pkg := id.Name fn := fc.Sel.Name - if isCallToExitFunction(pkg, fn) { + if isCallToExitFunction(pkg, fn, ce.Args) { w.onFailure(lint.Failure{ Confidence: 1, Node: ce, diff --git a/vendor/github.com/mgechev/revive/rule/string_format.go b/vendor/github.com/mgechev/revive/rule/string_format.go index d539577e7..b653cb13e 100644 --- a/vendor/github.com/mgechev/revive/rule/string_format.go +++ b/vendor/github.com/mgechev/revive/rule/string_format.go @@ -11,7 +11,7 @@ import ( "github.com/mgechev/revive/lint" ) -// StringFormatRule lints strings and/or comments according to a set of regular expressions given as Arguments +// StringFormatRule lints strings and/or comments according to a set of regular expressions given as Arguments. type StringFormatRule struct { rules []stringFormatSubrule } @@ -81,7 +81,7 @@ type stringFormatSubruleScope struct { field string // (optional) If the argument to be checked is a struct, which member of the struct is checked against the rule (top level members only) } -// Regex inserted to match valid function/struct field identifiers +// Regex inserted to match valid function/struct field identifiers. const identRegex = "[_A-Za-z][_A-Za-z0-9]*" var parseStringFormatScope = regexp.MustCompile( @@ -118,7 +118,7 @@ func (r *StringFormatRule) parseArgument(argument any, ruleNum int) (scopes stri for scopeNum, rawScope := range rawScopes { rawScope = strings.TrimSpace(rawScope) - if len(rawScope) == 0 { + if rawScope == "" { return stringFormatSubruleScopes{}, regex, false, "", r.parseScopeError("empty scope in rule scopes:", ruleNum, 0, scopeNum) } @@ -133,14 +133,14 @@ func (r *StringFormatRule) parseArgument(argument any, ruleNum int) (scopes stri r.parseScopeError(fmt.Sprintf("unexpected number of submatches when parsing scope: %d, expected 4", len(matches)), ruleNum, 0, scopeNum) } scope.funcName = matches[1] - if len(matches[2]) > 0 { + if matches[2] != "" { var err error scope.argument, err = strconv.Atoi(matches[2]) if err != nil { return stringFormatSubruleScopes{}, regex, false, "", r.parseScopeError("unable to parse argument number in rule scope", ruleNum, 0, scopeNum) } } - if len(matches[3]) > 0 { + if matches[3] != "" { scope.field = matches[3] } @@ -165,17 +165,17 @@ func (r *StringFormatRule) parseArgument(argument any, ruleNum int) (scopes stri return scopes, regex, negated, errorMessage, nil } -// Report an invalid config, this is specifically the user's fault +// Report an invalid config, this is specifically the user's fault. func (*StringFormatRule) configError(msg string, ruleNum, option int) error { return fmt.Errorf("invalid configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option) } -// Report a general config parsing failure, this may be the user's fault, but it isn't known for certain +// Report a general config parsing failure, this may be the user's fault, but it isn't known for certain. func (*StringFormatRule) parseError(msg string, ruleNum, option int) error { return fmt.Errorf("failed to parse configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option) } -// Report a general scope config parsing failure, this may be the user's fault, but it isn't known for certain +// Report a general scope config parsing failure, this may be the user's fault, but it isn't known for certain. func (*StringFormatRule) parseScopeError(msg string, ruleNum, option, scopeNum int) error { return fmt.Errorf("failed to parse configuration for string-format: %s [argument %d, option %d, scope index %d]", msg, ruleNum, option, scopeNum) } @@ -204,7 +204,7 @@ func (w *lintStringFormatRule) Visit(node ast.Node) ast.Visitor { return w } -// Return the name of a call expression in the form of package.Func or Func +// Return the name of a call expression in the form of package.Func or Func. func (*lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, ok bool) { if ident, ok := call.Fun.(*ast.Ident); ok { // Local function call @@ -227,7 +227,7 @@ func (*lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, o return "", false } -// apply a single format rule to a call expression (should be done after verifying the that the call expression matches the rule's scope) +// apply a single format rule to a call expression (should be done after verifying the that the call expression matches the rule's scope). func (r *stringFormatSubrule) apply(call *ast.CallExpr, scope *stringFormatSubruleScope) { if len(call.Args) <= scope.argument { return @@ -235,7 +235,7 @@ func (r *stringFormatSubrule) apply(call *ast.CallExpr, scope *stringFormatSubru arg := call.Args[scope.argument] var lit *ast.BasicLit - if len(scope.field) > 0 { + if scope.field != "" { // Try finding the scope's Field, treating arg as a composite literal composite, ok := arg.(*ast.CompositeLit) if !ok { @@ -292,7 +292,7 @@ func (r *stringFormatSubrule) stringIsOK(s string) bool { func (r *stringFormatSubrule) generateFailure(node ast.Node) { var failure string switch { - case len(r.errorMessage) > 0: + case r.errorMessage != "": failure = r.errorMessage case r.negated: failure = fmt.Sprintf("string literal matches user defined regex /%s/", r.regexp.String()) diff --git a/vendor/github.com/mgechev/revive/rule/struct_tag.go b/vendor/github.com/mgechev/revive/rule/struct_tag.go index 5cfa31c87..0830a257d 100644 --- a/vendor/github.com/mgechev/revive/rule/struct_tag.go +++ b/vendor/github.com/mgechev/revive/rule/struct_tag.go @@ -8,12 +8,15 @@ import ( "strings" "github.com/fatih/structtag" + + "github.com/mgechev/revive/internal/astutils" "github.com/mgechev/revive/lint" ) // StructTagRule lints struct tags. type StructTagRule struct { userDefined map[tagKey][]string // map: key -> []option + omittedTags map[tagKey]struct{} // set of tags that must not be analyzed } type tagKey string @@ -21,6 +24,8 @@ type tagKey string const ( keyASN1 tagKey = "asn1" keyBSON tagKey = "bson" + keyCbor tagKey = "cbor" + keyCodec tagKey = "codec" keyDatastore tagKey = "datastore" keyDefault tagKey = "default" keyJSON tagKey = "json" @@ -28,6 +33,7 @@ const ( keyProperties tagKey = "properties" keyProtobuf tagKey = "protobuf" keyRequired tagKey = "required" + keySpanner tagKey = "spanner" keyTOML tagKey = "toml" keyURL tagKey = "url" keyValidate tagKey = "validate" @@ -35,12 +41,13 @@ const ( keyYAML tagKey = "yaml" ) -type tagChecker func(checkCtx *checkContext, tag *structtag.Tag, fieldType ast.Expr) (message string, succeeded bool) +type tagChecker func(checkCtx *checkContext, tag *structtag.Tag, field *ast.Field) (message string, succeeded bool) -// populate tag checkers map var tagCheckers = map[tagKey]tagChecker{ keyASN1: checkASN1Tag, keyBSON: checkBSONTag, + keyCbor: checkCborTag, + keyCodec: checkCodecTag, keyDatastore: checkDatastoreTag, keyDefault: checkDefaultTag, keyJSON: checkJSONTag, @@ -48,6 +55,7 @@ var tagCheckers = map[tagKey]tagChecker{ keyProperties: checkPropertiesTag, keyProtobuf: checkProtobufTag, keyRequired: checkRequiredTag, + keySpanner: checkSpannerTag, keyTOML: checkTOMLTag, keyURL: checkURLTag, keyValidate: checkValidateTag, @@ -59,6 +67,7 @@ type checkContext struct { userDefined map[tagKey][]string // map: key -> []option usedTagNbr map[int]bool // list of used tag numbers usedTagName map[string]bool // list of used tag keys + commonOptions map[string]bool // list of options defined for all fields isAtLeastGo124 bool } @@ -71,6 +80,23 @@ func (checkCtx checkContext) isUserDefined(key tagKey, opt string) bool { return slices.Contains(options, opt) } +func (checkCtx *checkContext) isCommonOption(opt string) bool { + if checkCtx.commonOptions == nil { + return false + } + + _, ok := checkCtx.commonOptions[opt] + return ok +} + +func (checkCtx *checkContext) addCommonOption(opt string) { + if checkCtx.commonOptions == nil { + checkCtx.commonOptions = map[string]bool{} + } + + checkCtx.commonOptions[opt] = true +} + // Configure validates the rule configuration, and configures the rule accordingly. // // Configuration implements the [lint.ConfigurableRule] interface. @@ -84,17 +110,23 @@ func (r *StructTagRule) Configure(arguments lint.Arguments) error { return err } - r.userDefined = make(map[tagKey][]string, len(arguments)) + r.userDefined = map[tagKey][]string{} + r.omittedTags = map[tagKey]struct{}{} for _, arg := range arguments { item, ok := arg.(string) if !ok { return fmt.Errorf("invalid argument to the %s rule. Expecting a string, got %v (of type %T)", r.Name(), arg, arg) } + parts := strings.Split(item, ",") - if len(parts) < 2 { - return fmt.Errorf("invalid argument to the %s rule. Expecting a string of the form key[,option]+, got %s", r.Name(), item) + keyStr := strings.TrimSpace(parts[0]) + keyStr, isOmitted := strings.CutPrefix(keyStr, "!") + key := tagKey(keyStr) + if isOmitted { + r.omittedTags[key] = struct{}{} + continue } - key := tagKey(strings.TrimSpace(parts[0])) + for i := 1; i < len(parts); i++ { option := strings.TrimSpace(parts[i]) r.userDefined[key] = append(r.userDefined[key], option) @@ -114,6 +146,7 @@ func (r *StructTagRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure w := lintStructTagRule{ onFailure: onFailure, userDefined: r.userDefined, + omittedTags: r.omittedTags, isAtLeastGo124: file.Pkg.IsAtLeastGoVersion(lint.Go124), tagCheckers: tagCheckers, } @@ -131,13 +164,13 @@ func (*StructTagRule) Name() string { type lintStructTagRule struct { onFailure func(lint.Failure) userDefined map[tagKey][]string // map: key -> []option + omittedTags map[tagKey]struct{} isAtLeastGo124 bool tagCheckers map[tagKey]tagChecker } func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor { - switch n := node.(type) { - case *ast.StructType: + if n, ok := node.(*ast.StructType); ok { isEmptyStruct := n.Fields == nil || n.Fields.NumFields() < 1 if isEmptyStruct { return nil // skip empty structs @@ -162,34 +195,73 @@ func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor { // checkTaggedField checks the tag of the given field. // precondition: the field has a tag -func (w lintStructTagRule) checkTaggedField(checkCtx *checkContext, f *ast.Field) { - if len(f.Names) > 0 && !f.Names[0].IsExported() { - w.addFailuref(f, "tag on not-exported field %s", f.Names[0].Name) - } - - tags, err := structtag.Parse(strings.Trim(f.Tag.Value, "`")) +func (w lintStructTagRule) checkTaggedField(checkCtx *checkContext, field *ast.Field) { + tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")) if err != nil || tags == nil { - w.addFailuref(f.Tag, "malformed tag") + w.addFailuref(field.Tag, "malformed tag") return } + analyzedTags := map[tagKey]struct{}{} for _, tag := range tags.Tags() { + _, mustOmit := w.omittedTags[tagKey(tag.Key)] + if mustOmit { + continue + } + if msg, ok := w.checkTagNameIfNeed(checkCtx, tag); !ok { - w.addFailureWithTagKey(f.Tag, msg, tag.Key) + w.addFailureWithTagKey(field.Tag, msg, tag.Key) + } + + if msg, ok := checkOptionsOnIgnoredField(tag); !ok { + w.addFailureWithTagKey(field.Tag, msg, tag.Key) } - checker, ok := w.tagCheckers[tagKey(tag.Key)] + key := tagKey(tag.Key) + checker, ok := w.tagCheckers[key] if !ok { continue // we don't have a checker for the tag } - msg, ok := checker(checkCtx, tag, f.Type) + msg, ok := checker(checkCtx, tag, field) if !ok { - w.addFailureWithTagKey(f.Tag, msg, tag.Key) + w.addFailureWithTagKey(field.Tag, msg, tag.Key) } + + analyzedTags[key] = struct{}{} + } + + if w.shallWarnOnUnexportedField(field.Names, analyzedTags) { + w.addFailuref(field, "tag on not-exported field %s", field.Names[0].Name) } } +// tagKeyToSpecialField maps tag keys to their "special" meaning struct fields. +var tagKeyToSpecialField = map[tagKey]string{ + "codec": structTagCodecSpecialField, +} + +func (lintStructTagRule) shallWarnOnUnexportedField(fieldNames []*ast.Ident, tags map[tagKey]struct{}) bool { + if len(fieldNames) != 1 { // only handle the case of single field name (99.999% of cases) + return false + } + + if fieldNames[0].IsExported() { + return false + } + + fieldNameStr := fieldNames[0].Name + + for key := range tags { + specialField, ok := tagKeyToSpecialField[key] + if ok && specialField == fieldNameStr { + return false + } + } + + return true +} + func (w lintStructTagRule) checkTagNameIfNeed(checkCtx *checkContext, tag *structtag.Tag) (message string, succeeded bool) { isUnnamedTag := tag.Name == "" || tag.Name == "-" if isUnnamedTag { @@ -198,7 +270,7 @@ func (w lintStructTagRule) checkTagNameIfNeed(checkCtx *checkContext, tag *struc key := tagKey(tag.Key) switch key { - case keyBSON, keyJSON, keyXML, keyYAML, keyProtobuf: + case keyBSON, keyCodec, keyJSON, keyProtobuf, keySpanner, keyXML, keyYAML: // keys that need to check for duplicated tags default: return "", true } @@ -235,8 +307,9 @@ func (lintStructTagRule) getTagName(tag *structtag.Tag) string { } } -func checkASN1Tag(checkCtx *checkContext, tag *structtag.Tag, fieldType ast.Expr) (message string, succeeded bool) { - checkList := append(tag.Options, tag.Name) +func checkASN1Tag(checkCtx *checkContext, tag *structtag.Tag, field *ast.Field) (message string, succeeded bool) { + fieldType := field.Type + checkList := slices.Concat(tag.Options, []string{tag.Name}) for _, opt := range checkList { switch opt { case "application", "explicit", "generalized", "ia5", "omitempty", "optional", "set", "utf8": @@ -276,7 +349,7 @@ func checkCompoundANS1Option(checkCtx *checkContext, opt string, fieldType ast.E return "", true } -func checkDatastoreTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkDatastoreTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "flatten", "noindex", "omitempty": @@ -291,15 +364,15 @@ func checkDatastoreTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) ( return "", true } -func checkDefaultTag(_ *checkContext, tag *structtag.Tag, fieldType ast.Expr) (message string, succeeded bool) { - if !typeValueMatch(fieldType, tag.Name) { +func checkDefaultTag(_ *checkContext, tag *structtag.Tag, field *ast.Field) (message string, succeeded bool) { + if !typeValueMatch(field.Type, tag.Name) { return msgTypeMismatch, false } return "", true } -func checkBSONTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkBSONTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "inline", "minsize", "omitempty": @@ -314,7 +387,92 @@ func checkBSONTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messa return "", true } -func checkJSONTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkCborTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { + hasToArray := false + hasOmitEmptyOrZero := false + hasKeyAsInt := false + + for _, opt := range tag.Options { + switch opt { + case "omitempty", "omitzero": + hasOmitEmptyOrZero = true + case "toarray": + if tag.Name != "" { + return `tag name for option "toarray" should be empty`, false + } + hasToArray = true + case "keyasint": + intKey, err := strconv.Atoi(tag.Name) + if err != nil { + return `tag name for option "keyasint" should be an integer`, false + } + + _, ok := checkCtx.usedTagNbr[intKey] + if ok { + return fmt.Sprintf("duplicated integer key %d", intKey), false + } + + checkCtx.usedTagNbr[intKey] = true + hasKeyAsInt = true + continue + + default: + if !checkCtx.isUserDefined(keyCbor, opt) { + return fmt.Sprintf(msgUnknownOption, opt), false + } + } + } + + // Check for duplicated tag names + if tag.Name != "" { + _, ok := checkCtx.usedTagName[tag.Name] + if ok { + return fmt.Sprintf("duplicated tag name %s", tag.Name), false + } + checkCtx.usedTagName[tag.Name] = true + } + + // Check for integer tag names without keyasint option + if !hasKeyAsInt { + _, err := strconv.Atoi(tag.Name) + if err == nil { + return `integer tag names are only allowed in presence of "keyasint" option`, false + } + } + + if hasToArray && hasOmitEmptyOrZero { + return `options "omitempty" and "omitzero" are ignored in presence of "toarray" option`, false + } + + return "", true +} + +const structTagCodecSpecialField = "_struct" + +func checkCodecTag(checkCtx *checkContext, tag *structtag.Tag, field *ast.Field) (message string, succeeded bool) { + fieldNames := field.Names + mustAddToCommonOptions := len(fieldNames) == 1 && fieldNames[0].Name == structTagCodecSpecialField // see https://github.com/mgechev/revive/issues/1477#issuecomment-3191493076 + for _, opt := range tag.Options { + if mustAddToCommonOptions { + checkCtx.addCommonOption(opt) + } else if checkCtx.isCommonOption(opt) { + return fmt.Sprintf("redundant option %q, already set for all fields", opt), false + } + + switch opt { + case "omitempty", "toarray", "int", "uint", "float", "-", "omitemptyarray": + default: + if checkCtx.isUserDefined(keyCodec, opt) { + continue + } + return fmt.Sprintf(msgUnknownOption, opt), false + } + } + + return "", true +} + +func checkJSONTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "omitempty", "string": @@ -339,7 +497,7 @@ func checkJSONTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messa return "", true } -func checkMapstructureTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkMapstructureTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "omitempty", "reminder", "squash": @@ -354,13 +512,14 @@ func checkMapstructureTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr return "", true } -func checkPropertiesTag(_ *checkContext, tag *structtag.Tag, fieldType ast.Expr) (message string, succeeded bool) { +func checkPropertiesTag(_ *checkContext, tag *structtag.Tag, field *ast.Field) (message string, succeeded bool) { options := tag.Options if len(options) == 0 { return "", true } seenOptions := map[string]bool{} + fieldType := field.Type for _, opt := range options { msg, ok := fmt.Sprintf("unknown or malformed option %q", opt), false if key, value, found := strings.Cut(opt, "="); found { @@ -391,7 +550,7 @@ func checkCompoundPropertiesOption(key, value string, fieldType ast.Expr, seenOp return msgTypeMismatch, false } case "layout": - if gofmt(fieldType) != "time.Time" { + if astutils.GoFmt(fieldType) != "time.Time" { return "layout option is only applicable to fields of type time.Time", false } } @@ -399,7 +558,7 @@ func checkCompoundPropertiesOption(key, value string, fieldType ast.Expr, seenOp return "", true } -func checkProtobufTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkProtobufTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { // check name switch tag.Name { case "bytes", "fixed32", "fixed64", "group", "varint", "zigzag32", "zigzag64": @@ -452,7 +611,7 @@ func checkProtobufOptions(checkCtx *checkContext, options []string) (message str return "", true } -func checkRequiredTag(_ *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkRequiredTag(_ *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { switch tag.Name { case "true", "false": return "", true @@ -461,7 +620,7 @@ func checkRequiredTag(_ *checkContext, tag *structtag.Tag, _ ast.Expr) (message } } -func checkTOMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkTOMLTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "omitempty": @@ -476,12 +635,12 @@ func checkTOMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messa return "", true } -func checkURLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkURLTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { var delimiter = "" for _, opt := range tag.Options { switch opt { - case "int", "omitempty", "numbered", "brackets": - case "unix", "unixmilli", "unixnano": // TODO : check that the field is of type time.Time + case "int", "omitempty", "numbered", "brackets", + "unix", "unixmilli", "unixnano": // TODO : check that the field is of type time.Time case "comma", "semicolon", "space": if delimiter == "" { delimiter = opt @@ -499,7 +658,7 @@ func checkURLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messag return "", true } -func checkValidateTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkValidateTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { previousOption := "" seenKeysOption := false options := append([]string{tag.Name}, tag.Options...) @@ -528,7 +687,7 @@ func checkValidateTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (m return "", true } -func checkXMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkXMLTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "any", "attr", "cdata", "chardata", "comment", "innerxml", "omitempty", "typeattr": @@ -543,7 +702,7 @@ func checkXMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messag return "", true } -func checkYAMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) { +func checkYAMLTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { for _, opt := range tag.Options { switch opt { case "flow", "inline", "omitempty": @@ -558,6 +717,38 @@ func checkYAMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messa return "", true } +func checkSpannerTag(checkCtx *checkContext, tag *structtag.Tag, _ *ast.Field) (message string, succeeded bool) { + for _, opt := range tag.Options { + if !checkCtx.isUserDefined(keySpanner, opt) { + return fmt.Sprintf(msgUnknownOption, opt), false + } + } + + return "", true +} + +// checkOptionsOnIgnoredField checks if an ignored struct field (tag name "-") has any options specified. +// It returns a message and false if there are useless options present, or an empty message and true if valid. +func checkOptionsOnIgnoredField(tag *structtag.Tag) (message string, succeeded bool) { + if tag.Name != "-" { + return "", true + } + + switch len(tag.Options) { + case 0: + return "", true + case 1: + opt := strings.TrimSpace(tag.Options[0]) + if opt == "" { + return "", true // accept "-," as options + } + + return fmt.Sprintf("useless option %s for ignored field", opt), false + default: + return fmt.Sprintf("useless options %s for ignored field", strings.Join(tag.Options, ",")), false + } +} + func checkValidateOptionsAlternatives(checkCtx *checkContext, alternatives []string) (message string, succeeded bool) { for _, alternative := range alternatives { alternative := strings.TrimSpace(alternative) @@ -597,16 +788,14 @@ func typeValueMatch(t ast.Expr, val string) bool { case "int": _, err := strconv.ParseInt(val, 10, 64) typeMatches = err == nil - case "string": - case "nil": - default: + default: // "string", "nil", ... // unchecked type } return typeMatches } -func (w lintStructTagRule) addFailureWithTagKey(n ast.Node, msg string, tagKey string) { +func (w lintStructTagRule) addFailureWithTagKey(n ast.Node, msg, tagKey string) { w.addFailuref(n, "%s in %s tag", msg, tagKey) } @@ -638,101 +827,185 @@ const ( ) var validateSingleOptions = map[string]struct{}{ - "alpha": {}, - "alphanum": {}, - "alphanumunicode": {}, - "alphaunicode": {}, - "ascii": {}, - "base32": {}, - "base64": {}, - "base64url": {}, - "bcp47_language_tag": {}, - "boolean": {}, - "bic": {}, - "btc_addr": {}, - "btc_addr_bech32": {}, - "cidr": {}, - "cidrv4": {}, - "cidrv6": {}, - "country_code": {}, - "credit_card": {}, - "cron": {}, - "cve": {}, - "datauri": {}, - "dir": {}, - "dirpath": {}, - "dive": {}, - "dns_rfc1035_label": {}, - "e164": {}, - "email": {}, - "eth_addr": {}, - "file": {}, - "filepath": {}, - "fqdn": {}, - "hexadecimal": {}, - "hexcolor": {}, - "hostname": {}, - "hostname_port": {}, - "hostname_rfc1123": {}, - "hsl": {}, - "hsla": {}, - "html": {}, - "html_encoded": {}, - "image": {}, - "ip": {}, - "ip4_addr": {}, - "ip6_addr": {}, - "ip_addr": {}, - "ipv4": {}, - "ipv6": {}, - "isbn": {}, - "isbn10": {}, - "isbn13": {}, - "isdefault": {}, - "iso3166_1_alpha2": {}, - "iso3166_1_alpha3": {}, - "iscolor": {}, - "json": {}, - "jwt": {}, - "latitude": {}, - "longitude": {}, - "lowercase": {}, - "luhn_checksum": {}, - "mac": {}, - "mongodb": {}, - "mongodb_connection_string": {}, - "multibyte": {}, - "nostructlevel": {}, - "number": {}, - "numeric": {}, - "omitempty": {}, - "printascii": {}, - "required": {}, - "rgb": {}, - "rgba": {}, - "semver": {}, - "ssn": {}, - "structonly": {}, - "tcp_addr": {}, - "tcp4_addr": {}, - "tcp6_addr": {}, - "timezone": {}, - "udp4_addr": {}, - "udp6_addr": {}, - "ulid": {}, - "unique": {}, - "unix_addr": {}, - "uppercase": {}, - "uri": {}, - "url": {}, - "url_encoded": {}, - "urn_rfc2141": {}, - "uuid": {}, - "uuid3": {}, - "uuid4": {}, - "uuid5": {}, + "alpha": {}, + "alphanum": {}, + "alphanumunicode": {}, + "alphaunicode": {}, + "ascii": {}, + "base32": {}, + "base64": {}, + "base64rawurl": {}, + "base64url": {}, + "bcp47_language_tag": {}, + "bic": {}, + "boolean": {}, + "btc_addr": {}, + "btc_addr_bech32": {}, + "cidr": {}, + "cidrv4": {}, + "cidrv6": {}, + "contains": {}, + "containsany": {}, + "containsrune": {}, + "credit_card": {}, + "cron": {}, + "cve": {}, + "datauri": {}, + "datetime": {}, + "dir": {}, + "dirpath": {}, + "dive": {}, + "dns_rfc1035_label": {}, + "e164": {}, + "ein": {}, + "email": {}, + "endsnotwith": {}, + "endswith": {}, + "eq": {}, + "eq_ignore_case": {}, + "eqcsfield": {}, + "eqfield": {}, + "eth_addr": {}, + "eth_addr_checksum": {}, + "excluded_if": {}, + "excluded_unless": {}, + "excluded_with": {}, + "excluded_with_all": {}, + "excluded_without": {}, + "excluded_without_all": {}, + "excludes": {}, + "excludesall": {}, + "excludesrune": {}, + "fieldcontains": {}, + "fieldexcludes": {}, + "file": {}, + "filepath": {}, + "fqdn": {}, + "gt": {}, + "gtcsfield": {}, + "gte": {}, + "gtecsfield": {}, + "gtefield": {}, + "gtfield": {}, + "hexadecimal": {}, + "hexcolor": {}, + "hostname": {}, + "hostname_port": {}, + "hostname_rfc1123": {}, + "hsl": {}, + "hsla": {}, + "html": {}, + "html_encoded": {}, + "http_url": {}, + "image": {}, + "ip": {}, + "ip4_addr": {}, + "ip6_addr": {}, + "ip_addr": {}, + "ipv4": {}, + "ipv6": {}, + "isbn": {}, + "isbn10": {}, + "isbn13": {}, + "isdefault": {}, + "iso3166_1_alpha2": {}, + "iso3166_1_alpha2_eu": {}, + "iso3166_1_alpha3": {}, + "iso3166_1_alpha3_eu": {}, + "iso3166_1_alpha_numeric": {}, + "iso3166_1_alpha_numeric_eu": {}, + "iso3166_2": {}, + "iso4217": {}, + "iso4217_numeric": {}, + "issn": {}, + "json": {}, + "jwt": {}, + "latitude": {}, + "len": {}, + "longitude": {}, + "lowercase": {}, + "lt": {}, + "ltcsfield": {}, + "lte": {}, + "ltecsfield": {}, + "ltefield": {}, + "ltfield": {}, + "luhn_checksum": {}, + "mac": {}, + "max": {}, + "md4": {}, + "md5": {}, + "min": {}, + "mongodb": {}, + "mongodb_connection_string": {}, + "multibyte": {}, + "ne": {}, + "ne_ignore_case": {}, + "necsfield": {}, + "nefield": {}, + "number": {}, + "numeric": {}, + "omitempty": {}, + "omitnil": {}, + "omitzero": {}, + "oneof": {}, + "oneofci": {}, + "port": {}, + "postcode_iso3166_alpha2": {}, + "postcode_iso3166_alpha2_field": {}, + "printascii": {}, + "required": {}, + "required_if": {}, + "required_unless": {}, + "required_with": {}, + "required_with_all": {}, + "required_without": {}, + "required_without_all": {}, + "rgb": {}, + "rgba": {}, + "ripemd128": {}, + "ripemd160": {}, + "semver": {}, + "sha256": {}, + "sha384": {}, + "sha512": {}, + "skip_unless": {}, + "spicedb": {}, + "ssn": {}, + "startsnotwith": {}, + "startswith": {}, + "tcp4_addr": {}, + "tcp6_addr": {}, + "tcp_addr": {}, + "tiger128": {}, + "tiger160": {}, + "tiger192": {}, + "timezone": {}, + "udp4_addr": {}, + "udp6_addr": {}, + "udp_addr": {}, + "ulid": {}, + "unique": {}, + "unix_addr": {}, + "uppercase": {}, + "uri": {}, + "url": {}, + "url_encoded": {}, + "urn_rfc2141": {}, + "uuid": {}, + "uuid3": {}, + "uuid3_rfc4122": {}, + "uuid4": {}, + "uuid4_rfc4122": {}, + "uuid5": {}, + "uuid5_rfc4122": {}, + "uuid_rfc4122": {}, + "validateFn": {}, } +// These are options that are used in expressions of the form: +// +//