commit
bb240a6e40
|
@ -1,16 +1,29 @@
|
|||
---
|
||||
version: "2"
|
||||
|
||||
run:
|
||||
build-tags:
|
||||
- apparmor
|
||||
- seccomp
|
||||
- selinux
|
||||
# Don't exceed number of threads available when running under CI
|
||||
concurrency: 4
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofumpt
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- nolintlint
|
||||
- revive
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- whitespace
|
||||
exclusions:
|
||||
presets:
|
||||
- comments
|
||||
- std-error-handling
|
||||
settings:
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
- -QF1008 # https://staticcheck.dev/docs/checks/#QF1008 Omit embedded fields from selector expression.
|
||||
|
|
4
Makefile
4
Makefile
|
@ -52,6 +52,9 @@ ifeq ($(BUILDDEBUG), 1)
|
|||
override GOGCFLAGS += -N -l
|
||||
endif
|
||||
|
||||
# Managed by renovate.
|
||||
export GOLANGCI_LINT_VERSION := 2.0.2
|
||||
|
||||
# make all BUILDDEBUG=1
|
||||
# Note: Uses the -N -l go compiler options to disable compiler optimizations
|
||||
# and inlining. Using these build options allows you to subsequently
|
||||
|
@ -192,6 +195,7 @@ vendor:
|
|||
.PHONY: lint
|
||||
lint: install.tools
|
||||
./tests/tools/build/golangci-lint run $(LINTFLAGS)
|
||||
./tests/tools/build/golangci-lint run --tests=false $(LINTFLAGS)
|
||||
|
||||
# CAUTION: This is not a replacement for RPMs provided by your distro.
|
||||
# Only intended to build and test the latest unreleased changes.
|
||||
|
|
7
add.go
7
add.go
|
@ -454,10 +454,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
|
|||
}
|
||||
|
||||
// if the destination is a directory that doesn't yet exist, let's copy it.
|
||||
newDestDirFound := false
|
||||
if (len(destStats) == 1 || len(destStats[0].Globbed) == 0) && destMustBeDirectory && !destCanBeFile {
|
||||
newDestDirFound = true
|
||||
}
|
||||
newDestDirFound := (len(destStats) == 1 || len(destStats[0].Globbed) == 0) && destMustBeDirectory && !destCanBeFile
|
||||
|
||||
if len(destStats) == 1 && len(destStats[0].Globbed) == 1 && destStats[0].Results[destStats[0].Globbed[0]].IsRegular {
|
||||
if destMustBeDirectory {
|
||||
|
@ -625,7 +622,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
|
|||
}
|
||||
// Check for dockerignore-style exclusion of this item.
|
||||
if rel != "." {
|
||||
excluded, err := pm.Matches(filepath.ToSlash(rel)) // nolint:staticcheck
|
||||
excluded, err := pm.Matches(filepath.ToSlash(rel)) //nolint:staticcheck
|
||||
if err != nil {
|
||||
return fmt.Errorf("checking if %q(%q) is excluded: %w", globbed, rel, err)
|
||||
}
|
||||
|
|
|
@ -316,7 +316,7 @@ func TestProcessRlimits(t *testing.T) {
|
|||
rlim = &report.Spec.Process.Rlimits[i]
|
||||
}
|
||||
}
|
||||
if limit == unix.RLIM_INFINITY && !(rlim == nil || (rlim.Soft == unix.RLIM_INFINITY && rlim.Hard == unix.RLIM_INFINITY)) {
|
||||
if limit == unix.RLIM_INFINITY && rlim != nil && (rlim.Soft != unix.RLIM_INFINITY || rlim.Hard != unix.RLIM_INFINITY) {
|
||||
t.Fatalf("wasn't supposed to set limit on number of open files: %#v", rlim)
|
||||
}
|
||||
if limit != unix.RLIM_INFINITY && rlim == nil {
|
||||
|
|
|
@ -4,16 +4,12 @@ package chroot
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/common/pkg/seccomp"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const seccompAvailable = true
|
||||
|
||||
// setSeccomp sets the seccomp filter for ourselves and any processes that we'll start.
|
||||
func setSeccomp(spec *specs.Spec) error {
|
||||
logrus.Debugf("setting seccomp configuration")
|
||||
|
@ -178,27 +174,3 @@ func setSeccomp(spec *specs.Spec) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
|
||||
switch seccompProfilePath {
|
||||
case "unconfined":
|
||||
spec.Linux.Seccomp = nil
|
||||
case "":
|
||||
seccompConfig, err := seccomp.GetDefaultProfile(spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading default seccomp profile failed: %w", err)
|
||||
}
|
||||
spec.Linux.Seccomp = seccompConfig
|
||||
default:
|
||||
seccompProfile, err := os.ReadFile(seccompProfilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening seccomp profile failed: %w", err)
|
||||
}
|
||||
seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading seccomp profile (%s) failed: %w", seccompProfilePath, err)
|
||||
}
|
||||
spec.Linux.Seccomp = seccompConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//go:build linux && seccomp
|
||||
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/common/pkg/seccomp"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
const seccompAvailable = true
|
||||
|
||||
func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
|
||||
switch seccompProfilePath {
|
||||
case "unconfined":
|
||||
spec.Linux.Seccomp = nil
|
||||
case "":
|
||||
seccompConfig, err := seccomp.GetDefaultProfile(spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading default seccomp profile failed: %w", err)
|
||||
}
|
||||
spec.Linux.Seccomp = seccompConfig
|
||||
default:
|
||||
seccompProfile, err := os.ReadFile(seccompProfilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening seccomp profile failed: %w", err)
|
||||
}
|
||||
seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading seccomp profile (%s) failed: %w", seccompProfilePath, err)
|
||||
}
|
||||
spec.Linux.Seccomp = seccompConfig
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -8,19 +8,9 @@ import (
|
|||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
const seccompAvailable = false
|
||||
|
||||
func setSeccomp(spec *specs.Spec) error {
|
||||
if spec.Linux.Seccomp != nil {
|
||||
return errors.New("configured a seccomp filter without seccomp support?")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
|
||||
if spec.Linux != nil {
|
||||
// runtime-tools may have supplied us with a default filter
|
||||
spec.Linux.Seccomp = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//go:build (!linux && !freebsd) || !seccomp
|
||||
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
const seccompAvailable = false
|
||||
|
||||
func setupSeccomp(spec *specs.Spec, _ string) error {
|
||||
if spec.Linux != nil {
|
||||
// runtime-tools may have supplied us with a default filter
|
||||
spec.Linux.Seccomp = nil
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -189,7 +189,7 @@ func imagesCmd(c *cobra.Command, args []string, iopts *imageResults) error {
|
|||
|
||||
func outputHeader(opts imageOptions) string {
|
||||
if opts.format != "" {
|
||||
return strings.Replace(opts.format, `\t`, "\t", -1)
|
||||
return strings.ReplaceAll(opts.format, `\t`, "\t")
|
||||
}
|
||||
if opts.quiet {
|
||||
return formats.IDString
|
||||
|
|
|
@ -73,7 +73,7 @@ func infoCmd(c *cobra.Command, iopts infoResults) error {
|
|||
}
|
||||
t, err := template.New("format").Parse(format)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Template parsing error: %w", err)
|
||||
return fmt.Errorf("template parsing error: %w", err)
|
||||
}
|
||||
if err = t.Execute(os.Stdout, info); err != nil {
|
||||
return err
|
||||
|
|
|
@ -115,7 +115,7 @@ func inspectCmd(c *cobra.Command, args []string, iopts inspectResults) error {
|
|||
}
|
||||
t, err := template.New("format").Parse(format)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Template parsing error: %w", err)
|
||||
return fmt.Errorf("template parsing error: %w", err)
|
||||
}
|
||||
if err = t.Execute(os.Stdout, out); err != nil {
|
||||
return err
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
"github.com/hashicorp/go-multierror"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -148,7 +147,7 @@ func init() {
|
|||
flags.StringVar(&manifestAddOpts.artifactConfigType, "artifact-config-type", imgspecv1.DescriptorEmptyJSON.MediaType, "artifact config media type")
|
||||
flags.StringVar(&manifestAddOpts.artifactConfigFile, "artifact-config", "", "artifact config file")
|
||||
flags.StringVar(&manifestAddOpts.artifactLayerType, "artifact-layer-type", "", "artifact layer media type")
|
||||
flags.BoolVar(&manifestAddOpts.artifactExcludeTitles, "artifact-exclude-titles", false, fmt.Sprintf(`refrain from setting %q annotations on "layers"`, v1.AnnotationTitle))
|
||||
flags.BoolVar(&manifestAddOpts.artifactExcludeTitles, "artifact-exclude-titles", false, fmt.Sprintf(`refrain from setting %q annotations on "layers"`, imgspecv1.AnnotationTitle))
|
||||
flags.StringVar(&manifestAddOpts.artifactSubject, "artifact-subject", "", "artifact subject reference")
|
||||
flags.StringSliceVar(&manifestAddOpts.artifactAnnotations, "artifact-annotation", nil, "artifact annotation")
|
||||
flags.StringVar(&manifestAddOpts.authfile, "authfile", auth.GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||
|
@ -291,7 +290,7 @@ func init() {
|
|||
|
||||
func manifestExistsCmd(c *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("At least a name must be specified for the list")
|
||||
return errors.New("at least a name must be specified for the list")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
|
@ -322,7 +321,7 @@ func manifestExistsCmd(c *cobra.Command, args []string) error {
|
|||
|
||||
func manifestCreateCmd(c *cobra.Command, args []string, opts manifestCreateOpts) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("At least a name must be specified for the list")
|
||||
return errors.New("at least a name must be specified for the list")
|
||||
}
|
||||
listImageSpec := args[0]
|
||||
imageSpecs := args[1:]
|
||||
|
@ -433,21 +432,21 @@ func manifestAddCmd(c *cobra.Command, args []string, opts manifestAddOpts) error
|
|||
artifactSpec := []string{}
|
||||
switch len(args) {
|
||||
case 0, 1:
|
||||
return errors.New("At least a list image and an image or artifact to add must be specified")
|
||||
return errors.New("at least a list image and an image or artifact to add must be specified")
|
||||
default:
|
||||
listImageSpec = args[0]
|
||||
if listImageSpec == "" {
|
||||
return fmt.Errorf("Invalid image name %q", args[0])
|
||||
return fmt.Errorf("invalid image name %q", args[0])
|
||||
}
|
||||
if opts.artifact {
|
||||
artifactSpec = args[1:]
|
||||
} else {
|
||||
if len(args) > 2 {
|
||||
return errors.New("Too many arguments: expected list and image add to list")
|
||||
return errors.New("too many arguments: expected list and image add to list")
|
||||
}
|
||||
imageSpec = args[1]
|
||||
if imageSpec == "" {
|
||||
return fmt.Errorf("Invalid image name %q", args[1])
|
||||
return fmt.Errorf("invalid image name %q", args[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -635,18 +634,18 @@ func manifestRemoveCmd(c *cobra.Command, args []string, _ manifestRemoveOpts) er
|
|||
var instanceSpec string
|
||||
switch len(args) {
|
||||
case 0, 1:
|
||||
return errors.New("At least a list image and one or more instance digests must be specified")
|
||||
return errors.New("at least a list image and one or more instance digests must be specified")
|
||||
case 2:
|
||||
listImageSpec = args[0]
|
||||
if listImageSpec == "" {
|
||||
return fmt.Errorf(`Invalid image name "%s"`, args[0])
|
||||
return fmt.Errorf(`invalid image name "%s"`, args[0])
|
||||
}
|
||||
instanceSpec = args[1]
|
||||
if instanceSpec == "" {
|
||||
return fmt.Errorf(`Invalid instance "%s"`, args[1])
|
||||
return fmt.Errorf(`invalid instance "%s"`, args[1])
|
||||
}
|
||||
default:
|
||||
return errors.New("At least two arguments are necessary: list and digest of instance to remove from list")
|
||||
return errors.New("at least two arguments are necessary: list and digest of instance to remove from list")
|
||||
}
|
||||
|
||||
store, err := getStore(c)
|
||||
|
@ -677,23 +676,23 @@ func manifestRemoveCmd(c *cobra.Command, args []string, _ manifestRemoveOpts) er
|
|||
if err != nil {
|
||||
if instanceRef, err = alltransports.ParseImageName(util.DefaultTransport + instanceSpec); err != nil {
|
||||
if instanceRef, _, err = util.FindImage(store, "", systemContext, instanceSpec); err != nil {
|
||||
return fmt.Errorf(`Invalid instance "%s": %v`, instanceSpec, err)
|
||||
return fmt.Errorf(`invalid instance "%s": %v`, instanceSpec, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx := getContext()
|
||||
instanceImg, err := instanceRef.NewImageSource(ctx, systemContext)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Reading image instance: %w", err)
|
||||
return fmt.Errorf("reading image instance: %w", err)
|
||||
}
|
||||
defer instanceImg.Close()
|
||||
manifestBytes, _, err := image.UnparsedInstance(instanceImg, nil).Manifest(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Reading image instance manifest: %w", err)
|
||||
return fmt.Errorf("reading image instance manifest: %w", err)
|
||||
}
|
||||
d, err = manifest.Digest(manifestBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Digesting image instance manifest: %w", err)
|
||||
return fmt.Errorf("digesting image instance manifest: %w", err)
|
||||
}
|
||||
}
|
||||
instanceDigest = d
|
||||
|
@ -752,29 +751,29 @@ func manifestAnnotateCmd(c *cobra.Command, args []string, opts manifestAnnotateO
|
|||
}
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return errors.New("At least a list image must be specified")
|
||||
return errors.New("at least a list image must be specified")
|
||||
case 1:
|
||||
listImageSpec = args[0]
|
||||
if listImageSpec == "" {
|
||||
return fmt.Errorf(`Invalid image name "%s"`, args[0])
|
||||
return fmt.Errorf(`invalid image name "%s"`, args[0])
|
||||
}
|
||||
if !opts.index {
|
||||
return errors.New(`Expected an instance digest, image name, or artifact name`)
|
||||
return errors.New(`expected an instance digest, image name, or artifact name`)
|
||||
}
|
||||
case 2:
|
||||
listImageSpec = args[0]
|
||||
if listImageSpec == "" {
|
||||
return fmt.Errorf(`Invalid image name "%s"`, args[0])
|
||||
return fmt.Errorf(`invalid image name "%s"`, args[0])
|
||||
}
|
||||
if opts.index {
|
||||
return fmt.Errorf(`Did not expect image or artifact name "%s" when modifying the entire index`, args[1])
|
||||
return fmt.Errorf(`did not expect image or artifact name "%s" when modifying the entire index`, args[1])
|
||||
}
|
||||
instanceSpec = args[1]
|
||||
if instanceSpec == "" {
|
||||
return fmt.Errorf(`Invalid instance digest, image name, or artifact name "%s"`, instanceSpec)
|
||||
return fmt.Errorf(`invalid instance digest, image name, or artifact name "%s"`, instanceSpec)
|
||||
}
|
||||
default:
|
||||
return errors.New("Expected either a list name and --index or a list name and an image digest or image name or artifact name")
|
||||
return errors.New("expected either a list name and --index or a list name and an image digest or image name or artifact name")
|
||||
}
|
||||
|
||||
store, err := getStore(c)
|
||||
|
@ -817,23 +816,23 @@ func manifestAnnotateCmd(c *cobra.Command, args []string, opts manifestAnnotateO
|
|||
if instanceRef, err = alltransports.ParseImageName(util.DefaultTransport + instanceSpec); err != nil {
|
||||
// check if the local image exists
|
||||
if instanceRef, _, err = util.FindImage(store, "", systemContext, instanceSpec); err != nil {
|
||||
return fmt.Errorf(`Invalid instance "%s": %v`, instanceSpec, err)
|
||||
return fmt.Errorf(`invalid instance "%s": %v`, instanceSpec, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx := getContext()
|
||||
instanceImg, err := instanceRef.NewImageSource(ctx, systemContext)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Reading image instance: %w", err)
|
||||
return fmt.Errorf("reading image instance: %w", err)
|
||||
}
|
||||
defer instanceImg.Close()
|
||||
manifestBytes, _, err := image.UnparsedInstance(instanceImg, nil).Manifest(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Reading image instance manifest: %w", err)
|
||||
return fmt.Errorf("reading image instance manifest: %w", err)
|
||||
}
|
||||
d, err = manifest.Digest(manifestBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Digesting image instance manifest: %w", err)
|
||||
return fmt.Errorf("digesting image instance manifest: %w", err)
|
||||
}
|
||||
}
|
||||
instance = d
|
||||
|
@ -964,14 +963,14 @@ func manifestInspectCmd(c *cobra.Command, args []string, opts manifestInspectOpt
|
|||
imageSpec := ""
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return errors.New("At least a source list ID must be specified")
|
||||
return errors.New("at least a source list ID must be specified")
|
||||
case 1:
|
||||
imageSpec = args[0]
|
||||
if imageSpec == "" {
|
||||
return fmt.Errorf(`Invalid image name "%s"`, imageSpec)
|
||||
return fmt.Errorf(`invalid image name "%s"`, imageSpec)
|
||||
}
|
||||
default:
|
||||
return errors.New("Only one argument is necessary for inspect: an image name")
|
||||
return errors.New("only one argument is necessary for inspect: an image name")
|
||||
}
|
||||
|
||||
store, err := getStore(c)
|
||||
|
@ -1093,7 +1092,7 @@ func manifestPushCmd(c *cobra.Command, args []string, opts pushOptions) error {
|
|||
destSpec := ""
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return errors.New("At least a source list ID must be specified")
|
||||
return errors.New("at least a source list ID must be specified")
|
||||
case 1:
|
||||
listImageSpec = args[0]
|
||||
destSpec = "docker://" + listImageSpec
|
||||
|
@ -1101,7 +1100,7 @@ func manifestPushCmd(c *cobra.Command, args []string, opts pushOptions) error {
|
|||
listImageSpec = args[0]
|
||||
destSpec = args[1]
|
||||
default:
|
||||
return errors.New("Only two arguments are necessary to push: source and destination")
|
||||
return errors.New("only two arguments are necessary to push: source and destination")
|
||||
}
|
||||
if listImageSpec == "" {
|
||||
return fmt.Errorf(`invalid image name "%s"`, listImageSpec)
|
||||
|
|
|
@ -135,7 +135,7 @@ func pushCmd(c *cobra.Command, args []string, iopts pushOptions) error {
|
|||
return fmt.Errorf(`invalid image name "%s"`, args[0])
|
||||
}
|
||||
default:
|
||||
return errors.New("Only two arguments are necessary to push: source and destination")
|
||||
return errors.New("only two arguments are necessary to push: source and destination")
|
||||
}
|
||||
|
||||
compress := define.Gzip
|
||||
|
|
|
@ -47,7 +47,7 @@ func renameCmd(c *cobra.Command, args []string) error {
|
|||
}
|
||||
|
||||
if build, err := openBuilder(getContext(), store, newName); err == nil {
|
||||
return fmt.Errorf("The container name %q is already in use by container %q", newName, build.ContainerID)
|
||||
return fmt.Errorf("the container name %q is already in use by container %q", newName, build.ContainerID)
|
||||
}
|
||||
|
||||
err = store.SetNames(builder.ContainerID, []string{newName})
|
||||
|
|
|
@ -30,10 +30,8 @@ func init() {
|
|||
}
|
||||
|
||||
func umountCmd(c *cobra.Command, args []string) error {
|
||||
umountAll := false
|
||||
if c.Flag("all").Changed {
|
||||
umountAll = true
|
||||
}
|
||||
umountAll := c.Flag("all").Changed
|
||||
|
||||
umountContainerErrStr := "error unmounting container"
|
||||
if len(args) == 0 && !umountAll {
|
||||
return errors.New("at least one container ID must be specified")
|
||||
|
|
|
@ -701,9 +701,9 @@ func copierWithSubprocess(bulkReader io.Reader, bulkWriter io.Writer, req reques
|
|||
bulkReaderRead = nil
|
||||
bulkWriterWrite.Close()
|
||||
bulkWriterWrite = nil
|
||||
killAndReturn := func(err error, step string) (*response, error) { // nolint: unparam
|
||||
killAndReturn := func(err error, step string) error {
|
||||
if err2 := cmd.Process.Kill(); err2 != nil {
|
||||
return nil, fmt.Errorf("killing subprocess: %v; %s: %w", err2, step, err)
|
||||
return fmt.Errorf("killing subprocess: %v; %s: %w", err2, step, err)
|
||||
}
|
||||
if errors.Is(err, io.ErrClosedPipe) || errors.Is(err, syscall.EPIPE) {
|
||||
err2 := cmd.Wait()
|
||||
|
@ -711,22 +711,22 @@ func copierWithSubprocess(bulkReader io.Reader, bulkWriter io.Writer, req reques
|
|||
err = fmt.Errorf("%s: %w", errorText, err)
|
||||
}
|
||||
if err2 != nil {
|
||||
return nil, fmt.Errorf("waiting on subprocess: %v; %s: %w", err2, step, err)
|
||||
return fmt.Errorf("waiting on subprocess: %v; %s: %w", err2, step, err)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("%v: %w", step, err)
|
||||
return fmt.Errorf("%v: %w", step, err)
|
||||
}
|
||||
if err = encoder.Encode(req); err != nil {
|
||||
return killAndReturn(err, "error encoding work request for copier subprocess")
|
||||
return nil, killAndReturn(err, "error encoding work request for copier subprocess")
|
||||
}
|
||||
if err = decoder.Decode(&resp); err != nil {
|
||||
if errors.Is(err, io.EOF) && errorBuffer.Len() > 0 {
|
||||
return killAndReturn(errors.New(errorBuffer.String()), "error in copier subprocess")
|
||||
return nil, killAndReturn(errors.New(errorBuffer.String()), "error in copier subprocess")
|
||||
}
|
||||
return killAndReturn(err, "error decoding response from copier subprocess")
|
||||
return nil, killAndReturn(err, "error decoding response from copier subprocess")
|
||||
}
|
||||
if err = encoder.Encode(&request{Request: requestQuit}); err != nil {
|
||||
return killAndReturn(err, "error encoding quit request for copier subprocess")
|
||||
return nil, killAndReturn(err, "error encoding quit request for copier subprocess")
|
||||
}
|
||||
stdinWrite.Close()
|
||||
stdinWrite = nil
|
||||
|
@ -975,7 +975,7 @@ func pathIsExcluded(root, path string, pm *fileutils.PatternMatcher) (string, bo
|
|||
// Matches uses filepath.FromSlash() to convert candidates before
|
||||
// checking if they match the patterns it's been given, implying that
|
||||
// it expects Unix-style paths.
|
||||
matches, err := pm.Matches(filepath.ToSlash(rel)) // nolint:staticcheck
|
||||
matches, err := pm.Matches(filepath.ToSlash(rel)) //nolint:staticcheck
|
||||
if err != nil {
|
||||
return rel, false, fmt.Errorf("copier: error checking if %q is excluded: %w", rel, err)
|
||||
}
|
||||
|
@ -1009,7 +1009,7 @@ func resolvePath(root, path string, evaluateFinalComponent bool, pm *fileutils.P
|
|||
}
|
||||
excluded = excluded || thisExcluded
|
||||
if !excluded {
|
||||
if target, err := os.Readlink(filepath.Join(workingPath, components[0])); err == nil && !(len(components) == 1 && !evaluateFinalComponent) {
|
||||
if target, err := os.Readlink(filepath.Join(workingPath, components[0])); err == nil && (len(components) != 1 || evaluateFinalComponent) {
|
||||
followed++
|
||||
if followed > maxLoopsFollowed {
|
||||
return "", &os.PathError{
|
||||
|
@ -1661,14 +1661,15 @@ func copierHandlerGetOne(srcfi os.FileInfo, symlinkTarget, name, contentPath str
|
|||
return fmt.Errorf("getting fflags: %w", err)
|
||||
}
|
||||
var f *os.File
|
||||
if hdr.Typeflag == tar.TypeReg {
|
||||
switch hdr.Typeflag {
|
||||
case tar.TypeReg:
|
||||
// open the file first so that we don't write a header for it if we can't actually read it
|
||||
f, err = os.Open(contentPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening file for adding its contents to archive: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
} else if hdr.Typeflag == tar.TypeDir {
|
||||
case tar.TypeDir:
|
||||
// open the directory file first to make sure we can access it.
|
||||
f, err = os.Open(contentPath)
|
||||
if err != nil {
|
||||
|
@ -2080,7 +2081,7 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM
|
|||
// set xattrs, including some that might have been reset by chown()
|
||||
if !req.PutOptions.StripXattrs {
|
||||
xattrs := mapWithPrefixedKeysWithoutKeyPrefix(hdr.PAXRecords, xattrPAXRecordNamespace)
|
||||
if err = Lsetxattrs(path, xattrs); err != nil { // nolint:staticcheck
|
||||
if err = Lsetxattrs(path, xattrs); err != nil {
|
||||
if !req.PutOptions.IgnoreXattrErrors {
|
||||
return fmt.Errorf("copier: put: error setting extended attributes on %q: %w", path, err)
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ func makeContents(length int64) io.ReadCloser {
|
|||
for count < length {
|
||||
if _, err := buffered.Write([]byte{"0123456789abcdef"[count%16]}); err != nil {
|
||||
buffered.Flush()
|
||||
pipeWriter.CloseWithError(err) // nolint:errcheck
|
||||
pipeWriter.CloseWithError(err)
|
||||
return
|
||||
}
|
||||
count++
|
||||
|
@ -111,7 +111,7 @@ func makeArchive(headers []tar.Header, contents map[string][]byte) io.ReadCloser
|
|||
tw.Close()
|
||||
buffered.Flush()
|
||||
if err != nil {
|
||||
pipeWriter.CloseWithError(err) // nolint:errcheck
|
||||
pipeWriter.CloseWithError(err)
|
||||
} else {
|
||||
pipeWriter.Close()
|
||||
}
|
||||
|
|
|
@ -3,9 +3,15 @@
|
|||
package copier
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
testModeMask = int64(os.ModePerm)
|
||||
testIgnoreSymlinkDates = false
|
||||
)
|
||||
|
||||
func TestPutChroot(t *testing.T) {
|
||||
if uid != 0 {
|
||||
t.Skip("chroot() requires root privileges, skipping")
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
//go:build windows
|
||||
|
||||
package copier
|
||||
|
||||
const (
|
||||
testModeMask = int64(0o600)
|
||||
testIgnoreSymlinkDates = true
|
||||
)
|
|
@ -84,8 +84,3 @@ func sameDevice(a, b os.FileInfo) bool {
|
|||
}
|
||||
return uA.Dev == uB.Dev
|
||||
}
|
||||
|
||||
const (
|
||||
testModeMask = int64(os.ModePerm)
|
||||
testIgnoreSymlinkDates = false
|
||||
)
|
||||
|
|
|
@ -81,8 +81,3 @@ func lutimes(isSymlink bool, path string, atime, mtime time.Time) error {
|
|||
func sameDevice(a, b os.FileInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
testModeMask = int64(0o600)
|
||||
testIgnoreSymlinkDates = true
|
||||
)
|
||||
|
|
|
@ -164,7 +164,7 @@ type V1Image struct {
|
|||
// V2Image stores the image configuration
|
||||
type V2Image struct {
|
||||
V1Image
|
||||
Parent ID `json:"parent,omitempty"` // nolint:govet
|
||||
Parent ID `json:"parent,omitempty"`
|
||||
RootFS *V2S2RootFS `json:"rootfs,omitempty"`
|
||||
History []V2S2History `json:"history,omitempty"`
|
||||
OSVersion string `json:"os.version,omitempty"`
|
||||
|
|
|
@ -451,7 +451,7 @@ func buildDockerfilesOnce(ctx context.Context, store storage.Store, logger *logr
|
|||
if options.Target != "" {
|
||||
stagesTargeted, ok := stages.ThroughTarget(options.Target)
|
||||
if !ok {
|
||||
return "", nil, fmt.Errorf("The target %q was not found in the provided Dockerfile", options.Target)
|
||||
return "", nil, fmt.Errorf("the target %q was not found in the provided Dockerfile", options.Target)
|
||||
}
|
||||
stages = stagesTargeted
|
||||
}
|
||||
|
|
|
@ -622,7 +622,7 @@ func (s *StageExecutor) runStageMountPoints(mountList []string) (map[string]inte
|
|||
if strings.Contains(flag, "from") {
|
||||
tokens := strings.Split(flag, ",")
|
||||
if len(tokens) < 2 {
|
||||
return nil, fmt.Errorf("Invalid --mount command: %s", flag)
|
||||
return nil, fmt.Errorf("invalid --mount command: %s", flag)
|
||||
}
|
||||
for _, token := range tokens {
|
||||
key, val, hasVal := strings.Cut(token, "=")
|
||||
|
@ -712,18 +712,16 @@ func (s *StageExecutor) runStageMountPoints(mountList []string) (map[string]inte
|
|||
MountPoint: otherStage.mountPoint,
|
||||
}
|
||||
break
|
||||
} else {
|
||||
// Treat the source's name as the name of an image.
|
||||
mountPoint, err := s.getImageRootfs(s.ctx, from)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s from=%s: no stage or image found with that name", flag, from)
|
||||
}
|
||||
stageMountPoints[from] = internal.StageMountDetails{
|
||||
IsImage: true,
|
||||
DidExecute: true,
|
||||
MountPoint: mountPoint,
|
||||
}
|
||||
break
|
||||
}
|
||||
// Otherwise, treat the source's name as the name of an image.
|
||||
mountPoint, err := s.getImageRootfs(s.ctx, from)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s from=%s: no stage or image found with that name", flag, from)
|
||||
}
|
||||
stageMountPoints[from] = internal.StageMountDetails{
|
||||
IsImage: true,
|
||||
DidExecute: true,
|
||||
MountPoint: mountPoint,
|
||||
}
|
||||
default:
|
||||
continue
|
||||
|
@ -1547,7 +1545,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// we need to call ib.Run() to correctly put the args together before
|
||||
// determining if a cached layer with the same build args already exists
|
||||
// and that is done in the if block below.
|
||||
if checkForLayers && step.Command != "arg" && !(s.executor.squash && lastInstruction && lastStage) && !avoidLookingCache {
|
||||
if checkForLayers && step.Command != "arg" && (!s.executor.squash || !lastInstruction || !lastStage) && !avoidLookingCache {
|
||||
// For `COPY` and `ADD`, history entries include digests computed from
|
||||
// the content that's copied in. We need to compute that information so that
|
||||
// it can be used to evaluate the cache, which means we need to go ahead
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
func importBuilderDataFromImage(ctx context.Context, store storage.Store, systemContext *types.SystemContext, imageID, containerName, containerID string) (*Builder, error) {
|
||||
if imageID == "" {
|
||||
return nil, errors.New("Internal error: imageID is empty in importBuilderDataFromImage")
|
||||
return nil, errors.New("internal error: imageID is empty in importBuilderDataFromImage")
|
||||
}
|
||||
|
||||
storeopts, err := storage.DefaultStoreOptions()
|
||||
|
|
|
@ -26,17 +26,18 @@ type TeeConfigFlags struct {
|
|||
// TeeConfigFlagBits are bits representing run-time expectations.
|
||||
type TeeConfigFlagBits int
|
||||
|
||||
//nolint:revive,staticcheck // Don't warn about bad naming.
|
||||
const (
|
||||
SEV_CONFIG_NO_DEBUG TeeConfigFlagBits = 0b00000001 //revive:disable-line:var-naming no debugging of guests
|
||||
SEV_CONFIG_NO_KEY_SHARING TeeConfigFlagBits = 0b00000010 //revive:disable-line:var-naming no sharing keys between guests
|
||||
SEV_CONFIG_ENCRYPTED_STATE TeeConfigFlagBits = 0b00000100 //revive:disable-line:var-naming requires SEV-ES
|
||||
SEV_CONFIG_NO_SEND TeeConfigFlagBits = 0b00001000 //revive:disable-line:var-naming no transferring the guest to another platform
|
||||
SEV_CONFIG_DOMAIN TeeConfigFlagBits = 0b00010000 //revive:disable-line:var-naming no transferring the guest out of the domain (?)
|
||||
SEV_CONFIG_SEV TeeConfigFlagBits = 0b00100000 //revive:disable-line:var-naming no transferring the guest to non-SEV platforms
|
||||
SNP_CONFIG_SMT TeeConfigFlagBits = 0b00000001 //revive:disable-line:var-naming SMT is enabled on the host machine
|
||||
SNP_CONFIG_MANDATORY TeeConfigFlagBits = 0b00000010 //revive:disable-line:var-naming reserved bit which should always be set
|
||||
SNP_CONFIG_MIGRATE_MA TeeConfigFlagBits = 0b00000100 //revive:disable-line:var-naming allowed to use a migration agent
|
||||
SNP_CONFIG_DEBUG TeeConfigFlagBits = 0b00001000 //revive:disable-line:var-naming allow debugging
|
||||
SEV_CONFIG_NO_DEBUG TeeConfigFlagBits = 0b00000001 // no debugging of guests
|
||||
SEV_CONFIG_NO_KEY_SHARING TeeConfigFlagBits = 0b00000010 // no sharing keys between guests
|
||||
SEV_CONFIG_ENCRYPTED_STATE TeeConfigFlagBits = 0b00000100 // requires SEV-ES
|
||||
SEV_CONFIG_NO_SEND TeeConfigFlagBits = 0b00001000 // no transferring the guest to another platform
|
||||
SEV_CONFIG_DOMAIN TeeConfigFlagBits = 0b00010000 // no transferring the guest out of the domain (?)
|
||||
SEV_CONFIG_SEV TeeConfigFlagBits = 0b00100000 // no transferring the guest to non-SEV platforms
|
||||
SNP_CONFIG_SMT TeeConfigFlagBits = 0b00000001 // SMT is enabled on the host machine
|
||||
SNP_CONFIG_MANDATORY TeeConfigFlagBits = 0b00000010 // reserved bit which should always be set
|
||||
SNP_CONFIG_MIGRATE_MA TeeConfigFlagBits = 0b00000100 // allowed to use a migration agent
|
||||
SNP_CONFIG_DEBUG TeeConfigFlagBits = 0b00001000 // allow debugging
|
||||
)
|
||||
|
||||
// TeeConfigFlagMinFW corresponds to a minimum version of the kernel+initrd
|
||||
|
|
|
@ -28,7 +28,8 @@ type SnpWorkloadData struct {
|
|||
Generation string `json:"gen"` // "milan" (naples=1, rome=2, milan=3, genoa/bergamo/siena=4, turin=5)
|
||||
}
|
||||
|
||||
//nolint:revive,staticcheck // Don't warn about bad naming.
|
||||
const (
|
||||
// SEV_NO_ES is a known trusted execution environment type: AMD-SEV (secure encrypted virtualization without encrypted state, requires epyc 1000 "naples")
|
||||
SEV_NO_ES define.TeeType = "sev_no_es" //revive:disable-line:var-naming
|
||||
SEV_NO_ES define.TeeType = "sev_no_es"
|
||||
)
|
||||
|
|
|
@ -28,18 +28,23 @@ type (
|
|||
const (
|
||||
maxWorkloadConfigSize = 1024 * 1024
|
||||
preferredPaddingBoundary = 4096
|
||||
// SEV is a known trusted execution environment type: AMD-SEV
|
||||
SEV = define.SEV
|
||||
// SEV_NO_ES is a known trusted execution environment type: AMD-SEV without encrypted state
|
||||
SEV_NO_ES = types.SEV_NO_ES //revive:disable-line:var-naming
|
||||
// SNP is a known trusted execution environment type: AMD-SNP
|
||||
SNP = define.SNP
|
||||
|
||||
// krun looks for its configuration JSON directly in a disk image if the last twelve bytes
|
||||
// of the disk image are this magic value followed by a little-endian 64-bit
|
||||
// length-of-the-configuration
|
||||
krunMagic = "KRUN"
|
||||
)
|
||||
|
||||
//nolint:revive,staticcheck
|
||||
const (
|
||||
// SEV is a known trusted execution environment type: AMD-SEV
|
||||
SEV = define.SEV
|
||||
// SEV_NO_ES is a known trusted execution environment type: AMD-SEV without encrypted state
|
||||
SEV_NO_ES = types.SEV_NO_ES
|
||||
// SNP is a known trusted execution environment type: AMD-SNP
|
||||
SNP = define.SNP
|
||||
)
|
||||
|
||||
// ReadWorkloadConfigFromImage reads the workload configuration from the
|
||||
// specified disk image file
|
||||
func ReadWorkloadConfigFromImage(path string) (WorkloadConfig, error) {
|
||||
|
|
|
@ -94,7 +94,7 @@ func (t StdoutTemplateArray) Out() error {
|
|||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
if strings.HasPrefix(t.Template, "table") {
|
||||
// replace any spaces with tabs in template so that tabwriter can align it
|
||||
t.Template = strings.Replace(strings.TrimSpace(t.Template[5:]), " ", "\t", -1)
|
||||
t.Template = strings.ReplaceAll(strings.TrimSpace(t.Template[5:]), " ", "\t")
|
||||
headerTmpl, err := template.New("header").Funcs(headerFunctions).Parse(t.Template)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %w", parsingErrorStr, err)
|
||||
|
@ -105,7 +105,7 @@ func (t StdoutTemplateArray) Out() error {
|
|||
}
|
||||
fmt.Fprintln(w, "")
|
||||
}
|
||||
t.Template = strings.Replace(t.Template, " ", "\t", -1)
|
||||
t.Template = strings.ReplaceAll(t.Template, " ", "\t")
|
||||
tmpl, err := template.New("image").Funcs(basicFunctions).Parse(t.Template)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %w", parsingErrorStr, err)
|
||||
|
|
|
@ -705,11 +705,12 @@ func GetBuildOutput(buildOutput string) (define.BuildOutputOption, error) {
|
|||
return define.BuildOutputOption{}, fmt.Errorf("duplicate %q not supported", arr[0])
|
||||
}
|
||||
typeSelected = true
|
||||
if arr[1] == "local" {
|
||||
switch arr[1] {
|
||||
case "local":
|
||||
isDir = true
|
||||
} else if arr[1] == "tar" {
|
||||
case "tar":
|
||||
isDir = false
|
||||
} else {
|
||||
default:
|
||||
return define.BuildOutputOption{}, fmt.Errorf("invalid type %q selected for build output options %q", arr[1], buildOutput)
|
||||
}
|
||||
case "dest":
|
||||
|
|
|
@ -22,8 +22,8 @@ func get() (Rusage, error) {
|
|||
Date: time.Now(),
|
||||
Utime: mkduration(rusage.Utime),
|
||||
Stime: mkduration(rusage.Stime),
|
||||
Inblock: int64(rusage.Inblock), // nolint: unconvert
|
||||
Outblock: int64(rusage.Oublock), // nolint: unconvert
|
||||
Inblock: int64(rusage.Inblock), //nolint:unconvert
|
||||
Outblock: int64(rusage.Oublock), //nolint:unconvert
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
|
|
@ -734,7 +734,7 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, moreCreateArgs [
|
|||
return wstatus, nil
|
||||
}
|
||||
|
||||
func runCollectOutput(logger *logrus.Logger, fds, closeBeforeReadingFds []int) string { //nolint:interfacer
|
||||
func runCollectOutput(logger *logrus.Logger, fds, closeBeforeReadingFds []int) string {
|
||||
for _, fd := range closeBeforeReadingFds {
|
||||
unix.Close(fd)
|
||||
}
|
||||
|
@ -780,7 +780,7 @@ func runCollectOutput(logger *logrus.Logger, fds, closeBeforeReadingFds []int) s
|
|||
return b.String()
|
||||
}
|
||||
|
||||
func setNonblock(logger *logrus.Logger, fd int, description string, nonblocking bool) (bool, error) { //nolint:interfacer
|
||||
func setNonblock(logger *logrus.Logger, fd int, description string, nonblocking bool) (bool, error) {
|
||||
mask, err := unix.FcntlInt(uintptr(fd), unix.F_GETFL, 0)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -870,13 +870,13 @@ func runCopyStdio(logger *logrus.Logger, stdio *sync.WaitGroup, copyPipes bool,
|
|||
return
|
||||
}
|
||||
if blocked {
|
||||
defer setNonblock(logger, rfd, readDesc[rfd], false) // nolint:errcheck
|
||||
defer setNonblock(logger, rfd, readDesc[rfd], false) //nolint:errcheck
|
||||
}
|
||||
setNonblock(logger, wfd, writeDesc[wfd], false) // nolint:errcheck
|
||||
setNonblock(logger, wfd, writeDesc[wfd], false) //nolint:errcheck
|
||||
}
|
||||
|
||||
if copyPipes {
|
||||
setNonblock(logger, stdioPipe[unix.Stdin][1], writeDesc[stdioPipe[unix.Stdin][1]], true) // nolint:errcheck
|
||||
setNonblock(logger, stdioPipe[unix.Stdin][1], writeDesc[stdioPipe[unix.Stdin][1]], true) //nolint:errcheck
|
||||
}
|
||||
|
||||
runCopyStdioPassData(copyPipes, stdioPipe, finishCopy, relayMap, relayBuffer, readDesc, writeDesc)
|
||||
|
|
22
run_linux.go
22
run_linux.go
|
@ -456,7 +456,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
}
|
||||
|
||||
resolvFile := ""
|
||||
if !slices.Contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") {
|
||||
if !slices.Contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && (len(b.CommonBuildOpts.DNSServers) != 1 || strings.ToLower(b.CommonBuildOpts.DNSServers[0]) != "none") {
|
||||
resolvFile, err = b.createResolvConf(path, rootIDPair)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -691,9 +691,9 @@ func setupSlirp4netnsNetwork(config *config.Config, netns, cid string, options,
|
|||
}
|
||||
|
||||
return func() {
|
||||
syscall.Kill(res.Pid, syscall.SIGKILL) // nolint:errcheck
|
||||
syscall.Kill(res.Pid, syscall.SIGKILL) //nolint:errcheck
|
||||
var status syscall.WaitStatus
|
||||
syscall.Wait4(res.Pid, &status, 0, nil) // nolint:errcheck
|
||||
syscall.Wait4(res.Pid, &status, 0, nil) //nolint:errcheck
|
||||
}, result, nil
|
||||
}
|
||||
|
||||
|
@ -1062,28 +1062,28 @@ func addRlimits(ulimit []string, g *generate.Generator, defaultUlimits []string)
|
|||
g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Hard), uint64(ul.Soft))
|
||||
}
|
||||
if !nofileSet {
|
||||
max := define.RLimitDefaultValue
|
||||
lim := define.RLimitDefaultValue
|
||||
var rlimit unix.Rlimit
|
||||
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err == nil {
|
||||
if max < rlimit.Max || unshare.IsRootless() {
|
||||
max = rlimit.Max
|
||||
if lim < rlimit.Max || unshare.IsRootless() {
|
||||
lim = rlimit.Max
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
|
||||
}
|
||||
g.AddProcessRlimits("RLIMIT_NOFILE", max, max)
|
||||
g.AddProcessRlimits("RLIMIT_NOFILE", lim, lim)
|
||||
}
|
||||
if !nprocSet {
|
||||
max := define.RLimitDefaultValue
|
||||
lim := define.RLimitDefaultValue
|
||||
var rlimit unix.Rlimit
|
||||
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err == nil {
|
||||
if max < rlimit.Max || unshare.IsRootless() {
|
||||
max = rlimit.Max
|
||||
if lim < rlimit.Max || unshare.IsRootless() {
|
||||
lim = rlimit.Max
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err)
|
||||
}
|
||||
g.AddProcessRlimits("RLIMIT_NPROC", max, max)
|
||||
g.AddProcessRlimits("RLIMIT_NPROC", lim, lim)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -35,7 +35,6 @@ import (
|
|||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
istorage "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/image/v5/types"
|
||||
|
@ -648,7 +647,7 @@ func buildUsingBuildah(ctx context.Context, t *testing.T, store storage.Store, t
|
|||
|
||||
// return a reference to the new image, if we succeeded
|
||||
if err == nil {
|
||||
buildahRef, err = istorage.Transport.ParseStoreReference(store, imageID)
|
||||
buildahRef, err = is.Transport.ParseStoreReference(store, imageID)
|
||||
assert.Nil(t, err, "error parsing reference to newly-built image with ID %q", imageID)
|
||||
}
|
||||
return buildahRef, []byte(outputString)
|
||||
|
@ -935,7 +934,7 @@ func fsHeaderForEntry(hdr *tar.Header) FSHeader {
|
|||
ModTime: hdr.ModTime,
|
||||
Devmajor: hdr.Devmajor,
|
||||
Devminor: hdr.Devminor,
|
||||
Xattrs: hdr.Xattrs, // nolint:staticcheck
|
||||
Xattrs: hdr.Xattrs, //nolint:staticcheck
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1358,7 +1357,7 @@ func configCompareResult(miss, left, diff []string, notDocker string) string {
|
|||
if len(diff) > 0 {
|
||||
buffer.WriteString("Fields present in both versions have different values:\n")
|
||||
tw := tabwriter.NewWriter(&buffer, 1, 1, 8, ' ', 0)
|
||||
if _, err := tw.Write([]byte(fmt.Sprintf("Field\tDocker\t%s\n", notDocker))); err != nil {
|
||||
if _, err := fmt.Fprintf(tw, "Field\tDocker\t%s\n", notDocker); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, d := range diff {
|
||||
|
@ -1390,7 +1389,7 @@ func fsCompareResult(miss, left, diff []string, notDocker string) string {
|
|||
if len(diff) > 0 {
|
||||
buffer.WriteString("File attributes in both versions have different values:\n")
|
||||
tw := tabwriter.NewWriter(&buffer, 1, 1, 8, ' ', 0)
|
||||
if _, err := tw.Write([]byte(fmt.Sprintf("File:attr\tDocker\t%s\n", notDocker))); err != nil {
|
||||
if _, err := fmt.Fprintf(tw, "File:attr\tDocker\t%s\n", notDocker); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, d := range fixup(diff) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
//go:build linux
|
||||
|
||||
package conformance
|
||||
|
||||
import (
|
|
@ -97,7 +97,7 @@ func main() {
|
|||
|
||||
errors := false
|
||||
defer func() {
|
||||
store.Shutdown(false) // nolint:errcheck
|
||||
store.Shutdown(false) //nolint:errcheck
|
||||
if errors {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -49,14 +48,10 @@ func main() {
|
|||
key = args[5]
|
||||
}
|
||||
if len(args) > 6 && args[6] != "" {
|
||||
f, err := os.Create(args[6])
|
||||
err := os.WriteFile(args[6], []byte(strconv.Itoa(os.Getpid())), 0o644)
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
if _, err := f.WriteString(fmt.Sprintf("%d", os.Getpid())); err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
http.HandleFunc("/", sendThatFile(basedir))
|
||||
server := http.Server{
|
||||
|
|
|
@ -325,7 +325,7 @@ func getLinuxSysctl(r *types.TestReport) error {
|
|||
return fmt.Errorf("reading sysctl %q: %w", path, err)
|
||||
}
|
||||
path = strings.TrimPrefix(path, "/proc/sys/")
|
||||
sysctl := strings.Replace(path, "/", ".", -1)
|
||||
sysctl := strings.ReplaceAll(path, "/", ".")
|
||||
val := strings.TrimRight(string(value), "\r\n")
|
||||
if strings.ContainsAny(val, "\r\n") {
|
||||
val = string(value)
|
||||
|
|
|
@ -33,5 +33,16 @@ $(BUILDDIR): \
|
|||
$(BUILDDIR)/go-md2man: $(SOURCES)
|
||||
$(GO_BUILD) -o $@ ./vendor/github.com/cpuguy83/go-md2man/v2
|
||||
|
||||
$(BUILDDIR)/golangci-lint: $(SOURCES)
|
||||
$(GO_BUILD) -o $@ ./vendor/github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
# Use GOLANGCI_LINT_VERSION exported in top-level Makefile,
|
||||
# or, if called directly, use "latest".
|
||||
$(BUILDDIR)/golangci-lint: VERSION=$(if $(GOLANGCI_LINT_VERSION),v$(GOLANGCI_LINT_VERSION),latest)
|
||||
$(BUILDDIR)/golangci-lint: check-lint-version
|
||||
@test -f $(BUILDDIR)/golangci-lint || \
|
||||
curl -fsSL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b ./$(BUILDDIR) $(VERSION)
|
||||
|
||||
.PHONY: check-lint-version
|
||||
check-lint-version: VERSION=$(GOLANGCI_LINT_VERSION)
|
||||
check-lint-version:
|
||||
@test -n "$(VERSION)" && \
|
||||
$(BUILDDIR)/golangci-lint version 2>/dev/null | grep -F $(VERSION) || \
|
||||
rm -f $(BUILDDIR)/golangci-lint
|
||||
|
|
|
@ -2,190 +2,6 @@ module github.com/containers/buildah/tests/tools
|
|||
|
||||
go 1.22.1
|
||||
|
||||
require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4
|
||||
github.com/golangci/golangci-lint v1.61.0
|
||||
)
|
||||
require github.com/cpuguy83/go-md2man/v2 v2.0.4
|
||||
|
||||
require (
|
||||
4d63.com/gocheckcompilerdirectives v1.2.1 // indirect
|
||||
4d63.com/gochecknoglobals v0.2.1 // indirect
|
||||
github.com/4meepo/tagalign v1.3.4 // indirect
|
||||
github.com/Abirdcfly/dupword v0.1.1 // indirect
|
||||
github.com/Antonboom/errname v0.1.13 // indirect
|
||||
github.com/Antonboom/nilnil v0.1.9 // indirect
|
||||
github.com/Antonboom/testifylint v1.4.3 // indirect
|
||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
|
||||
github.com/Crocmagnon/fatcontext v0.5.2 // indirect
|
||||
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
|
||||
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect
|
||||
github.com/alecthomas/go-check-sumtype v0.1.4 // indirect
|
||||
github.com/alexkohler/nakedret/v2 v2.0.4 // indirect
|
||||
github.com/alexkohler/prealloc v1.0.0 // indirect
|
||||
github.com/alingse/asasalint v0.0.11 // indirect
|
||||
github.com/ashanbrown/forbidigo v1.6.0 // indirect
|
||||
github.com/ashanbrown/makezero v1.1.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bkielbasa/cyclop v1.2.1 // indirect
|
||||
github.com/blizzy78/varnamelen v0.8.0 // indirect
|
||||
github.com/bombsimon/wsl/v4 v4.4.1 // indirect
|
||||
github.com/breml/bidichk v0.2.7 // indirect
|
||||
github.com/breml/errchkjson v0.3.6 // indirect
|
||||
github.com/butuzov/ireturn v0.3.0 // indirect
|
||||
github.com/butuzov/mirror v1.2.0 // indirect
|
||||
github.com/catenacyber/perfsprint v0.7.1 // indirect
|
||||
github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/charithe/durationcheck v0.0.10 // indirect
|
||||
github.com/chavacava/garif v0.1.0 // indirect
|
||||
github.com/ckaznocha/intrange v0.2.0 // indirect
|
||||
github.com/curioswitch/go-reassign v0.2.0 // indirect
|
||||
github.com/daixiang0/gci v0.13.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/denis-tingaikin/go-header v0.5.0 // indirect
|
||||
github.com/ettle/strcase v0.2.0 // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/fatih/structtag v1.2.0 // indirect
|
||||
github.com/firefart/nonamedreturns v1.0.5 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/fzipp/gocyclo v0.6.0 // indirect
|
||||
github.com/ghostiam/protogetter v0.3.6 // indirect
|
||||
github.com/go-critic/go-critic v0.11.4 // 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
|
||||
github.com/go-toolsmith/astfmt v1.1.0 // indirect
|
||||
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.1.0 // indirect
|
||||
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect
|
||||
github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 // indirect
|
||||
github.com/golangci/misspell v0.6.0 // indirect
|
||||
github.com/golangci/modinfo v0.3.4 // indirect
|
||||
github.com/golangci/plugin-module-register v0.1.1 // indirect
|
||||
github.com/golangci/revgrep v0.5.3 // indirect
|
||||
github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/gordonklaus/ineffassign v0.1.0 // indirect
|
||||
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
|
||||
github.com/gostaticanalysis/comment v1.4.2 // indirect
|
||||
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
|
||||
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jgautheron/goconst v1.7.1 // indirect
|
||||
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
|
||||
github.com/jjti/go-spancheck v0.6.2 // indirect
|
||||
github.com/julz/importas v0.1.0 // indirect
|
||||
github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect
|
||||
github.com/kisielk/errcheck v1.7.0 // indirect
|
||||
github.com/kkHAIKE/contextcheck v1.1.5 // indirect
|
||||
github.com/kulti/thelper v0.6.3 // indirect
|
||||
github.com/kunwardeep/paralleltest v1.0.10 // indirect
|
||||
github.com/kyoh86/exportloopref v0.1.11 // indirect
|
||||
github.com/lasiar/canonicalheader v1.1.1 // indirect
|
||||
github.com/ldez/gomoddirectives v0.2.4 // indirect
|
||||
github.com/ldez/tagliatelle v0.5.0 // indirect
|
||||
github.com/leonklingele/grouper v1.1.2 // indirect
|
||||
github.com/lufeee/execinquery v1.2.1 // indirect
|
||||
github.com/macabu/inamedparam v0.1.3 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/maratori/testableexamples v1.0.0 // indirect
|
||||
github.com/maratori/testpackage v1.1.1 // indirect
|
||||
github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mgechev/revive v1.3.9 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moricho/tparallel v0.3.2 // indirect
|
||||
github.com/nakabonne/nestif v0.3.1 // indirect
|
||||
github.com/nishanths/exhaustive v0.12.0 // indirect
|
||||
github.com/nishanths/predeclared v0.2.2 // indirect
|
||||
github.com/nunnatsa/ginkgolinter v0.16.2 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/polyfloyd/go-errorlint v1.6.0 // indirect
|
||||
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22 // 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
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/ryancurrah/gomodguard v1.3.5 // indirect
|
||||
github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
|
||||
github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
|
||||
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
|
||||
github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect
|
||||
github.com/securego/gosec/v2 v2.21.2 // indirect
|
||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sivchari/containedctx v1.0.3 // indirect
|
||||
github.com/sivchari/tenv v1.10.0 // indirect
|
||||
github.com/sonatard/noctx v0.0.2 // indirect
|
||||
github.com/sourcegraph/go-diff v0.7.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // 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.1.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/tdakkota/asciicheck v0.2.0 // indirect
|
||||
github.com/tetafro/godot v1.4.17 // indirect
|
||||
github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect
|
||||
github.com/timonwong/loggercheck v0.9.4 // indirect
|
||||
github.com/tomarrell/wrapcheck/v2 v2.9.0 // indirect
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
|
||||
github.com/ultraware/funlen v0.1.0 // indirect
|
||||
github.com/ultraware/whitespace v0.1.1 // indirect
|
||||
github.com/uudashr/gocognit v1.1.3 // indirect
|
||||
github.com/xen0n/gosmopolitan v1.2.2 // indirect
|
||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||
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.12.2 // indirect
|
||||
go-simpler.org/sloglint v0.7.2 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/automaxprocs v1.5.3 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // 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.5.1 // indirect
|
||||
mvdan.cc/gofumpt v0.7.0 // indirect
|
||||
mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect
|
||||
)
|
||||
require github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
|
|
|
@ -1,954 +1,4 @@
|
|||
4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA=
|
||||
4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs=
|
||||
4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc=
|
||||
4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/4meepo/tagalign v1.3.4 h1:P51VcvBnf04YkHzjfclN6BbsopfJR5rxs1n+5zHt+w8=
|
||||
github.com/4meepo/tagalign v1.3.4/go.mod h1:M+pnkHH2vG8+qhE5bVc/zeP7HS/j910Fwa9TUSyZVI0=
|
||||
github.com/Abirdcfly/dupword v0.1.1 h1:Bsxe0fIw6OwBtXMIncaTxCLHYO5BB+3mcsR5E8VXloY=
|
||||
github.com/Abirdcfly/dupword v0.1.1/go.mod h1:B49AcJdTYYkpd4HjgAcutNGG9HZ2JWwKunH9Y2BA6sM=
|
||||
github.com/Antonboom/errname v0.1.13 h1:JHICqsewj/fNckzrfVSe+T33svwQxmjC+1ntDsHOVvM=
|
||||
github.com/Antonboom/errname v0.1.13/go.mod h1:uWyefRYRN54lBg6HseYCFhs6Qjcy41Y3Jl/dVhA87Ns=
|
||||
github.com/Antonboom/nilnil v0.1.9 h1:eKFMejSxPSA9eLSensFmjW2XTgTwJMjZ8hUHtV4s/SQ=
|
||||
github.com/Antonboom/nilnil v0.1.9/go.mod h1:iGe2rYwCq5/Me1khrysB4nwI7swQvjclR8/YRPl5ihQ=
|
||||
github.com/Antonboom/testifylint v1.4.3 h1:ohMt6AHuHgttaQ1xb6SSnxCeK4/rnK7KKzbvs7DmEck=
|
||||
github.com/Antonboom/testifylint v1.4.3/go.mod h1:+8Q9+AOLsz5ZiQiiYujJKs9mNz398+M6UgslP4qgJLA=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
|
||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Crocmagnon/fatcontext v0.5.2 h1:vhSEg8Gqng8awhPju2w7MKHqMlg4/NI+gSDHtR3xgwA=
|
||||
github.com/Crocmagnon/fatcontext v0.5.2/go.mod h1:87XhRMaInHP44Q7Tlc7jkgKKB7kZAOPiDkFMdKCC+74=
|
||||
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.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU=
|
||||
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao=
|
||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA=
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ=
|
||||
github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk=
|
||||
github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
|
||||
github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c=
|
||||
github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
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/alexkohler/nakedret/v2 v2.0.4 h1:yZuKmjqGi0pSmjGpOC016LtPJysIL0WEUiaXW5SUnNg=
|
||||
github.com/alexkohler/nakedret/v2 v2.0.4/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU=
|
||||
github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw=
|
||||
github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE=
|
||||
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/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY=
|
||||
github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU=
|
||||
github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s=
|
||||
github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/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/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.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJY=
|
||||
github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM=
|
||||
github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M=
|
||||
github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k=
|
||||
github.com/bombsimon/wsl/v4 v4.4.1 h1:jfUaCkN+aUpobrMO24zwyAMwMAV5eSziCkOKEauOLdw=
|
||||
github.com/bombsimon/wsl/v4 v4.4.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo=
|
||||
github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY=
|
||||
github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ=
|
||||
github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA=
|
||||
github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U=
|
||||
github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0=
|
||||
github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA=
|
||||
github.com/butuzov/mirror v1.2.0 h1:9YVK1qIjNspaqWutSv8gsge2e/Xpq1eqEkslEUHy5cs=
|
||||
github.com/butuzov/mirror v1.2.0/go.mod h1:DqZZDtzm42wIAIyHXeN8W/qb1EPlb9Qn/if9icBOpdQ=
|
||||
github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc=
|
||||
github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50=
|
||||
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/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/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
|
||||
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/ckaznocha/intrange v0.2.0 h1:FykcZuJ8BD7oX93YbO1UY9oZtkRbp+1/kJcDjkefYLs=
|
||||
github.com/ckaznocha/intrange v0.2.0/go.mod h1:r5I7nUlAAG56xmkOpw4XVr16BXhwYTUdcuRFeevn1oE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo=
|
||||
github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc=
|
||||
github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c=
|
||||
github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8=
|
||||
github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q=
|
||||
github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
|
||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA=
|
||||
github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
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.6 h1:R7qEWaSgFCsy20yYHNIJsU9ZOb8TziSRRxuAOTVKeOk=
|
||||
github.com/ghostiam/protogetter v0.3.6/go.mod h1:7lpeDnEJ1ZjL/YtyoN99ljO4z0pd3H0d18/t2dPBxHw=
|
||||
github.com/go-critic/go-critic v0.11.4 h1:O7kGOCx0NDIni4czrkRIXTnit0mkyKOCePh3My6OyEU=
|
||||
github.com/go-critic/go-critic v0.11.4/go.mod h1:2QAdo4iuLik5S9YG0rT4wcZ8QxwHYkrr6/2MWAiv/vc=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8=
|
||||
github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU=
|
||||
github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s=
|
||||
github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw=
|
||||
github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4=
|
||||
github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ=
|
||||
github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw=
|
||||
github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY=
|
||||
github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco=
|
||||
github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4=
|
||||
github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA=
|
||||
github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA=
|
||||
github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk=
|
||||
github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus=
|
||||
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw=
|
||||
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.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w=
|
||||
github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U=
|
||||
github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
||||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
|
||||
github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME=
|
||||
github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9/go.mod h1:Oesb/0uFAyWoaw1U1qS5zyjCg5NP9C9iwjnI4tIsXEE=
|
||||
github.com/golangci/golangci-lint v1.61.0 h1:VvbOLaRVWmyxCnUIMTbf1kDsaJbTzH20FAMXTAlQGu8=
|
||||
github.com/golangci/golangci-lint v1.61.0/go.mod h1:e4lztIrJJgLPhWvFPDkhiMwEFRrWlmFbrZea3FsJyN8=
|
||||
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
|
||||
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
|
||||
github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA=
|
||||
github.com/golangci/modinfo v0.3.4/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM=
|
||||
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/revgrep v0.5.3 h1:3tL7c1XBMtWHHqVpS5ChmiAAoe4PF/d5+ULzV9sLAzs=
|
||||
github.com/golangci/revgrep v0.5.3/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k=
|
||||
github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs=
|
||||
github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
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.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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.5/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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA=
|
||||
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
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/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 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q=
|
||||
github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM=
|
||||
github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70=
|
||||
github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak=
|
||||
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/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
|
||||
github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY=
|
||||
github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU=
|
||||
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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
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/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
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.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk=
|
||||
github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
|
||||
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/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48=
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
|
||||
github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk=
|
||||
github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
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/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY=
|
||||
github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
|
||||
github.com/karamaru-alpha/copyloopvar v1.1.0 h1:x7gNyKcC2vRBO1H2Mks5u1VxQtYvFiym7fCjIP8RPos=
|
||||
github.com/karamaru-alpha/copyloopvar v1.1.0/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k=
|
||||
github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0=
|
||||
github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg=
|
||||
github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA=
|
||||
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.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
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.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs=
|
||||
github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY=
|
||||
github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ=
|
||||
github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA=
|
||||
github.com/lasiar/canonicalheader v1.1.1 h1:wC+dY9ZfiqiPwAexUApFush/csSPXeIi4QqyxXmng8I=
|
||||
github.com/lasiar/canonicalheader v1.1.1/go.mod h1:cXkb3Dlk6XXy+8MVQnF23CYKWlyA7kfQhSw2CcZtZb0=
|
||||
github.com/ldez/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg=
|
||||
github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g=
|
||||
github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo=
|
||||
github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4=
|
||||
github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY=
|
||||
github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA=
|
||||
github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM=
|
||||
github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM=
|
||||
github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk=
|
||||
github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
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/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE=
|
||||
github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
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-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 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A=
|
||||
github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU=
|
||||
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=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
|
||||
github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
|
||||
github.com/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/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U=
|
||||
github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE=
|
||||
github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg=
|
||||
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.16.2 h1:8iLqHIZvN4fTLDC0Ke9tbSZVcyVHoBs0HIbnVSxfHJk=
|
||||
github.com/nunnatsa/ginkgolinter v0.16.2/go.mod h1:4tWRinDN1FeJgU+iJANW/kz7xKN5nYRAOfJDQUS9dOQ=
|
||||
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/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
||||
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||
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=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/polyfloyd/go-errorlint v1.6.0 h1:tftWV9DE7txiFzPpztTAwyoRLKNj9gpVm2cg8/OwcYY=
|
||||
github.com/polyfloyd/go-errorlint v1.6.0/go.mod h1:HR7u8wuP1kb1NeN1zqTd1ZMlqUKPPHF+Id4vIPvDqVw=
|
||||
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 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.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
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.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo=
|
||||
github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI=
|
||||
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/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=
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
|
||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs=
|
||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU=
|
||||
github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE=
|
||||
github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
|
||||
github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
|
||||
github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc=
|
||||
github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
|
||||
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.27.0 h1:t/3jZpSXtRPRf2xr0m63i32ZrusyurIGT9E5wAvXQnI=
|
||||
github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8=
|
||||
github.com/securego/gosec/v2 v2.21.2 h1:deZp5zmYf3TWwU7A7cR2+SolbTpZ3HQiwFqnzQyEl3M=
|
||||
github.com/securego/gosec/v2 v2.21.2/go.mod h1:au33kg78rNseF5PwPnTWhuYBFf534bvJRvOrgZ/bFzU=
|
||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU=
|
||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/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.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/sivchari/tenv v1.10.0 h1:g/hzMA+dBCKqGXgW8AV/1xIWhAvDrx0zFKNR48NFMg0=
|
||||
github.com/sivchari/tenv v1.10.0/go.mod h1:tdY24masnVoZFxYrHv/nD6Tc8FbkEtAQEEziXpyMgqY=
|
||||
github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00=
|
||||
github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo=
|
||||
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.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
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.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/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.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc=
|
||||
github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/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=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
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/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM=
|
||||
github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg=
|
||||
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.4.17 h1:pGzu+Ye7ZUEFx7LHU0dAKmCOXWsPjl7qA6iMGndsjPs=
|
||||
github.com/tetafro/godot v1.4.17/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio=
|
||||
github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M=
|
||||
github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ=
|
||||
github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4=
|
||||
github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg=
|
||||
github.com/tomarrell/wrapcheck/v2 v2.9.0 h1:801U2YCAjLhdN8zhZ/7tdjB3EnAoRlJHt/s+9hijLQ4=
|
||||
github.com/tomarrell/wrapcheck/v2 v2.9.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo=
|
||||
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.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI=
|
||||
github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4=
|
||||
github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/Gk8VQ=
|
||||
github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8=
|
||||
github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM=
|
||||
github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U=
|
||||
github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU=
|
||||
github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg=
|
||||
github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM=
|
||||
github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk=
|
||||
github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs=
|
||||
github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4=
|
||||
github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw=
|
||||
github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
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.12.2 h1:J7lRc2ysXOq7eM8rwaTYnNrHd5JwjppzB6mScysB2Cs=
|
||||
go-simpler.org/musttag v0.12.2/go.mod h1:uN1DVIasMTQKk6XSik7yrJoEysGtR2GRqvWnI9S7TYM=
|
||||
go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY=
|
||||
go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
|
||||
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
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-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
|
||||
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
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.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
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.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
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.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
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.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.6.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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/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-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
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-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/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-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
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.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
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.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||
golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
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/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
|
||||
honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs=
|
||||
mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
|
||||
mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
|
||||
mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U=
|
||||
mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
package tools
|
||||
|
||||
|
@ -8,5 +7,4 @@ package tools
|
|||
|
||||
import (
|
||||
_ "github.com/cpuguy83/go-md2man/v2"
|
||||
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
|
||||
)
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Leigh McCulloch
|
||||
|
||||
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.
|
|
@ -1,105 +0,0 @@
|
|||
package checkcompilerdirectives
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func Analyzer() *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: "gocheckcompilerdirectives",
|
||||
Doc: "Checks that go compiler directive comments (//go:) are valid.",
|
||||
Run: run,
|
||||
}
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
for _, file := range pass.Files {
|
||||
for _, group := range file.Comments {
|
||||
for _, comment := range group.List {
|
||||
text := comment.Text
|
||||
if !strings.HasPrefix(text, "//") {
|
||||
continue
|
||||
}
|
||||
start := 2
|
||||
spaces := 0
|
||||
for _, c := range text[start:] {
|
||||
if c == ' ' {
|
||||
spaces++
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
start += spaces
|
||||
if !strings.HasPrefix(text[start:], "go:") {
|
||||
continue
|
||||
}
|
||||
start += 3
|
||||
end := strings.Index(text[start:], " ")
|
||||
if end == -1 {
|
||||
continue
|
||||
}
|
||||
directive := text[start : start+end]
|
||||
if len(directive) == 0 {
|
||||
continue
|
||||
}
|
||||
prefix := text[:start+end]
|
||||
// Leading whitespace will cause the go directive to be ignored
|
||||
// by the compiler with no error, causing it not to work. This
|
||||
// is an easy mistake.
|
||||
if spaces > 0 {
|
||||
pass.ReportRangef(comment, "compiler directive contains space: %s", prefix)
|
||||
}
|
||||
// If the directive is unknown it will be ignored by the
|
||||
// compiler with no error. This is an easy mistake to make,
|
||||
// especially if you typo a directive.
|
||||
if !isKnown(directive) {
|
||||
pass.ReportRangef(comment, "compiler directive unrecognized: %s", prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func isKnown(directive string) bool {
|
||||
for _, k := range known {
|
||||
if directive == k {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var known = []string{
|
||||
// Found by running the following command on the source of go.
|
||||
// git grep -o -E -h '//go:[a-z_]+' -- ':!**/*_test.go' ':!test/' ':!**/testdata/**' | sort -u
|
||||
"binary",
|
||||
"build",
|
||||
"buildsomethingelse",
|
||||
"cgo_dynamic_linker",
|
||||
"cgo_export_dynamic",
|
||||
"cgo_export_static",
|
||||
"cgo_import_dynamic",
|
||||
"cgo_import_static",
|
||||
"cgo_ldflag",
|
||||
"cgo_unsafe_args",
|
||||
"embed",
|
||||
"generate",
|
||||
"linkname",
|
||||
"name",
|
||||
"nocheckptr",
|
||||
"noescape",
|
||||
"noinline",
|
||||
"nointerface",
|
||||
"norace",
|
||||
"nosplit",
|
||||
"notinheap",
|
||||
"nowritebarrier",
|
||||
"nowritebarrierrec",
|
||||
"systemstack",
|
||||
"uintptrescapes",
|
||||
"uintptrkeepalive",
|
||||
"yeswritebarrierrec",
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 Leigh McCulloch
|
||||
|
||||
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.
|
200
tests/tools/vendor/4d63.com/gochecknoglobals/checknoglobals/check_no_globals.go
generated
vendored
200
tests/tools/vendor/4d63.com/gochecknoglobals/checknoglobals/check_no_globals.go
generated
vendored
|
@ -1,200 +0,0 @@
|
|||
package checknoglobals
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
// allowedExpression is a struct representing packages and methods that will
|
||||
// be an allowed combination to use as a global variable, f.ex. Name `regexp`
|
||||
// and SelName `MustCompile`.
|
||||
type allowedExpression struct {
|
||||
Name string
|
||||
SelName string
|
||||
}
|
||||
|
||||
const Doc = `check that no global variables exist
|
||||
|
||||
This analyzer checks for global variables and errors on any found.
|
||||
|
||||
A global variable is a variable declared in package scope and that can be read
|
||||
and written to by any function within the package. Global variables can cause
|
||||
side effects which are difficult to keep track of. A code in one function may
|
||||
change the variables state while another unrelated chunk of code may be
|
||||
effected by it.`
|
||||
|
||||
// Analyzer provides an Analyzer that checks that there are no global
|
||||
// variables, except for errors and variables containing regular
|
||||
// expressions.
|
||||
func Analyzer() *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: "gochecknoglobals",
|
||||
Doc: Doc,
|
||||
Run: checkNoGlobals,
|
||||
Flags: flags(),
|
||||
RunDespiteErrors: true,
|
||||
}
|
||||
}
|
||||
|
||||
func flags() flag.FlagSet {
|
||||
flags := flag.NewFlagSet("", flag.ExitOnError)
|
||||
flags.Bool("t", false, "Include tests")
|
||||
|
||||
return *flags
|
||||
}
|
||||
|
||||
func isAllowed(cm ast.CommentMap, v ast.Node, ti *types.Info) bool {
|
||||
switch i := v.(type) {
|
||||
case *ast.GenDecl:
|
||||
return hasEmbedComment(cm, i)
|
||||
case *ast.Ident:
|
||||
return i.Name == "_" || i.Name == "version" || isError(i, ti) || identHasEmbedComment(cm, i)
|
||||
case *ast.CallExpr:
|
||||
if expr, ok := i.Fun.(*ast.SelectorExpr); ok {
|
||||
return isAllowedSelectorExpression(expr)
|
||||
}
|
||||
case *ast.CompositeLit:
|
||||
if expr, ok := i.Type.(*ast.SelectorExpr); ok {
|
||||
return isAllowedSelectorExpression(expr)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isAllowedSelectorExpression(v *ast.SelectorExpr) bool {
|
||||
x, ok := v.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
allowList := []allowedExpression{
|
||||
{Name: "regexp", SelName: "MustCompile"},
|
||||
}
|
||||
|
||||
for _, i := range allowList {
|
||||
if x.Name == i.Name && v.Sel.Name == i.SelName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isError reports whether the AST identifier looks like
|
||||
// an error and implements the error interface.
|
||||
func isError(i *ast.Ident, ti *types.Info) bool {
|
||||
return looksLikeError(i) && implementsError(i, ti)
|
||||
}
|
||||
|
||||
// looksLikeError returns true if the AST identifier starts
|
||||
// with 'err' or 'Err', or false otherwise.
|
||||
func looksLikeError(i *ast.Ident) bool {
|
||||
prefix := "err"
|
||||
if i.IsExported() {
|
||||
prefix = "Err"
|
||||
}
|
||||
return strings.HasPrefix(i.Name, prefix)
|
||||
}
|
||||
|
||||
// implementsError reports whether the AST identifier
|
||||
// implements the error interface.
|
||||
func implementsError(i *ast.Ident, ti *types.Info) bool {
|
||||
t := ti.TypeOf(i)
|
||||
et := types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
|
||||
return types.Implements(t, et)
|
||||
}
|
||||
|
||||
func identHasEmbedComment(cm ast.CommentMap, i *ast.Ident) bool {
|
||||
if i.Obj == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
spec, ok := i.Obj.Decl.(*ast.ValueSpec)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasEmbedComment(cm, spec)
|
||||
}
|
||||
|
||||
// hasEmbedComment returns true if the AST node has
|
||||
// a '//go:embed ' comment, or false otherwise.
|
||||
func hasEmbedComment(cm ast.CommentMap, n ast.Node) bool {
|
||||
for _, g := range cm[n] {
|
||||
for _, c := range g.List {
|
||||
if strings.HasPrefix(c.Text, "//go:embed ") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func checkNoGlobals(pass *analysis.Pass) (interface{}, error) {
|
||||
includeTests := pass.Analyzer.Flags.Lookup("t").Value.(flag.Getter).Get().(bool)
|
||||
|
||||
for _, file := range pass.Files {
|
||||
filename := pass.Fset.Position(file.Pos()).Filename
|
||||
if !strings.HasSuffix(filename, ".go") {
|
||||
continue
|
||||
}
|
||||
if !includeTests && strings.HasSuffix(filename, "_test.go") {
|
||||
continue
|
||||
}
|
||||
|
||||
fileCommentMap := ast.NewCommentMap(pass.Fset, file, file.Comments)
|
||||
|
||||
for _, decl := range file.Decls {
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if genDecl.Tok != token.VAR {
|
||||
continue
|
||||
}
|
||||
if isAllowed(fileCommentMap, genDecl, pass.TypesInfo) {
|
||||
continue
|
||||
}
|
||||
for _, spec := range genDecl.Specs {
|
||||
valueSpec := spec.(*ast.ValueSpec)
|
||||
onlyAllowedValues := false
|
||||
|
||||
for _, vn := range valueSpec.Values {
|
||||
if isAllowed(fileCommentMap, vn, pass.TypesInfo) {
|
||||
onlyAllowedValues = true
|
||||
continue
|
||||
}
|
||||
|
||||
onlyAllowedValues = false
|
||||
break
|
||||
}
|
||||
|
||||
if onlyAllowedValues {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, vn := range valueSpec.Names {
|
||||
if isAllowed(fileCommentMap, vn, pass.TypesInfo) {
|
||||
continue
|
||||
}
|
||||
|
||||
message := fmt.Sprintf("%s is a global variable", vn.Name)
|
||||
pass.Report(analysis.Diagnostic{
|
||||
Pos: vn.Pos(),
|
||||
Category: "global",
|
||||
Message: message,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,go
|
||||
|
||||
### Go ###
|
||||
# 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
|
||||
|
||||
.vscode
|
||||
|
||||
# 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
|
||||
|
||||
### 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
|
||||
|
||||
### macOS Patch ###
|
||||
# iCloud generated files
|
||||
*.icloud
|
||||
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,go
|
||||
|
||||
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
|
@ -1,106 +0,0 @@
|
|||
# See https://golangci-lint.run/usage/configuration/
|
||||
|
||||
linters-settings:
|
||||
revive:
|
||||
# see https://github.com/mgechev/revive#available-rules for details.
|
||||
ignore-generated-header: true
|
||||
severity: warning
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: blank-imports
|
||||
- name: bool-literal-in-expr
|
||||
- name: call-to-gc
|
||||
- name: confusing-naming
|
||||
- name: confusing-results
|
||||
- name: constant-logical-expr
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: deep-exit
|
||||
- name: defer
|
||||
- name: dot-imports
|
||||
- name: duplicated-imports
|
||||
- name: early-return
|
||||
- name: empty-block
|
||||
- name: empty-lines
|
||||
- name: error-naming
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: errorf
|
||||
- name: exported
|
||||
- name: get-return
|
||||
- name: identical-branches
|
||||
- name: if-return
|
||||
- name: import-shadowing
|
||||
- name: increment-decrement
|
||||
- name: indent-error-flow
|
||||
- name: modifies-parameter
|
||||
- name: modifies-value-receiver
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: range-val-address
|
||||
- name: range-val-in-closure
|
||||
- name: receiver-naming
|
||||
- name: redefines-builtin-id
|
||||
- name: string-of-int
|
||||
- name: superfluous-else
|
||||
- name: time-naming
|
||||
- name: unconditional-recursion
|
||||
- name: unexported-naming
|
||||
- name: unexported-return
|
||||
- name: unnecessary-stmt
|
||||
- name: unreachable-code
|
||||
- name: unused-parameter
|
||||
- name: var-declaration
|
||||
- name: var-naming
|
||||
- name: waitgroup-by-value
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- dogsled
|
||||
- dupl
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- forcetypeassert
|
||||
- gochecknoinits
|
||||
- gocognit
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- godox
|
||||
- goimports
|
||||
- gomoddirectives
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
# - govet
|
||||
- importas
|
||||
- ineffassign
|
||||
- makezero
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilerr
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- predeclared
|
||||
- revive
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- thelper
|
||||
- tparallel
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- whitespace
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
project_name: tagalign
|
||||
|
||||
release:
|
||||
github:
|
||||
owner: 4meepo
|
||||
name: tagalign
|
||||
|
||||
builds:
|
||||
- binary: tagalign
|
||||
goos:
|
||||
- darwin
|
||||
- windows
|
||||
- linux
|
||||
- freebsd
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- arm
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
gomips:
|
||||
- hardfloat
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
main: ./cmd/tagalign/
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Yifei Liu
|
||||
|
||||
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.
|
|
@ -1,7 +0,0 @@
|
|||
.PHONY: lint
|
||||
lint:
|
||||
golangci-lint run ./...
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build -o tagalign cmd/tagalign/tagalign.go
|
|
@ -1,130 +0,0 @@
|
|||
# Go Tag Align
|
||||
|
||||

|
||||
[](https://codecov.io/github/4meepo/tagalign)
|
||||
[](https://pkg.go.dev/github.com/4meepo/tagalign)
|
||||
[](https://goreportcard.com/report/github.com/4meepo/tagalign)
|
||||
|
||||
TagAlign is used to align and sort tags in Go struct. It can make the struct more readable and easier to maintain.
|
||||
|
||||
For example, this struct
|
||||
|
||||
```go
|
||||
type FooBar struct {
|
||||
Foo int `json:"foo" validate:"required"`
|
||||
Bar string `json:"bar" validate:"required"`
|
||||
FooFoo int8 `json:"foo_foo" validate:"required"`
|
||||
BarBar int `json:"bar_bar" validate:"required"`
|
||||
FooBar struct {
|
||||
Foo int `json:"foo" yaml:"foo" validate:"required"`
|
||||
Bar222 string `json:"bar222" validate:"required" yaml:"bar"`
|
||||
} `json:"foo_bar" validate:"required"`
|
||||
BarFoo string `json:"bar_foo" validate:"required"`
|
||||
BarFooBar string `json:"bar_foo_bar" validate:"required"`
|
||||
}
|
||||
```
|
||||
|
||||
can be aligned to:
|
||||
|
||||
```go
|
||||
type FooBar struct {
|
||||
Foo int `json:"foo" validate:"required"`
|
||||
Bar string `json:"bar" validate:"required"`
|
||||
FooFoo int8 `json:"foo_foo" validate:"required"`
|
||||
BarBar int `json:"bar_bar" validate:"required"`
|
||||
FooBar struct {
|
||||
Foo int `json:"foo" yaml:"foo" validate:"required"`
|
||||
Bar222 string `json:"bar222" validate:"required" yaml:"bar"`
|
||||
} `json:"foo_bar" validate:"required"`
|
||||
BarFoo string `json:"bar_foo" validate:"required"`
|
||||
BarFooBar string `json:"bar_foo_bar" validate:"required"`
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
By default tagalign will only align tags, but not sort them. But alignment and [sort feature](https://github.com/4meepo/tagalign#sort-tag) can work together or separately.
|
||||
|
||||
* As a Golangci Linter (Recommended)
|
||||
|
||||
Tagalign is a built-in linter in [Golangci Lint](https://golangci-lint.run/usage/linters/#tagalign) since `v1.53`.
|
||||
> Note: In order to have the best experience, add the `--fix` flag to `golangci-lint` to enable the autofix feature.
|
||||
|
||||
* Standalone Mode
|
||||
|
||||
Install it using `GO` or download it [here](https://github.com/4meepo/tagalign/releases).
|
||||
|
||||
```bash
|
||||
go install github.com/4meepo/tagalign/cmd/tagalign@latest
|
||||
```
|
||||
|
||||
Run it in your terminal.
|
||||
|
||||
```bash
|
||||
# Only align tags.
|
||||
tagalign -fix {package path}
|
||||
# Only sort tags with fixed order.
|
||||
tagalign -fix -noalign -sort -order "json,xml" {package path}
|
||||
# Align and sort together.
|
||||
tagalign -fix -sort -order "json,xml" {package path}
|
||||
# Align and sort together in strict style.
|
||||
tagalign -fix -sort -order "json,xml" -strict {package path}
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Sort Tag
|
||||
|
||||
In addition to alignment, it can also sort tags with fixed order. If we enable sort with fixed order `json,xml`, the following code
|
||||
|
||||
```go
|
||||
type SortExample struct {
|
||||
Foo int `json:"foo,omitempty" yaml:"bar" xml:"baz" binding:"required" gorm:"column:foo" zip:"foo" validate:"required"`
|
||||
Bar int `validate:"required" yaml:"foo" xml:"bar" binding:"required" json:"bar,omitempty" gorm:"column:bar" zip:"bar" `
|
||||
FooBar int `gorm:"column:bar" validate:"required" xml:"bar" binding:"required" json:"bar,omitempty" zip:"bar" yaml:"foo"`
|
||||
}
|
||||
```
|
||||
|
||||
will be sorted and aligned to:
|
||||
|
||||
```go
|
||||
type SortExample struct {
|
||||
Foo int `json:"foo,omitempty" xml:"baz" binding:"required" gorm:"column:foo" validate:"required" yaml:"bar" zip:"foo"`
|
||||
Bar int `json:"bar,omitempty" xml:"bar" binding:"required" gorm:"column:bar" validate:"required" yaml:"foo" zip:"bar"`
|
||||
FooBar int `json:"bar,omitempty" xml:"bar" binding:"required" gorm:"column:bar" validate:"required" yaml:"foo" zip:"bar"`
|
||||
}
|
||||
```
|
||||
|
||||
The fixed order is `json,xml`, so the tags `json` and `xml` will be sorted and aligned first, and the rest tags will be sorted and aligned in the dictionary order.
|
||||
|
||||
### Strict Style
|
||||
|
||||
Sometimes, you may want to align your tags in strict style. In this style, the tags will be sorted and aligned in the dictionary order, and the tags with the same name will be aligned together. For example, the following code
|
||||
|
||||
```go
|
||||
type StrictStyleExample struct {
|
||||
Foo int ` xml:"baz" yaml:"bar" zip:"foo" binding:"required" gorm:"column:foo" validate:"required"`
|
||||
Bar int `validate:"required" gorm:"column:bar" yaml:"foo" xml:"bar" binding:"required" json:"bar,omitempty" `
|
||||
}
|
||||
```
|
||||
|
||||
will be aligned to
|
||||
|
||||
```go
|
||||
type StrictStyleExample struct {
|
||||
Foo int `binding:"required" gorm:"column:foo" validate:"required" xml:"baz" yaml:"bar" zip:"foo"`
|
||||
Bar int `binding:"required" gorm:"column:bar" json:"bar,omitempty" validate:"required" xml:"bar" yaml:"foo"`
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️Note: The strict style can't run without the align or sort feature enabled.
|
||||
|
||||
## References
|
||||
|
||||
[Golang AST Visualizer](http://goast.yuroyoro.net/)
|
||||
|
||||
[Create New Golang CI Linter](https://golangci-lint.run/contributing/new-linters/)
|
||||
|
||||
[Autofix Example](https://github.com/golangci/golangci-lint/pull/2450/files)
|
||||
|
||||
[Integrating](https://disaev.me/p/writing-useful-go-analysis-linter/#integrating)
|
|
@ -1,37 +0,0 @@
|
|||
package tagalign
|
||||
|
||||
type Option func(*Helper)
|
||||
|
||||
// WithMode specify the mode of tagalign.
|
||||
func WithMode(mode Mode) Option {
|
||||
return func(h *Helper) {
|
||||
h.mode = mode
|
||||
}
|
||||
}
|
||||
|
||||
// WithSort enable tags sort.
|
||||
// fixedOrder specify the order of tags, the other tags will be sorted by name.
|
||||
// Sory is disabled by default.
|
||||
func WithSort(fixedOrder ...string) Option {
|
||||
return func(h *Helper) {
|
||||
h.sort = true
|
||||
h.fixedTagOrder = fixedOrder
|
||||
}
|
||||
}
|
||||
|
||||
// WithAlign configure whether enable tags align.
|
||||
// Align is enabled by default.
|
||||
func WithAlign(enabled bool) Option {
|
||||
return func(h *Helper) {
|
||||
h.align = enabled
|
||||
}
|
||||
}
|
||||
|
||||
// WithStrictStyle configure whether enable strict style.
|
||||
// StrictStyle is disabled by default.
|
||||
// Note: StrictStyle must be used with WithAlign(true) and WithSort(...) together, or it will be ignored.
|
||||
func WithStrictStyle() Option {
|
||||
return func(h *Helper) {
|
||||
h.style = StrictStyle
|
||||
}
|
||||
}
|
|
@ -1,459 +0,0 @@
|
|||
package tagalign
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"log"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/structtag"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
StandaloneMode Mode = iota
|
||||
GolangciLintMode
|
||||
)
|
||||
|
||||
type Style int
|
||||
|
||||
const (
|
||||
DefaultStyle Style = iota
|
||||
StrictStyle
|
||||
)
|
||||
|
||||
const (
|
||||
errTagValueSyntax = "bad syntax for struct tag value"
|
||||
)
|
||||
|
||||
func NewAnalyzer(options ...Option) *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: "tagalign",
|
||||
Doc: "check that struct tags are well aligned",
|
||||
Run: func(p *analysis.Pass) (any, error) {
|
||||
Run(p, options...)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func Run(pass *analysis.Pass, options ...Option) []Issue {
|
||||
var issues []Issue
|
||||
for _, f := range pass.Files {
|
||||
h := &Helper{
|
||||
mode: StandaloneMode,
|
||||
style: DefaultStyle,
|
||||
align: true,
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(h)
|
||||
}
|
||||
|
||||
// StrictStyle must be used with WithAlign(true) and WithSort(...) together, or it will be ignored.
|
||||
if h.style == StrictStyle && (!h.align || !h.sort) {
|
||||
h.style = DefaultStyle
|
||||
}
|
||||
|
||||
if !h.align && !h.sort {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
h.find(pass, n)
|
||||
return true
|
||||
})
|
||||
h.Process(pass)
|
||||
issues = append(issues, h.issues...)
|
||||
}
|
||||
return issues
|
||||
}
|
||||
|
||||
type Helper struct {
|
||||
mode Mode
|
||||
|
||||
style Style
|
||||
|
||||
align bool // whether enable tags align.
|
||||
sort bool // whether enable tags sort.
|
||||
fixedTagOrder []string // the order of tags, the other tags will be sorted by name.
|
||||
|
||||
singleFields []*ast.Field
|
||||
consecutiveFieldsGroups [][]*ast.Field // fields in this group, must be consecutive in struct.
|
||||
issues []Issue
|
||||
}
|
||||
|
||||
// Issue is used to integrate with golangci-lint's inline auto fix.
|
||||
type Issue struct {
|
||||
Pos token.Position
|
||||
Message string
|
||||
InlineFix InlineFix
|
||||
}
|
||||
type InlineFix struct {
|
||||
StartCol int // zero-based
|
||||
Length int
|
||||
NewString string
|
||||
}
|
||||
|
||||
func (w *Helper) find(pass *analysis.Pass, n ast.Node) {
|
||||
v, ok := n.(*ast.StructType)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
fields := v.Fields.List
|
||||
if len(fields) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
fs := make([]*ast.Field, 0)
|
||||
split := func() {
|
||||
n := len(fs)
|
||||
if n > 1 {
|
||||
w.consecutiveFieldsGroups = append(w.consecutiveFieldsGroups, fs)
|
||||
} else if n == 1 {
|
||||
w.singleFields = append(w.singleFields, fs[0])
|
||||
}
|
||||
|
||||
fs = nil
|
||||
}
|
||||
|
||||
for i, field := range fields {
|
||||
if field.Tag == nil {
|
||||
// field without tags
|
||||
split()
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
if fields[i-1].Tag == nil {
|
||||
// if previous filed do not have a tag
|
||||
fs = append(fs, field)
|
||||
continue
|
||||
}
|
||||
preLineNum := pass.Fset.Position(fields[i-1].Tag.Pos()).Line
|
||||
lineNum := pass.Fset.Position(field.Tag.Pos()).Line
|
||||
if lineNum-preLineNum > 1 {
|
||||
// fields with tags are not consecutive, including two case:
|
||||
// 1. splited by lines
|
||||
// 2. splited by a struct
|
||||
split()
|
||||
|
||||
// check if the field is a struct
|
||||
if _, ok := field.Type.(*ast.StructType); ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs = append(fs, field)
|
||||
}
|
||||
|
||||
split()
|
||||
}
|
||||
|
||||
func (w *Helper) report(pass *analysis.Pass, field *ast.Field, startCol int, msg, replaceStr string) {
|
||||
if w.mode == GolangciLintMode {
|
||||
iss := Issue{
|
||||
Pos: pass.Fset.Position(field.Tag.Pos()),
|
||||
Message: msg,
|
||||
InlineFix: InlineFix{
|
||||
StartCol: startCol,
|
||||
Length: len(field.Tag.Value),
|
||||
NewString: replaceStr,
|
||||
},
|
||||
}
|
||||
w.issues = append(w.issues, iss)
|
||||
}
|
||||
|
||||
if w.mode == StandaloneMode {
|
||||
pass.Report(analysis.Diagnostic{
|
||||
Pos: field.Tag.Pos(),
|
||||
End: field.Tag.End(),
|
||||
Message: msg,
|
||||
SuggestedFixes: []analysis.SuggestedFix{
|
||||
{
|
||||
Message: msg,
|
||||
TextEdits: []analysis.TextEdit{
|
||||
{
|
||||
Pos: field.Tag.Pos(),
|
||||
End: field.Tag.End(),
|
||||
NewText: []byte(replaceStr),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit
|
||||
// process grouped fields
|
||||
for _, fields := range w.consecutiveFieldsGroups {
|
||||
offsets := make([]int, len(fields))
|
||||
|
||||
var maxTagNum int
|
||||
var tagsGroup, notSortedTagsGroup [][]*structtag.Tag
|
||||
|
||||
var uniqueKeys []string
|
||||
addKey := func(k string) {
|
||||
for _, key := range uniqueKeys {
|
||||
if key == k {
|
||||
return
|
||||
}
|
||||
}
|
||||
uniqueKeys = append(uniqueKeys, k)
|
||||
}
|
||||
|
||||
for i := 0; i < len(fields); {
|
||||
field := fields[i]
|
||||
column := pass.Fset.Position(field.Tag.Pos()).Column - 1
|
||||
offsets[i] = column
|
||||
|
||||
tag, err := strconv.Unquote(field.Tag.Value)
|
||||
if err != nil {
|
||||
// if tag value is not a valid string, report it directly
|
||||
w.report(pass, field, column, errTagValueSyntax, field.Tag.Value)
|
||||
fields = removeField(fields, i)
|
||||
continue
|
||||
}
|
||||
|
||||
tags, err := structtag.Parse(tag)
|
||||
if err != nil {
|
||||
// if tag value is not a valid struct tag, report it directly
|
||||
w.report(pass, field, column, err.Error(), field.Tag.Value)
|
||||
fields = removeField(fields, i)
|
||||
continue
|
||||
}
|
||||
|
||||
maxTagNum = max(maxTagNum, tags.Len())
|
||||
|
||||
if w.sort {
|
||||
cp := make([]*structtag.Tag, tags.Len())
|
||||
for i, tag := range tags.Tags() {
|
||||
cp[i] = tag
|
||||
}
|
||||
notSortedTagsGroup = append(notSortedTagsGroup, cp)
|
||||
sortBy(w.fixedTagOrder, tags)
|
||||
}
|
||||
for _, t := range tags.Tags() {
|
||||
addKey(t.Key)
|
||||
}
|
||||
tagsGroup = append(tagsGroup, tags.Tags())
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
if w.sort && StrictStyle == w.style {
|
||||
sortAllKeys(w.fixedTagOrder, uniqueKeys)
|
||||
maxTagNum = len(uniqueKeys)
|
||||
}
|
||||
|
||||
// record the max length of each column tag
|
||||
type tagLen struct {
|
||||
Key string // present only when sort enabled
|
||||
Len int
|
||||
}
|
||||
tagMaxLens := make([]tagLen, maxTagNum)
|
||||
for j := 0; j < maxTagNum; j++ {
|
||||
var maxLength int
|
||||
var key string
|
||||
for i := 0; i < len(tagsGroup); i++ {
|
||||
if w.style == StrictStyle {
|
||||
key = uniqueKeys[j]
|
||||
// search by key
|
||||
for _, tag := range tagsGroup[i] {
|
||||
if tag.Key == key {
|
||||
maxLength = max(maxLength, len(tag.String()))
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(tagsGroup[i]) <= j {
|
||||
// in case of index out of range
|
||||
continue
|
||||
}
|
||||
maxLength = max(maxLength, len(tagsGroup[i][j].String()))
|
||||
}
|
||||
}
|
||||
tagMaxLens[j] = tagLen{key, maxLength}
|
||||
}
|
||||
|
||||
for i, field := range fields {
|
||||
tags := tagsGroup[i]
|
||||
|
||||
var newTagStr string
|
||||
if w.align {
|
||||
// if align enabled, align tags.
|
||||
newTagBuilder := strings.Builder{}
|
||||
for i, n := 0, 0; i < len(tags) && n < len(tagMaxLens); {
|
||||
tag := tags[i]
|
||||
var format string
|
||||
if w.style == StrictStyle {
|
||||
if tagMaxLens[n].Key == tag.Key {
|
||||
// match
|
||||
format = alignFormat(tagMaxLens[n].Len + 1) // with an extra space
|
||||
newTagBuilder.WriteString(fmt.Sprintf(format, tag.String()))
|
||||
i++
|
||||
n++
|
||||
} else {
|
||||
// tag missing
|
||||
format = alignFormat(tagMaxLens[n].Len + 1)
|
||||
newTagBuilder.WriteString(fmt.Sprintf(format, ""))
|
||||
n++
|
||||
}
|
||||
} else {
|
||||
format = alignFormat(tagMaxLens[n].Len + 1) // with an extra space
|
||||
newTagBuilder.WriteString(fmt.Sprintf(format, tag.String()))
|
||||
i++
|
||||
n++
|
||||
}
|
||||
}
|
||||
newTagStr = newTagBuilder.String()
|
||||
} else {
|
||||
// otherwise check if tags order changed
|
||||
if w.sort && reflect.DeepEqual(notSortedTagsGroup[i], tags) {
|
||||
// if tags order not changed, do nothing
|
||||
continue
|
||||
}
|
||||
tagsStr := make([]string, len(tags))
|
||||
for i, tag := range tags {
|
||||
tagsStr[i] = tag.String()
|
||||
}
|
||||
newTagStr = strings.Join(tagsStr, " ")
|
||||
}
|
||||
|
||||
unquoteTag := strings.TrimRight(newTagStr, " ")
|
||||
// unquoteTag := newTagStr
|
||||
newTagValue := fmt.Sprintf("`%s`", unquoteTag)
|
||||
if field.Tag.Value == newTagValue {
|
||||
// nothing changed
|
||||
continue
|
||||
}
|
||||
|
||||
msg := "tag is not aligned, should be: " + unquoteTag
|
||||
|
||||
w.report(pass, field, offsets[i], msg, newTagValue)
|
||||
}
|
||||
}
|
||||
|
||||
// process single fields
|
||||
for _, field := range w.singleFields {
|
||||
column := pass.Fset.Position(field.Tag.Pos()).Column - 1
|
||||
tag, err := strconv.Unquote(field.Tag.Value)
|
||||
if err != nil {
|
||||
w.report(pass, field, column, errTagValueSyntax, field.Tag.Value)
|
||||
continue
|
||||
}
|
||||
|
||||
tags, err := structtag.Parse(tag)
|
||||
if err != nil {
|
||||
w.report(pass, field, column, err.Error(), field.Tag.Value)
|
||||
continue
|
||||
}
|
||||
originalTags := append([]*structtag.Tag(nil), tags.Tags()...)
|
||||
if w.sort {
|
||||
sortBy(w.fixedTagOrder, tags)
|
||||
}
|
||||
|
||||
newTagValue := fmt.Sprintf("`%s`", tags.String())
|
||||
if reflect.DeepEqual(originalTags, tags.Tags()) && field.Tag.Value == newTagValue {
|
||||
// if tags order not changed, do nothing
|
||||
continue
|
||||
}
|
||||
|
||||
msg := "tag is not aligned , should be: " + tags.String()
|
||||
|
||||
w.report(pass, field, column, msg, newTagValue)
|
||||
}
|
||||
}
|
||||
|
||||
// Issues returns all issues found by the analyzer.
|
||||
// It is used to integrate with golangci-lint.
|
||||
func (w *Helper) Issues() []Issue {
|
||||
log.Println("tagalign 's Issues() should only be called in golangci-lint mode")
|
||||
return w.issues
|
||||
}
|
||||
|
||||
// sortBy sorts tags by fixed order.
|
||||
// If a tag is not in the fixed order, it will be sorted by name.
|
||||
func sortBy(fixedOrder []string, tags *structtag.Tags) {
|
||||
// sort by fixed order
|
||||
sort.Slice(tags.Tags(), func(i, j int) bool {
|
||||
ti := tags.Tags()[i]
|
||||
tj := tags.Tags()[j]
|
||||
|
||||
oi := findIndex(fixedOrder, ti.Key)
|
||||
oj := findIndex(fixedOrder, tj.Key)
|
||||
|
||||
if oi == -1 && oj == -1 {
|
||||
return ti.Key < tj.Key
|
||||
}
|
||||
|
||||
if oi == -1 {
|
||||
return false
|
||||
}
|
||||
|
||||
if oj == -1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return oi < oj
|
||||
})
|
||||
}
|
||||
|
||||
func sortAllKeys(fixedOrder []string, keys []string) {
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
oi := findIndex(fixedOrder, keys[i])
|
||||
oj := findIndex(fixedOrder, keys[j])
|
||||
|
||||
if oi == -1 && oj == -1 {
|
||||
return keys[i] < keys[j]
|
||||
}
|
||||
|
||||
if oi == -1 {
|
||||
return false
|
||||
}
|
||||
|
||||
if oj == -1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return oi < oj
|
||||
})
|
||||
}
|
||||
|
||||
func findIndex(s []string, e string) int {
|
||||
for i, a := range s {
|
||||
if a == e {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func alignFormat(length int) string {
|
||||
return "%" + fmt.Sprintf("-%ds", length)
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func removeField(fields []*ast.Field, index int) []*ast.Field {
|
||||
if index < 0 || index >= len(fields) {
|
||||
return fields
|
||||
}
|
||||
|
||||
return append(fields[:index], fields[index+1:]...)
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
|
||||
# Godot-specific ignores
|
||||
.import/
|
||||
export.cfg
|
||||
export_presets.cfg
|
||||
|
||||
# Mono-specific ignores
|
||||
.mono/
|
||||
data_*/
|
||||
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
.idea/artifacts
|
||||
.idea/compiler.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/modules.xml
|
||||
.idea/*.iml
|
||||
.idea/modules
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Emacs template
|
||||
# -*- mode: gitignore; -*-
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
|
||||
# Org-mode
|
||||
.org-id-locations
|
||||
*_archive
|
||||
|
||||
# flymake-mode
|
||||
*_flymake.*
|
||||
|
||||
# eshell files
|
||||
/eshell/history
|
||||
/eshell/lastdir
|
||||
|
||||
# elpa packages
|
||||
/elpa/
|
||||
|
||||
# reftex files
|
||||
*.rel
|
||||
|
||||
# AUCTeX auto folder
|
||||
/auto/
|
||||
|
||||
# cask packages
|
||||
.cask/
|
||||
dist/
|
||||
|
||||
# Flycheck
|
||||
flycheck_*.el
|
||||
|
||||
# server auth directory
|
||||
/server/
|
||||
|
||||
# projectiles files
|
||||
.projectile
|
||||
|
||||
# directory configuration
|
||||
.dir-locals.el
|
||||
|
||||
# network security
|
||||
/network-security.data
|
||||
|
||||
|
||||
### Vim template
|
||||
# Swap
|
||||
[._]*.s[a-v][a-z]
|
||||
!*.svg # comment out if you don't need vector files
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
# Session
|
||||
Session.vim
|
||||
Sessionx.vim
|
||||
|
||||
# Temporary
|
||||
.netrwhist
|
||||
*~
|
||||
# Auto-generated tag files
|
||||
tags
|
||||
# Persistent undo
|
||||
[._]*.un~
|
||||
|
||||
### macOS template
|
||||
# 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
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
---
|
||||
project_name: dupword
|
||||
|
||||
release:
|
||||
github:
|
||||
owner: Abirdcfly
|
||||
name: dupword
|
||||
|
||||
builds:
|
||||
- binary: dupword
|
||||
goos:
|
||||
- darwin
|
||||
- windows
|
||||
- linux
|
||||
- freebsd
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- arm
|
||||
- 386
|
||||
- ppc64le
|
||||
- s390x
|
||||
- mips64
|
||||
- mips64le
|
||||
- riscv64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
gomips:
|
||||
- hardfloat
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
main: ./cmd/dupword/
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{.Date}}
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
wrap_in_directory: true
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
|
||||
files:
|
||||
- LICENSE
|
||||
- README.md
|
||||
|
||||
snapshot:
|
||||
name_template: SNAPSHOT-{{ .Commit }}
|
||||
|
||||
checksum:
|
||||
name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt'
|
||||
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '(?i)^docs?:'
|
||||
- '(?i)^docs\([^:]+\):'
|
||||
- '(?i)^docs\[[^:]+\]:'
|
||||
- '^tests?:'
|
||||
- '(?i)^dev:'
|
||||
- '^build\(deps\): bump .* in /docs \(#\d+\)'
|
||||
- '^build\(deps\): bump .* in /\.github/peril \(#\d+\)'
|
||||
- Merge pull request
|
||||
- Merge branch
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Abirdcfly
|
||||
|
||||
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.
|
|
@ -1,153 +0,0 @@
|
|||
# dupword
|
||||
|
||||

|
||||
[](https://pkg.go.dev/github.com/Abirdcfly/dupword)
|
||||
[](https://github.com/Abirdcfly/dupword/actions)
|
||||
[](https://goreportcard.com/report/github.com/Abirdcfly/dupword)
|
||||
|
||||
A linter that checks for duplicate words in the source code (usually miswritten)
|
||||
|
||||
Examples in real code and related issues can be viewed in [dupword#3](https://github.com/Abirdcfly/dupword/issues/3)
|
||||
|
||||
## example
|
||||
|
||||
1. Repeated words appear on two adjacent lines [commit](https://github.com/golang/go/commit/d8f90ce0f8119bf593efb6fb91825de5b61fcda7)
|
||||
|
||||
```diff
|
||||
--- a/src/cmd/compile/internal/ssa/schedule.go
|
||||
+++ b/src/cmd/compile/internal/ssa/schedule.go
|
||||
@@ -179,7 +179,7 @@ func schedule(f *Func) {
|
||||
// scored CarryChainTail (and prove w is not a tail).
|
||||
score[w.ID] = ScoreFlags
|
||||
}
|
||||
- // Verify v has not been scored. If v has not been visited, v may be the
|
||||
+ // Verify v has not been scored. If v has not been visited, v may be
|
||||
// the final (tail) operation in a carry chain. If v is not, v will be
|
||||
// rescored above when v's carry-using op is scored. When scoring is done,
|
||||
// only tail operations will retain the CarryChainTail score.
|
||||
```
|
||||
|
||||
2. Repeated words appearing on the same line [commit](https://github.com/golang/go/commit/48da729e8468b630ee003ac51cbaac595d53bec8)
|
||||
|
||||
```diff
|
||||
--- a/src/net/http/cookiejar/jar.go
|
||||
+++ b/src/net/http/cookiejar/jar.go
|
||||
@@ -465,7 +465,7 @@ func (j *Jar) domainAndType(host, domain string) (string, bool, error) {
|
||||
// dot in the domain-attribute before processing the cookie.
|
||||
//
|
||||
// Most browsers don't do that for IP addresses, only curl
|
||||
- // version 7.54) and and IE (version 11) do not reject a
|
||||
+ // version 7.54) and IE (version 11) do not reject a
|
||||
// Set-Cookie: a=1; domain=.127.0.0.1
|
||||
// This leading dot is optional and serves only as hint for
|
||||
// humans to indicate that a cookie with "domain=.bbc.co.uk"
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
go install github.com/Abirdcfly/dupword/cmd/dupword@latest
|
||||
```
|
||||
|
||||
**Or** install the main branch (including the last commit) with:
|
||||
|
||||
```bash
|
||||
go install github.com/Abirdcfly/dupword/cmd/dupword@main
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### 1. default
|
||||
|
||||
Run with default settings(include test file):
|
||||
|
||||
**But note that not all repeated words are wrong** see [dupword#4](https://github.com/Abirdcfly/dupword/issues/4) for real code example.
|
||||
|
||||
```bash
|
||||
$ dupword ./...
|
||||
/Users/xxx/go/src/dupword/dupword_test.go:88:10: Duplicate words (the) found
|
||||
exit status 3
|
||||
```
|
||||
|
||||
### 2. skip test file
|
||||
|
||||
Skip detection test file(`*_test.go`):
|
||||
|
||||
```bash
|
||||
$ dupword -test=false ./...
|
||||
```
|
||||
|
||||
### 3. auto-fix
|
||||
|
||||
```bash
|
||||
$ dupword -fix ./...
|
||||
```
|
||||
|
||||
### 4. all options
|
||||
|
||||
All options:
|
||||
|
||||
```bash
|
||||
$ dupword --help
|
||||
dupword: checks for duplicate words in the source code (usually miswritten)
|
||||
|
||||
Usage: dupword [-flag] [package]
|
||||
|
||||
This analyzer checks miswritten duplicate words in comments or package doc or string declaration
|
||||
|
||||
Flags:
|
||||
-V print version and exit
|
||||
-all
|
||||
no effect (deprecated)
|
||||
-c int
|
||||
display offending line with this many lines of context (default -1)
|
||||
-cpuprofile string
|
||||
write CPU profile to this file
|
||||
-debug string
|
||||
debug flags, any subset of "fpstv"
|
||||
-fix
|
||||
apply all suggested fixes
|
||||
-flags
|
||||
print analyzer flags in JSON
|
||||
-ignore value
|
||||
ignore words
|
||||
-json
|
||||
emit JSON output
|
||||
-keyword value
|
||||
keywords for detecting duplicate words
|
||||
-memprofile string
|
||||
write memory profile to this file
|
||||
-source
|
||||
no effect (deprecated)
|
||||
-tags string
|
||||
no effect (deprecated)
|
||||
-test
|
||||
indicates whether test files should be analyzed, too (default true)
|
||||
-trace string
|
||||
write trace log to this file
|
||||
-v no effect (deprecated)
|
||||
```
|
||||
|
||||
### 5. my advice
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
$ dupword --keyword=the,and,a -fix ./...
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
- [x] add this linter to golangci-lint
|
||||
- [ ] rewrite the detection logic to make it more efficient
|
||||
|
||||
## Limitation
|
||||
|
||||
1. Only for `*.go` file.But some miswritten occurs in `*.md` or `*.json` file.(example: kubernetes), In this case, my advice is to use [rg](https://github.com/BurntSushi/ripgrep) to do the lookup and replace manually.
|
||||
2. When use `-fix`, also running `go fmt` in the dark.([This logic is determined upstream](https://github.com/golang/tools/blob/248c34b88a4148128f89e41923498bd86f805b7d/go/analysis/internal/checker/checker.go#L424-L433), the project does not have this part of the code.)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
|
@ -1,343 +0,0 @@
|
|||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Abirdcfly
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package dupword defines an Analyzer that checks that duplicate words
|
||||
// int the source code.
|
||||
package dupword
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
const (
|
||||
Name = "dupword"
|
||||
Doc = `checks for duplicate words in the source code (usually miswritten)
|
||||
|
||||
This analyzer checks miswritten duplicate words in comments or package doc or string declaration`
|
||||
Message = "Duplicate words (%s) found"
|
||||
CommentPrefix = `//`
|
||||
)
|
||||
|
||||
var (
|
||||
defaultWord = []string{}
|
||||
// defaultWord = []string{"the", "and", "a"}
|
||||
ignoreWord = map[string]bool{}
|
||||
)
|
||||
|
||||
type analyzer struct {
|
||||
KeyWord []string
|
||||
}
|
||||
|
||||
func (a *analyzer) String() string {
|
||||
return strings.Join(a.KeyWord, ",")
|
||||
}
|
||||
|
||||
func (a *analyzer) Set(w string) error {
|
||||
if len(w) != 0 {
|
||||
a.KeyWord = make([]string, 0)
|
||||
a.KeyWord = append(a.KeyWord, strings.Split(w, ",")...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ignore struct {
|
||||
}
|
||||
|
||||
func (a *ignore) String() string {
|
||||
t := make([]string, 0, len(ignoreWord))
|
||||
for k := range ignoreWord {
|
||||
t = append(t, k)
|
||||
}
|
||||
return strings.Join(t, ",")
|
||||
}
|
||||
|
||||
func (a *ignore) Set(w string) error {
|
||||
for _, k := range strings.Split(w, ",") {
|
||||
ignoreWord[k] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// for test only
|
||||
func ClearIgnoreWord() {
|
||||
ignoreWord = map[string]bool{}
|
||||
}
|
||||
|
||||
func NewAnalyzer() *analysis.Analyzer {
|
||||
ignore := &ignore{}
|
||||
analyzer := &analyzer{KeyWord: defaultWord}
|
||||
a := &analysis.Analyzer{
|
||||
Name: Name,
|
||||
Doc: Doc,
|
||||
Requires: []*analysis.Analyzer{inspect.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(version{}, "V", "print version and exit")
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *analyzer) run(pass *analysis.Pass) (interface{}, error) {
|
||||
for _, file := range pass.Files {
|
||||
a.fixDuplicateWordInComment(pass, file)
|
||||
}
|
||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
nodeFilter := []ast.Node{
|
||||
(*ast.BasicLit)(nil),
|
||||
}
|
||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
||||
if lit, ok := n.(*ast.BasicLit); ok {
|
||||
a.fixDuplicateWordInString(pass, lit)
|
||||
}
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (a *analyzer) fixDuplicateWordInComment(pass *analysis.Pass, f *ast.File) {
|
||||
isTestFile := strings.HasSuffix(pass.Fset.File(f.FileStart).Name(), "_test.go")
|
||||
for _, cg := range f.Comments {
|
||||
// avoid checking example outputs for duplicate words
|
||||
if isTestFile && isExampleOutputStart(cg.List[0].Text) {
|
||||
continue
|
||||
}
|
||||
var preLine *ast.Comment
|
||||
for _, c := range cg.List {
|
||||
update, keyword, find := a.Check(c.Text)
|
||||
if find {
|
||||
pass.Report(analysis.Diagnostic{Pos: c.Slash, End: c.End(), Message: fmt.Sprintf(Message, keyword), SuggestedFixes: []analysis.SuggestedFix{{
|
||||
Message: "Update",
|
||||
TextEdits: []analysis.TextEdit{{
|
||||
Pos: c.Slash,
|
||||
End: c.End(),
|
||||
NewText: []byte(update),
|
||||
}},
|
||||
}}})
|
||||
}
|
||||
if preLine != nil {
|
||||
fields := strings.Fields(preLine.Text)
|
||||
if len(fields) < 1 {
|
||||
continue
|
||||
}
|
||||
preLineContent := fields[len(fields)-1] + "\n"
|
||||
thisLineContent := c.Text
|
||||
if find {
|
||||
thisLineContent = update
|
||||
}
|
||||
before, after, _ := strings.Cut(thisLineContent, CommentPrefix)
|
||||
update, keyword, find := a.Check(preLineContent + after)
|
||||
if find {
|
||||
var suggestedFixes []analysis.SuggestedFix
|
||||
if strings.Contains(update, preLineContent) {
|
||||
update = before + CommentPrefix + strings.TrimPrefix(update, preLineContent)
|
||||
suggestedFixes = []analysis.SuggestedFix{{
|
||||
Message: "Update",
|
||||
TextEdits: []analysis.TextEdit{{
|
||||
Pos: c.Slash,
|
||||
End: c.End(),
|
||||
NewText: []byte(update),
|
||||
}},
|
||||
}}
|
||||
}
|
||||
pass.Report(analysis.Diagnostic{Pos: c.Slash, End: c.End(), Message: fmt.Sprintf(Message, keyword), SuggestedFixes: suggestedFixes})
|
||||
}
|
||||
}
|
||||
preLine = c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *analyzer) fixDuplicateWordInString(pass *analysis.Pass, lit *ast.BasicLit) {
|
||||
if lit.Kind != token.STRING {
|
||||
return
|
||||
}
|
||||
value, err := strconv.Unquote(lit.Value)
|
||||
if err != nil {
|
||||
fmt.Printf("lit.Value:%v, err: %v\n", lit.Value, err)
|
||||
// fall back to default
|
||||
value = lit.Value
|
||||
}
|
||||
quote := value != lit.Value
|
||||
update, keyword, find := a.Check(value)
|
||||
if quote {
|
||||
update = strconv.Quote(update)
|
||||
}
|
||||
if find {
|
||||
pass.Report(analysis.Diagnostic{Pos: lit.Pos(), End: lit.End(), Message: fmt.Sprintf(Message, keyword), SuggestedFixes: []analysis.SuggestedFix{{
|
||||
Message: "Update",
|
||||
TextEdits: []analysis.TextEdit{{
|
||||
Pos: lit.Pos(),
|
||||
End: lit.End(),
|
||||
NewText: []byte(update),
|
||||
}},
|
||||
}}})
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if key == "" {
|
||||
has := false
|
||||
fields := strings.Fields(raw)
|
||||
for i := range fields {
|
||||
if i == len(fields)-1 {
|
||||
break
|
||||
}
|
||||
if fields[i] == fields[i+1] {
|
||||
has = true
|
||||
}
|
||||
}
|
||||
if !has {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if x := strings.Split(raw, key); len(x) < 2 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
findWordMap := make(map[string]bool, 4)
|
||||
newLine := strings.Builder{}
|
||||
wordStart, spaceStart := 0, 0
|
||||
curWord, preWord := "", ""
|
||||
lastSpace := ""
|
||||
var lastRune int32
|
||||
for i, r := range raw {
|
||||
if !unicode.IsSpace(r) && unicode.IsSpace(lastRune) {
|
||||
// word start position
|
||||
/*
|
||||
i
|
||||
|
|
||||
hello[ spaceA ]the[ spaceB ]the[ spaceC ]word
|
||||
^ ^
|
||||
| curWord: the
|
||||
preWord: the
|
||||
*/
|
||||
symbol := raw[spaceStart:i]
|
||||
if ((key != "" && curWord == key) || key == "") && curWord == preWord && curWord != "" {
|
||||
if !ExcludeWords(curWord) {
|
||||
find = true
|
||||
findWordMap[curWord] = true
|
||||
newLine.WriteString(lastSpace)
|
||||
symbol = ""
|
||||
}
|
||||
} else {
|
||||
newLine.WriteString(lastSpace)
|
||||
newLine.WriteString(curWord)
|
||||
}
|
||||
lastSpace = symbol
|
||||
preWord = curWord
|
||||
wordStart = i
|
||||
} else if unicode.IsSpace(r) && !unicode.IsSpace(lastRune) {
|
||||
// space start position
|
||||
spaceStart = i
|
||||
curWord = raw[wordStart:i]
|
||||
} else if i == len(raw)-1 {
|
||||
// last position
|
||||
word := raw[wordStart:]
|
||||
if ((key != "" && word == key) || key == "") && word == preWord {
|
||||
if !ExcludeWords(word) {
|
||||
find = true
|
||||
findWordMap[word] = true
|
||||
}
|
||||
} else {
|
||||
newLine.WriteString(lastSpace)
|
||||
newLine.WriteString(word)
|
||||
}
|
||||
}
|
||||
lastRune = r
|
||||
}
|
||||
if find {
|
||||
new = newLine.String()
|
||||
findWordSlice := make([]string, len(findWordMap))
|
||||
i := 0
|
||||
for k := range findWordMap {
|
||||
findWordSlice[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(findWordSlice)
|
||||
findWord = strings.Join(findWordSlice, ",")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *analyzer) Check(raw string) (update string, keyword string, find bool) {
|
||||
for _, key := range a.KeyWord {
|
||||
updateOne, _, findOne := CheckOneKey(raw, key)
|
||||
if findOne {
|
||||
raw = updateOne
|
||||
find = findOne
|
||||
update = updateOne
|
||||
if keyword == "" {
|
||||
keyword = key
|
||||
} else {
|
||||
keyword = keyword + "," + key
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(a.KeyWord) == 0 {
|
||||
return CheckOneKey(raw, "")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ExcludeWords determines whether duplicate words should be reported,
|
||||
//
|
||||
// e.g. %s, </div> should not be reported.
|
||||
func ExcludeWords(word string) (exclude bool) {
|
||||
firstRune, _ := utf8.DecodeRuneInString(word)
|
||||
if unicode.IsDigit(firstRune) {
|
||||
return true
|
||||
}
|
||||
if unicode.IsPunct(firstRune) {
|
||||
return true
|
||||
}
|
||||
if unicode.IsSymbol(firstRune) {
|
||||
return true
|
||||
}
|
||||
if _, exist := ignoreWord[word]; exist {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isExampleOutputStart(comment string) bool {
|
||||
return strings.HasPrefix(comment, "// Output:") ||
|
||||
strings.HasPrefix(comment, "// output:") ||
|
||||
strings.HasPrefix(comment, "// Unordered output:") ||
|
||||
strings.HasPrefix(comment, "// unordered output:")
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// MIT License
|
||||
//
|
||||
// # Copyright (c) 2022 Abirdcfly
|
||||
//
|
||||
// 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.
|
||||
|
||||
package dupword
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var Version = "dev"
|
||||
|
||||
type version struct{}
|
||||
|
||||
func (version) IsBoolFlag() bool { return true }
|
||||
func (version) Get() interface{} { return nil }
|
||||
func (version) String() string { return "" }
|
||||
func (version) Set(_ string) error {
|
||||
fmt.Println(Version)
|
||||
os.Exit(0)
|
||||
return nil
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Anton Telyshev
|
||||
|
||||
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.
|
|
@ -1,135 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
// New returns new errname analyzer.
|
||||
func New() *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: "errname",
|
||||
Doc: "Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`.",
|
||||
Run: run,
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
}
|
||||
}
|
||||
|
||||
type stringSet = map[string]struct{}
|
||||
|
||||
var (
|
||||
importNodes = []ast.Node{(*ast.ImportSpec)(nil)}
|
||||
typeNodes = []ast.Node{(*ast.TypeSpec)(nil)}
|
||||
funcNodes = []ast.Node{(*ast.FuncDecl)(nil)}
|
||||
)
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
|
||||
pkgAliases := map[string]string{}
|
||||
insp.Preorder(importNodes, func(node ast.Node) {
|
||||
i := node.(*ast.ImportSpec)
|
||||
if n := i.Name; n != nil && i.Path != nil {
|
||||
if path, err := strconv.Unquote(i.Path.Value); err == nil {
|
||||
pkgAliases[n.Name] = getPkgFromPath(path)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
allTypes := stringSet{}
|
||||
typesSpecs := map[string]*ast.TypeSpec{}
|
||||
insp.Preorder(typeNodes, func(node ast.Node) {
|
||||
t := node.(*ast.TypeSpec)
|
||||
allTypes[t.Name.Name] = struct{}{}
|
||||
typesSpecs[t.Name.Name] = t
|
||||
})
|
||||
|
||||
errorTypes := stringSet{}
|
||||
insp.Preorder(funcNodes, func(node ast.Node) {
|
||||
f := node.(*ast.FuncDecl)
|
||||
t, ok := isMethodError(f)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
errorTypes[t] = struct{}{}
|
||||
|
||||
tSpec, ok := typesSpecs[t]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("no specification for type %q", t))
|
||||
}
|
||||
|
||||
if _, ok := tSpec.Type.(*ast.ArrayType); ok {
|
||||
if !isValidErrorArrayTypeName(t) {
|
||||
reportAboutErrorType(pass, tSpec.Pos(), t, true)
|
||||
}
|
||||
} else if !isValidErrorTypeName(t) {
|
||||
reportAboutErrorType(pass, tSpec.Pos(), t, false)
|
||||
}
|
||||
})
|
||||
|
||||
errorFuncs := stringSet{}
|
||||
insp.Preorder(funcNodes, func(node ast.Node) {
|
||||
f := node.(*ast.FuncDecl)
|
||||
if isFuncReturningErr(f.Type, allTypes, errorTypes) {
|
||||
errorFuncs[f.Name.Name] = struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
inspectPkgLevelVarsOnly := func(node ast.Node) bool {
|
||||
switch v := node.(type) {
|
||||
case *ast.FuncDecl:
|
||||
return false
|
||||
|
||||
case *ast.ValueSpec:
|
||||
if name, ok := isSentinelError(v, pkgAliases, allTypes, errorTypes, errorFuncs); ok && !isValidErrorVarName(name) {
|
||||
reportAboutErrorVar(pass, v.Pos(), name)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
for _, f := range pass.Files {
|
||||
ast.Inspect(f, inspectPkgLevelVarsOnly)
|
||||
}
|
||||
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
func reportAboutErrorType(pass *analysis.Pass, typePos token.Pos, typeName string, isArrayType bool) {
|
||||
var form string
|
||||
if unicode.IsLower([]rune(typeName)[0]) {
|
||||
form = "xxxError"
|
||||
} else {
|
||||
form = "XxxError"
|
||||
}
|
||||
|
||||
if isArrayType {
|
||||
form += "s"
|
||||
}
|
||||
pass.Reportf(typePos, "the type name `%s` should conform to the `%s` format", typeName, form)
|
||||
}
|
||||
|
||||
func reportAboutErrorVar(pass *analysis.Pass, pos token.Pos, varName string) {
|
||||
var form string
|
||||
if unicode.IsLower([]rune(varName)[0]) {
|
||||
form = "errXxx"
|
||||
} else {
|
||||
form = "ErrXxx"
|
||||
}
|
||||
pass.Reportf(pos, "the variable name `%s` should conform to the `%s` format", varName, form)
|
||||
}
|
||||
|
||||
func getPkgFromPath(p string) string {
|
||||
idx := strings.LastIndex(p, "/")
|
||||
if idx == -1 {
|
||||
return p
|
||||
}
|
||||
return p[idx+1:]
|
||||
}
|
|
@ -1,272 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func isMethodError(f *ast.FuncDecl) (typeName string, ok bool) {
|
||||
if f.Recv == nil || len(f.Recv.List) != 1 {
|
||||
return "", false
|
||||
}
|
||||
if f.Name == nil || f.Name.Name != "Error" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if f.Type == nil || f.Type.Results == nil || len(f.Type.Results.List) != 1 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
returnType, ok := f.Type.Results.List[0].Type.(*ast.Ident)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
var receiverType string
|
||||
|
||||
unwrapIdentName := func(e ast.Expr) string {
|
||||
switch v := e.(type) {
|
||||
case *ast.Ident:
|
||||
return v.Name
|
||||
case *ast.IndexExpr:
|
||||
if i, ok := v.X.(*ast.Ident); ok {
|
||||
return i.Name
|
||||
}
|
||||
case *ast.IndexListExpr:
|
||||
if i, ok := v.X.(*ast.Ident); ok {
|
||||
return i.Name
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("unsupported Error() receiver type %q", types.ExprString(e)))
|
||||
}
|
||||
|
||||
switch rt := f.Recv.List[0].Type; v := rt.(type) {
|
||||
case *ast.Ident, *ast.IndexExpr, *ast.IndexListExpr: // SomeError, SomeError[T], SomeError[T1, T2, ...]
|
||||
receiverType = unwrapIdentName(rt)
|
||||
|
||||
case *ast.StarExpr: // *SomeError, *SomeError[T], *SomeError[T1, T2, ...]
|
||||
receiverType = unwrapIdentName(v.X)
|
||||
}
|
||||
|
||||
return receiverType, returnType.Name == "string"
|
||||
}
|
||||
|
||||
func isValidErrorTypeName(s string) bool {
|
||||
if isInitialism(s) {
|
||||
return true
|
||||
}
|
||||
|
||||
words := split(s)
|
||||
wordsCnt := wordsCount(words)
|
||||
|
||||
if wordsCnt["error"] != 1 {
|
||||
return false
|
||||
}
|
||||
return words[len(words)-1] == "error"
|
||||
}
|
||||
|
||||
func isValidErrorArrayTypeName(s string) bool {
|
||||
if isInitialism(s) {
|
||||
return true
|
||||
}
|
||||
|
||||
words := split(s)
|
||||
wordsCnt := wordsCount(words)
|
||||
|
||||
if wordsCnt["errors"] != 1 {
|
||||
return false
|
||||
}
|
||||
return words[len(words)-1] == "errors"
|
||||
}
|
||||
|
||||
func isFuncReturningErr(fType *ast.FuncType, allTypes, errorTypes stringSet) bool {
|
||||
if fType == nil || fType.Results == nil || len(fType.Results.List) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
var returnTypeName string
|
||||
switch rt := fType.Results.List[0].Type.(type) {
|
||||
case *ast.Ident:
|
||||
returnTypeName = rt.Name
|
||||
case *ast.StarExpr:
|
||||
if i, ok := rt.X.(*ast.Ident); ok {
|
||||
returnTypeName = i.Name
|
||||
}
|
||||
}
|
||||
|
||||
return isErrorType(returnTypeName, allTypes, errorTypes)
|
||||
}
|
||||
|
||||
func isErrorType(tName string, allTypes, errorTypes stringSet) bool {
|
||||
_, isUserType := allTypes[tName]
|
||||
_, isErrType := errorTypes[tName]
|
||||
return isErrType || (tName == "error" && !isUserType)
|
||||
}
|
||||
|
||||
var knownErrConstructors = stringSet{
|
||||
"fmt.Errorf": {},
|
||||
"errors.Errorf": {},
|
||||
"errors.New": {},
|
||||
"errors.Newf": {},
|
||||
"errors.NewWithDepth": {},
|
||||
"errors.NewWithDepthf": {},
|
||||
"errors.NewAssertionErrorWithWrappedErrf": {},
|
||||
}
|
||||
|
||||
func isSentinelError( //nolint:gocognit,gocyclo
|
||||
v *ast.ValueSpec,
|
||||
pkgAliases map[string]string,
|
||||
allTypes, errorTypes, errorFuncs stringSet,
|
||||
) (varName string, ok bool) {
|
||||
if len(v.Names) != 1 {
|
||||
return "", false
|
||||
}
|
||||
varName = v.Names[0].Name
|
||||
|
||||
switch vv := v.Type.(type) {
|
||||
// var ErrEndOfFile error
|
||||
// var ErrEndOfFile SomeErrType
|
||||
case *ast.Ident:
|
||||
if isErrorType(vv.Name, allTypes, errorTypes) {
|
||||
return varName, true
|
||||
}
|
||||
|
||||
// var ErrEndOfFile *SomeErrType
|
||||
case *ast.StarExpr:
|
||||
if i, ok := vv.X.(*ast.Ident); ok && isErrorType(i.Name, allTypes, errorTypes) {
|
||||
return varName, true
|
||||
}
|
||||
}
|
||||
|
||||
if len(v.Values) != 1 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
switch vv := v.Values[0].(type) {
|
||||
case *ast.CallExpr:
|
||||
switch fun := vv.Fun.(type) {
|
||||
// var ErrEndOfFile = errors.New("end of file")
|
||||
case *ast.SelectorExpr:
|
||||
pkg, ok := fun.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
pkgFun := fun.Sel
|
||||
|
||||
pkgName := pkg.Name
|
||||
if a, ok := pkgAliases[pkgName]; ok {
|
||||
pkgName = a
|
||||
}
|
||||
|
||||
_, ok = knownErrConstructors[pkgName+"."+pkgFun.Name]
|
||||
return varName, ok
|
||||
|
||||
// var ErrEndOfFile = newErrEndOfFile()
|
||||
// var ErrEndOfFile = new(EndOfFileError)
|
||||
// const ErrEndOfFile = constError("end of file")
|
||||
// var statusCodeError = new(SomePtrError[string])
|
||||
case *ast.Ident:
|
||||
if isErrorType(fun.Name, allTypes, errorTypes) {
|
||||
return varName, true
|
||||
}
|
||||
|
||||
if _, ok := errorFuncs[fun.Name]; ok {
|
||||
return varName, true
|
||||
}
|
||||
|
||||
if fun.Name == "new" && len(vv.Args) == 1 {
|
||||
switch i := vv.Args[0].(type) {
|
||||
case *ast.Ident:
|
||||
return varName, isErrorType(i.Name, allTypes, errorTypes)
|
||||
case *ast.IndexExpr:
|
||||
if ii, ok := i.X.(*ast.Ident); ok {
|
||||
return varName, isErrorType(ii.Name, allTypes, errorTypes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// var ErrEndOfFile = func() error { ... }
|
||||
case *ast.FuncLit:
|
||||
return varName, isFuncReturningErr(fun.Type, allTypes, errorTypes)
|
||||
}
|
||||
|
||||
// var ErrEndOfFile = &EndOfFileError{}
|
||||
// var ErrOK = &SomePtrError[string]{Code: "200 OK"}
|
||||
case *ast.UnaryExpr:
|
||||
if vv.Op == token.AND { // &
|
||||
if lit, ok := vv.X.(*ast.CompositeLit); ok {
|
||||
switch i := lit.Type.(type) {
|
||||
case *ast.Ident:
|
||||
return varName, isErrorType(i.Name, allTypes, errorTypes)
|
||||
case *ast.IndexExpr:
|
||||
if ii, ok := i.X.(*ast.Ident); ok {
|
||||
return varName, isErrorType(ii.Name, allTypes, errorTypes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// var ErrEndOfFile = EndOfFileError{}
|
||||
// var ErrNotFound = SomeError[string]{Code: "Not Found"}
|
||||
case *ast.CompositeLit:
|
||||
switch i := vv.Type.(type) {
|
||||
case *ast.Ident:
|
||||
return varName, isErrorType(i.Name, allTypes, errorTypes)
|
||||
case *ast.IndexExpr:
|
||||
if ii, ok := i.X.(*ast.Ident); ok {
|
||||
return varName, isErrorType(ii.Name, allTypes, errorTypes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
func isValidErrorVarName(s string) bool {
|
||||
if isInitialism(s) {
|
||||
return true
|
||||
}
|
||||
|
||||
words := split(s)
|
||||
wordsCnt := wordsCount(words)
|
||||
|
||||
if wordsCnt["err"] != 1 {
|
||||
return false
|
||||
}
|
||||
return words[0] == "err"
|
||||
}
|
||||
|
||||
func isInitialism(s string) bool {
|
||||
return strings.ToLower(s) == s || strings.ToUpper(s) == s
|
||||
}
|
||||
|
||||
func split(s string) []string {
|
||||
var words []string
|
||||
ss := []rune(s)
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteRune(ss[0])
|
||||
|
||||
for _, r := range ss[1:] {
|
||||
if unicode.IsUpper(r) {
|
||||
words = append(words, strings.ToLower(b.String()))
|
||||
b.Reset()
|
||||
}
|
||||
b.WriteRune(r)
|
||||
}
|
||||
|
||||
words = append(words, strings.ToLower(b.String()))
|
||||
return words
|
||||
}
|
||||
|
||||
func wordsCount(w []string) map[string]int {
|
||||
result := make(map[string]int, len(w))
|
||||
for _, ww := range w {
|
||||
result[ww]++
|
||||
}
|
||||
return result
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Anton Telyshev
|
||||
|
||||
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.
|
|
@ -1,184 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
const (
|
||||
name = "nilnil"
|
||||
doc = "Checks that there is no simultaneous return of `nil` error and an invalid value."
|
||||
|
||||
reportMsg = "return both the `nil` error and invalid value: use a sentinel error instead"
|
||||
)
|
||||
|
||||
// New returns new nilnil analyzer.
|
||||
func New() *analysis.Analyzer {
|
||||
n := newNilNil()
|
||||
|
||||
a := &analysis.Analyzer{
|
||||
Name: name,
|
||||
Doc: doc,
|
||||
Run: n.run,
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
}
|
||||
a.Flags.Var(&n.checkedTypes, "checked-types", "coma separated list")
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
type nilNil struct {
|
||||
checkedTypes checkedTypes
|
||||
}
|
||||
|
||||
func newNilNil() *nilNil {
|
||||
return &nilNil{
|
||||
checkedTypes: newDefaultCheckedTypes(),
|
||||
}
|
||||
}
|
||||
|
||||
var funcAndReturns = []ast.Node{
|
||||
(*ast.FuncDecl)(nil),
|
||||
(*ast.FuncLit)(nil),
|
||||
(*ast.ReturnStmt)(nil),
|
||||
}
|
||||
|
||||
func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) {
|
||||
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
|
||||
var fs funcTypeStack
|
||||
insp.Nodes(funcAndReturns, func(node ast.Node, push bool) (proceed bool) {
|
||||
switch v := node.(type) {
|
||||
case *ast.FuncLit:
|
||||
if push {
|
||||
fs.Push(v.Type)
|
||||
} else {
|
||||
fs.Pop()
|
||||
}
|
||||
|
||||
case *ast.FuncDecl:
|
||||
if push {
|
||||
fs.Push(v.Type)
|
||||
} else {
|
||||
fs.Pop()
|
||||
}
|
||||
|
||||
case *ast.ReturnStmt:
|
||||
ft := fs.Top() // Current function.
|
||||
|
||||
if !push || len(v.Results) != 2 || ft == nil || ft.Results == nil || len(ft.Results.List) != 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
fRes1Type := pass.TypesInfo.TypeOf(ft.Results.List[0].Type)
|
||||
if fRes1Type == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
fRes2Type := pass.TypesInfo.TypeOf(ft.Results.List[1].Type)
|
||||
if fRes2Type == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
ok, zv := n.isDangerNilType(fRes1Type)
|
||||
if !(ok && isErrorType(fRes2Type)) {
|
||||
return false
|
||||
}
|
||||
|
||||
retVal, retErr := v.Results[0], v.Results[1]
|
||||
|
||||
var needWarn bool
|
||||
switch zv {
|
||||
case zeroValueNil:
|
||||
needWarn = isNil(pass, retVal) && isNil(pass, retErr)
|
||||
case zeroValueZero:
|
||||
needWarn = isZero(retVal) && isNil(pass, retErr)
|
||||
}
|
||||
|
||||
if needWarn {
|
||||
pass.Reportf(v.Pos(), reportMsg)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
type zeroValue int
|
||||
|
||||
const (
|
||||
zeroValueNil = iota + 1
|
||||
zeroValueZero
|
||||
)
|
||||
|
||||
func (n *nilNil) isDangerNilType(t types.Type) (bool, zeroValue) {
|
||||
switch v := t.(type) {
|
||||
case *types.Pointer:
|
||||
return n.checkedTypes.Contains(ptrType), zeroValueNil
|
||||
|
||||
case *types.Signature:
|
||||
return n.checkedTypes.Contains(funcType), zeroValueNil
|
||||
|
||||
case *types.Interface:
|
||||
return n.checkedTypes.Contains(ifaceType), zeroValueNil
|
||||
|
||||
case *types.Map:
|
||||
return n.checkedTypes.Contains(mapType), zeroValueNil
|
||||
|
||||
case *types.Chan:
|
||||
return n.checkedTypes.Contains(chanType), zeroValueNil
|
||||
|
||||
case *types.Basic:
|
||||
if v.Kind() == types.Uintptr {
|
||||
return n.checkedTypes.Contains(uintptrType), zeroValueZero
|
||||
}
|
||||
if v.Kind() == types.UnsafePointer {
|
||||
return n.checkedTypes.Contains(unsafeptrType), zeroValueNil
|
||||
}
|
||||
|
||||
case *types.Named:
|
||||
return n.isDangerNilType(v.Underlying())
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
|
||||
var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
|
||||
|
||||
func isErrorType(t types.Type) bool {
|
||||
_, ok := t.Underlying().(*types.Interface)
|
||||
return ok && types.Implements(t, errorIface)
|
||||
}
|
||||
|
||||
func isNil(pass *analysis.Pass, e ast.Expr) bool {
|
||||
i, ok := e.(*ast.Ident)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
_, ok = pass.TypesInfo.ObjectOf(i).(*types.Nil)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isZero(e ast.Expr) bool {
|
||||
bl, ok := e.(*ast.BasicLit)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if bl.Kind != token.INT {
|
||||
return false
|
||||
}
|
||||
|
||||
v, err := strconv.ParseInt(bl.Value, 0, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return v == 0
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func newDefaultCheckedTypes() checkedTypes {
|
||||
return checkedTypes{
|
||||
ptrType: {},
|
||||
funcType: {},
|
||||
ifaceType: {},
|
||||
mapType: {},
|
||||
chanType: {},
|
||||
uintptrType: {},
|
||||
unsafeptrType: {},
|
||||
}
|
||||
}
|
||||
|
||||
const separator = ','
|
||||
|
||||
type typeName string
|
||||
|
||||
func (t typeName) S() string {
|
||||
return string(t)
|
||||
}
|
||||
|
||||
const (
|
||||
ptrType typeName = "ptr"
|
||||
funcType typeName = "func"
|
||||
ifaceType typeName = "iface"
|
||||
mapType typeName = "map"
|
||||
chanType typeName = "chan"
|
||||
uintptrType typeName = "uintptr"
|
||||
unsafeptrType typeName = "unsafeptr"
|
||||
)
|
||||
|
||||
type checkedTypes map[typeName]struct{}
|
||||
|
||||
func (c checkedTypes) Contains(t typeName) bool {
|
||||
_, ok := c[t]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (c checkedTypes) String() string {
|
||||
result := make([]string, 0, len(c))
|
||||
for t := range c {
|
||||
result = append(result, t.S())
|
||||
}
|
||||
|
||||
sort.Strings(result)
|
||||
return strings.Join(result, string(separator))
|
||||
}
|
||||
|
||||
func (c checkedTypes) Set(s string) error {
|
||||
types := strings.FieldsFunc(s, func(c rune) bool { return c == separator })
|
||||
if len(types) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.disableAll()
|
||||
for _, t := range types {
|
||||
switch tt := typeName(t); tt {
|
||||
case ptrType, funcType, ifaceType, mapType, chanType, uintptrType, unsafeptrType:
|
||||
c[tt] = struct{}{}
|
||||
default:
|
||||
return fmt.Errorf("unknown checked type name %q (see help)", t)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c checkedTypes) disableAll() {
|
||||
for k := range c {
|
||||
delete(c, k)
|
||||
}
|
||||
}
|
29
tests/tools/vendor/github.com/Antonboom/nilnil/pkg/analyzer/func_type_stack.go
generated
vendored
29
tests/tools/vendor/github.com/Antonboom/nilnil/pkg/analyzer/func_type_stack.go
generated
vendored
|
@ -1,29 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
type funcTypeStack []*ast.FuncType
|
||||
|
||||
func (s *funcTypeStack) Push(f *ast.FuncType) {
|
||||
*s = append(*s, f)
|
||||
}
|
||||
|
||||
func (s *funcTypeStack) Pop() *ast.FuncType {
|
||||
if len(*s) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
last := len(*s) - 1
|
||||
f := (*s)[last]
|
||||
*s = (*s)[:last]
|
||||
return f
|
||||
}
|
||||
|
||||
func (s *funcTypeStack) Top() *ast.FuncType {
|
||||
if len(*s) == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*s)[len(*s)-1]
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Anton Telyshev
|
||||
|
||||
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.
|
|
@ -1,93 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"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"
|
||||
)
|
||||
|
||||
const (
|
||||
name = "testifylint"
|
||||
doc = "Checks usage of " + testify.ModulePath + "."
|
||||
url = "https://github.com/antonboom/" + name
|
||||
)
|
||||
|
||||
// New returns a new instance of testifylint analyzer.
|
||||
func New() *analysis.Analyzer {
|
||||
cfg := config.NewDefault()
|
||||
|
||||
analyzer := &analysis.Analyzer{
|
||||
Name: name,
|
||||
Doc: doc,
|
||||
URL: url,
|
||||
Run: func(pass *analysis.Pass) (any, error) {
|
||||
regularCheckers, advancedCheckers, err := newCheckers(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("build checkers: %v", err)
|
||||
}
|
||||
|
||||
tl := &testifyLint{
|
||||
regularCheckers: regularCheckers,
|
||||
advancedCheckers: advancedCheckers,
|
||||
}
|
||||
return tl.run(pass)
|
||||
},
|
||||
}
|
||||
config.BindToFlags(&cfg, &analyzer.Flags)
|
||||
|
||||
return analyzer
|
||||
}
|
||||
|
||||
type testifyLint struct {
|
||||
regularCheckers []checkers.RegularChecker
|
||||
advancedCheckers []checkers.AdvancedChecker
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
insp := inspector.New(filesToAnalysis)
|
||||
|
||||
// Regular checkers.
|
||||
insp.Preorder([]ast.Node{(*ast.CallExpr)(nil)}, func(node ast.Node) {
|
||||
tl.regularCheck(pass, node.(*ast.CallExpr))
|
||||
})
|
||||
|
||||
// Advanced checkers.
|
||||
for _, ch := range tl.advancedCheckers {
|
||||
for _, d := range ch.Check(pass, insp) {
|
||||
pass.Report(d)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (tl *testifyLint) regularCheck(pass *analysis.Pass, ce *ast.CallExpr) {
|
||||
call := checkers.NewCallMeta(pass, ce)
|
||||
if nil == call {
|
||||
return
|
||||
}
|
||||
|
||||
for _, ch := range tl.regularCheckers {
|
||||
if d := ch.Check(pass, call); d != nil {
|
||||
pass.Report(*d)
|
||||
// NOTE(a.telyshev): I'm not interested in multiple diagnostics per assertion.
|
||||
// This simplifies the code and also makes the linter more efficient.
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
81
tests/tools/vendor/github.com/Antonboom/testifylint/analyzer/checkers_factory.go
generated
vendored
81
tests/tools/vendor/github.com/Antonboom/testifylint/analyzer/checkers_factory.go
generated
vendored
|
@ -1,81 +0,0 @@
|
|||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/checkers"
|
||||
"github.com/Antonboom/testifylint/internal/config"
|
||||
)
|
||||
|
||||
// newCheckers accepts linter config and returns slices of enabled checkers sorted by priority.
|
||||
func newCheckers(cfg config.Config) ([]checkers.RegularChecker, []checkers.AdvancedChecker, error) {
|
||||
if err := cfg.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
enabledCheckersSet := make(map[string]struct{})
|
||||
|
||||
if cfg.EnableAll {
|
||||
for _, checker := range checkers.All() {
|
||||
enabledCheckersSet[checker] = struct{}{}
|
||||
}
|
||||
} else if !cfg.DisableAll {
|
||||
for _, checker := range checkers.EnabledByDefault() {
|
||||
enabledCheckersSet[checker] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for _, checker := range cfg.EnabledCheckers {
|
||||
enabledCheckersSet[checker] = struct{}{}
|
||||
}
|
||||
|
||||
for _, checker := range cfg.DisabledCheckers {
|
||||
delete(enabledCheckersSet, checker)
|
||||
}
|
||||
|
||||
enabledCheckers := make([]string, 0, len(enabledCheckersSet))
|
||||
for v := range enabledCheckersSet {
|
||||
enabledCheckers = append(enabledCheckers, v)
|
||||
}
|
||||
checkers.SortByPriority(enabledCheckers)
|
||||
|
||||
regularCheckers := make([]checkers.RegularChecker, 0, len(enabledCheckers))
|
||||
advancedCheckers := make([]checkers.AdvancedChecker, 0, len(enabledCheckers)/2)
|
||||
|
||||
for _, name := range enabledCheckers {
|
||||
ch, ok := checkers.Get(name)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unknown checker %q", name)
|
||||
}
|
||||
|
||||
switch c := ch.(type) {
|
||||
case *checkers.BoolCompare:
|
||||
c.SetIgnoreCustomTypes(cfg.BoolCompare.IgnoreCustomTypes)
|
||||
|
||||
case *checkers.ExpectedActual:
|
||||
c.SetExpVarPattern(cfg.ExpectedActual.ExpVarPattern.Regexp)
|
||||
|
||||
case *checkers.Formatter:
|
||||
c.SetCheckFormatString(cfg.Formatter.CheckFormatString)
|
||||
c.SetRequireFFuncs(cfg.Formatter.RequireFFuncs)
|
||||
|
||||
case *checkers.GoRequire:
|
||||
c.SetIgnoreHTTPHandlers(cfg.GoRequire.IgnoreHTTPHandlers)
|
||||
|
||||
case *checkers.RequireError:
|
||||
c.SetFnPattern(cfg.RequireError.FnPattern.Regexp)
|
||||
|
||||
case *checkers.SuiteExtraAssertCall:
|
||||
c.SetMode(cfg.SuiteExtraAssertCall.Mode)
|
||||
}
|
||||
|
||||
switch casted := ch.(type) {
|
||||
case checkers.RegularChecker:
|
||||
regularCheckers = append(regularCheckers, casted)
|
||||
case checkers.AdvancedChecker:
|
||||
advancedCheckers = append(advancedCheckers, casted)
|
||||
}
|
||||
}
|
||||
|
||||
return regularCheckers, advancedCheckers, nil
|
||||
}
|
9
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/doc.go
generated
vendored
9
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/doc.go
generated
vendored
|
@ -1,9 +0,0 @@
|
|||
// Package analysisutil contains functions common for `analyzer` and `internal/checkers` packages.
|
||||
// In addition, it is intended to "lighten" these packages.
|
||||
//
|
||||
// If the function is common to several packages, or it makes sense to test it separately without
|
||||
// "polluting" the target package with tests of private functionality, then you can put function in this package.
|
||||
//
|
||||
// It's important to avoid dependency on `golang.org/x/tools/go/analysis` in the helpers API.
|
||||
// This makes the API "narrower" and also allows you to test functions without some "abstraction leaks".
|
||||
package analysisutil
|
28
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go
generated
vendored
28
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go
generated
vendored
|
@ -1,28 +0,0 @@
|
|||
package analysisutil
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Imports tells if the file imports at least one of the packages.
|
||||
// If no packages provided then function returns false.
|
||||
func Imports(file *ast.File, pkgs ...string) bool {
|
||||
for _, i := range file.Imports {
|
||||
if i.Path == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
path, err := strconv.Unquote(i.Path.Value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// NOTE(a.telyshev): Don't use `slices.Contains` to keep the minimum module version 1.20.
|
||||
for _, pkg := range pkgs { // Small O(n).
|
||||
if pkg == path {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
34
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/format.go
generated
vendored
34
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/format.go
generated
vendored
|
@ -1,34 +0,0 @@
|
|||
package analysisutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// NodeString is a more powerful analogue of types.ExprString.
|
||||
// Return empty string if node AST is invalid.
|
||||
func NodeString(fset *token.FileSet, node ast.Node) string {
|
||||
if v := formatNode(fset, node); v != nil {
|
||||
return v.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NodeBytes works as NodeString but returns a byte slice.
|
||||
// Return nil if node AST is invalid.
|
||||
func NodeBytes(fset *token.FileSet, node ast.Node) []byte {
|
||||
if v := formatNode(fset, node); v != nil {
|
||||
return v.Bytes()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatNode(fset *token.FileSet, node ast.Node) *bytes.Buffer {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := format.Node(buf, fset, node); err != nil {
|
||||
return nil
|
||||
}
|
||||
return buf
|
||||
}
|
34
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/object.go
generated
vendored
34
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/object.go
generated
vendored
|
@ -1,34 +0,0 @@
|
|||
package analysisutil
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// ObjectOf works in context of Golang package and returns types.Object for the given object's package and name.
|
||||
// The search is based on the provided package and its dependencies (imports).
|
||||
// Returns nil if the object is not found.
|
||||
func ObjectOf(pkg *types.Package, objPkg, objName string) types.Object {
|
||||
if pkg.Path() == objPkg {
|
||||
return pkg.Scope().Lookup(objName)
|
||||
}
|
||||
|
||||
for _, i := range pkg.Imports() {
|
||||
if trimVendor(i.Path()) == objPkg {
|
||||
return i.Scope().Lookup(objName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsObj returns true if expression is identifier which notes to given types.Object.
|
||||
// Useful in combination with types.Universe objects.
|
||||
func IsObj(typesInfo *types.Info, expr ast.Expr, expected types.Object) bool {
|
||||
id, ok := expr.(*ast.Ident)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
obj := typesInfo.ObjectOf(id)
|
||||
return obj == expected
|
||||
}
|
19
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/pkg.go
generated
vendored
19
tests/tools/vendor/github.com/Antonboom/testifylint/internal/analysisutil/pkg.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
package analysisutil
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsPkg checks that package has corresponding objName and path.
|
||||
// Supports vendored packages.
|
||||
func IsPkg(pkg *types.Package, name, path string) bool {
|
||||
return pkg.Name() == name && trimVendor(pkg.Path()) == path
|
||||
}
|
||||
|
||||
func trimVendor(path string) string {
|
||||
if strings.HasPrefix(path, "vendor/") {
|
||||
return path[len("vendor/"):]
|
||||
}
|
||||
return path
|
||||
}
|
69
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go
generated
vendored
69
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go
generated
vendored
|
@ -1,69 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/testify"
|
||||
)
|
||||
|
||||
// BlankImport detects useless blank imports of testify's packages.
|
||||
// These imports are useless since testify doesn't do any magic with init() function.
|
||||
//
|
||||
// The checker detects situations like
|
||||
//
|
||||
// import (
|
||||
// "testing"
|
||||
//
|
||||
// _ "github.com/stretchr/testify"
|
||||
// _ "github.com/stretchr/testify/assert"
|
||||
// _ "github.com/stretchr/testify/http"
|
||||
// _ "github.com/stretchr/testify/mock"
|
||||
// _ "github.com/stretchr/testify/require"
|
||||
// _ "github.com/stretchr/testify/suite"
|
||||
// )
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// import (
|
||||
// "testing"
|
||||
// )
|
||||
type BlankImport struct{}
|
||||
|
||||
// NewBlankImport constructs BlankImport checker.
|
||||
func NewBlankImport() BlankImport { return BlankImport{} }
|
||||
func (BlankImport) Name() string { return "blank-import" }
|
||||
|
||||
func (checker BlankImport) Check(pass *analysis.Pass, _ *inspector.Inspector) (diagnostics []analysis.Diagnostic) {
|
||||
for _, file := range pass.Files {
|
||||
for _, imp := range file.Imports {
|
||||
if imp.Name == nil || imp.Name.Name != "_" {
|
||||
continue
|
||||
}
|
||||
|
||||
pkg, err := strconv.Unquote(imp.Path.Value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := packagesNotIntendedForBlankImport[pkg]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("avoid blank import of %s as it does nothing", pkg)
|
||||
diagnostics = append(diagnostics, *newDiagnostic(checker.Name(), imp, msg, nil))
|
||||
}
|
||||
}
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
var packagesNotIntendedForBlankImport = map[string]struct{}{
|
||||
testify.ModulePath: {},
|
||||
testify.AssertPkgPath: {},
|
||||
testify.HTTPPkgPath: {},
|
||||
testify.MockPkgPath: {},
|
||||
testify.RequirePkgPath: {},
|
||||
testify.SuitePkgPath: {},
|
||||
}
|
212
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go
generated
vendored
212
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go
generated
vendored
|
@ -1,212 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
// BoolCompare detects situations like
|
||||
//
|
||||
// assert.Equal(t, false, result)
|
||||
// assert.EqualValues(t, false, result)
|
||||
// assert.Exactly(t, false, result)
|
||||
// assert.NotEqual(t, true, result)
|
||||
// assert.NotEqualValues(t, true, result)
|
||||
// assert.False(t, !result)
|
||||
// assert.True(t, result == true)
|
||||
// ...
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.False(t, result)
|
||||
// assert.True(t, result)
|
||||
type BoolCompare struct {
|
||||
ignoreCustomTypes bool
|
||||
}
|
||||
|
||||
// NewBoolCompare constructs BoolCompare checker.
|
||||
func NewBoolCompare() *BoolCompare { return new(BoolCompare) }
|
||||
func (BoolCompare) Name() string { return "bool-compare" }
|
||||
|
||||
func (checker *BoolCompare) SetIgnoreCustomTypes(v bool) *BoolCompare {
|
||||
checker.ignoreCustomTypes = v
|
||||
return checker
|
||||
}
|
||||
|
||||
func (checker BoolCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
newBoolCast := func(e ast.Expr) ast.Expr {
|
||||
return &ast.CallExpr{Fun: &ast.Ident{Name: "bool"}, Args: []ast.Expr{e}}
|
||||
}
|
||||
|
||||
newUseFnDiagnostic := func(proposed string, survivingArg ast.Expr, replaceStart, replaceEnd token.Pos) *analysis.Diagnostic {
|
||||
if !isBuiltinBool(pass, survivingArg) {
|
||||
if checker.ignoreCustomTypes {
|
||||
return nil
|
||||
}
|
||||
survivingArg = newBoolCast(survivingArg)
|
||||
}
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
|
||||
newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
|
||||
Pos: replaceStart,
|
||||
End: replaceEnd,
|
||||
NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
newUseTrueDiagnostic := func(survivingArg ast.Expr, replaceStart, replaceEnd token.Pos) *analysis.Diagnostic {
|
||||
return newUseFnDiagnostic("True", survivingArg, replaceStart, replaceEnd)
|
||||
}
|
||||
|
||||
newUseFalseDiagnostic := func(survivingArg ast.Expr, replaceStart, replaceEnd token.Pos) *analysis.Diagnostic {
|
||||
return newUseFnDiagnostic("False", survivingArg, replaceStart, replaceEnd)
|
||||
}
|
||||
|
||||
newNeedSimplifyDiagnostic := func(survivingArg ast.Expr, replaceStart, replaceEnd token.Pos) *analysis.Diagnostic {
|
||||
if !isBuiltinBool(pass, survivingArg) {
|
||||
if checker.ignoreCustomTypes {
|
||||
return nil
|
||||
}
|
||||
survivingArg = newBoolCast(survivingArg)
|
||||
}
|
||||
return newDiagnostic(checker.Name(), call, "need to simplify the assertion",
|
||||
&analysis.SuggestedFix{
|
||||
Message: "Simplify the assertion",
|
||||
TextEdits: []analysis.TextEdit{{
|
||||
Pos: replaceStart,
|
||||
End: replaceEnd,
|
||||
NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
|
||||
}},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Equal", "EqualValues", "Exactly":
|
||||
if len(call.Args) < 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
arg1, arg2 := call.Args[0], call.Args[1]
|
||||
if anyCondSatisfaction(pass, isEmptyInterface, arg1, arg2) {
|
||||
return nil
|
||||
}
|
||||
if anyCondSatisfaction(pass, isBoolOverride, arg1, arg2) {
|
||||
return nil
|
||||
}
|
||||
|
||||
t1, t2 := isUntypedTrue(pass, arg1), isUntypedTrue(pass, arg2)
|
||||
f1, f2 := isUntypedFalse(pass, arg1), isUntypedFalse(pass, arg2)
|
||||
|
||||
switch {
|
||||
case xor(t1, t2):
|
||||
survivingArg, _ := anyVal([]bool{t1, t2}, arg2, arg1)
|
||||
if call.Fn.NameFTrimmed == "Exactly" && !isBuiltinBool(pass, survivingArg) {
|
||||
// NOTE(a.telyshev): `Exactly` assumes no type casting.
|
||||
return nil
|
||||
}
|
||||
return newUseTrueDiagnostic(survivingArg, arg1.Pos(), arg2.End())
|
||||
|
||||
case xor(f1, f2):
|
||||
survivingArg, _ := anyVal([]bool{f1, f2}, arg2, arg1)
|
||||
if call.Fn.NameFTrimmed == "Exactly" && !isBuiltinBool(pass, survivingArg) {
|
||||
// NOTE(a.telyshev): `Exactly` assumes no type casting.
|
||||
return nil
|
||||
}
|
||||
return newUseFalseDiagnostic(survivingArg, arg1.Pos(), arg2.End())
|
||||
}
|
||||
|
||||
case "NotEqual", "NotEqualValues":
|
||||
if len(call.Args) < 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
arg1, arg2 := call.Args[0], call.Args[1]
|
||||
if anyCondSatisfaction(pass, isEmptyInterface, arg1, arg2) {
|
||||
return nil
|
||||
}
|
||||
if anyCondSatisfaction(pass, isBoolOverride, arg1, arg2) {
|
||||
return nil
|
||||
}
|
||||
|
||||
t1, t2 := isUntypedTrue(pass, arg1), isUntypedTrue(pass, arg2)
|
||||
f1, f2 := isUntypedFalse(pass, arg1), isUntypedFalse(pass, arg2)
|
||||
|
||||
switch {
|
||||
case xor(t1, t2):
|
||||
survivingArg, _ := anyVal([]bool{t1, t2}, arg2, arg1)
|
||||
return newUseFalseDiagnostic(survivingArg, arg1.Pos(), arg2.End())
|
||||
|
||||
case xor(f1, f2):
|
||||
survivingArg, _ := anyVal([]bool{f1, f2}, arg2, arg1)
|
||||
return newUseTrueDiagnostic(survivingArg, arg1.Pos(), arg2.End())
|
||||
}
|
||||
|
||||
case "True":
|
||||
if len(call.Args) < 1 {
|
||||
return nil
|
||||
}
|
||||
expr := call.Args[0]
|
||||
|
||||
{
|
||||
arg1, ok1 := isComparisonWithTrue(pass, expr, token.EQL)
|
||||
arg2, ok2 := isComparisonWithFalse(pass, expr, token.NEQ)
|
||||
|
||||
survivingArg, ok := anyVal([]bool{ok1, ok2}, arg1, arg2)
|
||||
if ok && !isEmptyInterface(pass, survivingArg) {
|
||||
return newNeedSimplifyDiagnostic(survivingArg, expr.Pos(), expr.End())
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
arg1, ok1 := isComparisonWithTrue(pass, expr, token.NEQ)
|
||||
arg2, ok2 := isComparisonWithFalse(pass, expr, token.EQL)
|
||||
arg3, ok3 := isNegation(expr)
|
||||
|
||||
survivingArg, ok := anyVal([]bool{ok1, ok2, ok3}, arg1, arg2, arg3)
|
||||
if ok && !isEmptyInterface(pass, survivingArg) {
|
||||
return newUseFalseDiagnostic(survivingArg, expr.Pos(), expr.End())
|
||||
}
|
||||
}
|
||||
|
||||
case "False":
|
||||
if len(call.Args) < 1 {
|
||||
return nil
|
||||
}
|
||||
expr := call.Args[0]
|
||||
|
||||
{
|
||||
arg1, ok1 := isComparisonWithTrue(pass, expr, token.EQL)
|
||||
arg2, ok2 := isComparisonWithFalse(pass, expr, token.NEQ)
|
||||
|
||||
survivingArg, ok := anyVal([]bool{ok1, ok2}, arg1, arg2)
|
||||
if ok && !isEmptyInterface(pass, survivingArg) {
|
||||
return newNeedSimplifyDiagnostic(survivingArg, expr.Pos(), expr.End())
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
arg1, ok1 := isComparisonWithTrue(pass, expr, token.NEQ)
|
||||
arg2, ok2 := isComparisonWithFalse(pass, expr, token.EQL)
|
||||
arg3, ok3 := isNegation(expr)
|
||||
|
||||
survivingArg, ok := anyVal([]bool{ok1, ok2, ok3}, arg1, arg2, arg3)
|
||||
if ok && !isEmptyInterface(pass, survivingArg) {
|
||||
return newUseTrueDiagnostic(survivingArg, expr.Pos(), expr.End())
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isNegation(e ast.Expr) (ast.Expr, bool) {
|
||||
ue, ok := e.(*ast.UnaryExpr)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return ue.X, ue.Op == token.NOT
|
||||
}
|
133
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/call_meta.go
generated
vendored
133
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/call_meta.go
generated
vendored
|
@ -1,133 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/types/typeutil"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
"github.com/Antonboom/testifylint/internal/testify"
|
||||
)
|
||||
|
||||
// CallMeta stores meta info about assertion function/method call, for example
|
||||
//
|
||||
// assert.Equal(t, 42, result, "helpful comment")
|
||||
type CallMeta struct {
|
||||
// Call stores the original AST call expression.
|
||||
Call *ast.CallExpr
|
||||
// Range contains start and end position of assertion call.
|
||||
analysis.Range
|
||||
// IsPkg true if this is package (not object) call.
|
||||
IsPkg bool
|
||||
// IsAssert true if this is "testify/assert" package (or object) call.
|
||||
IsAssert bool
|
||||
// Selector is the AST expression of "assert.Equal".
|
||||
Selector *ast.SelectorExpr
|
||||
// SelectorXStr is a string representation of Selector's left part – value before point, e.g. "assert".
|
||||
SelectorXStr string
|
||||
// Fn stores meta info about assertion function itself.
|
||||
Fn FnMeta
|
||||
// Args stores assertion call arguments but without `t *testing.T` argument.
|
||||
// E.g [42, result, "helpful comment"].
|
||||
Args []ast.Expr
|
||||
// ArgsRaw stores assertion call initial arguments.
|
||||
// E.g [t, 42, result, "helpful comment"].
|
||||
ArgsRaw []ast.Expr
|
||||
}
|
||||
|
||||
func (c CallMeta) String() string {
|
||||
return c.SelectorXStr + "." + c.Fn.Name
|
||||
}
|
||||
|
||||
// FnMeta stores meta info about assertion function itself, for example "Equal".
|
||||
type FnMeta struct {
|
||||
// Range contains start and end position of function Name.
|
||||
analysis.Range
|
||||
// Name is a function name.
|
||||
Name string
|
||||
// NameFTrimmed is a function name without "f" suffix.
|
||||
NameFTrimmed string
|
||||
// IsFmt is true if function is formatted, e.g. "Equalf".
|
||||
IsFmt bool
|
||||
// Signature represents assertion signature.
|
||||
Signature *types.Signature
|
||||
}
|
||||
|
||||
// NewCallMeta returns meta information about testify assertion call.
|
||||
// Returns nil if ast.CallExpr is not testify call.
|
||||
func NewCallMeta(pass *analysis.Pass, ce *ast.CallExpr) *CallMeta {
|
||||
se, ok := ce.Fun.(*ast.SelectorExpr)
|
||||
if !ok || se.Sel == nil {
|
||||
return nil
|
||||
}
|
||||
fnName := se.Sel.Name
|
||||
|
||||
initiatorPkg, isPkgCall := func() (*types.Package, bool) {
|
||||
// Examples:
|
||||
// s.Assert -> method of *suite.Suite -> package suite ("vendor/github.com/stretchr/testify/suite")
|
||||
// s.Assert().Equal -> method of *assert.Assertions -> package assert ("vendor/github.com/stretchr/testify/assert")
|
||||
// s.Equal -> method of *assert.Assertions -> package assert ("vendor/github.com/stretchr/testify/assert")
|
||||
// reqObj.Falsef -> method of *require.Assertions -> package require ("vendor/github.com/stretchr/testify/require")
|
||||
if sel, isSel := pass.TypesInfo.Selections[se]; isSel {
|
||||
return sel.Obj().Pkg(), false
|
||||
}
|
||||
|
||||
// Examples:
|
||||
// assert.False -> assert -> package assert ("vendor/github.com/stretchr/testify/assert")
|
||||
// require.NotEqualf -> require -> package require ("vendor/github.com/stretchr/testify/require")
|
||||
if id, isIdent := se.X.(*ast.Ident); isIdent {
|
||||
if selObj := pass.TypesInfo.ObjectOf(id); selObj != nil {
|
||||
if pkg, isPkgName := selObj.(*types.PkgName); isPkgName {
|
||||
return pkg.Imported(), true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}()
|
||||
if initiatorPkg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
isAssert := analysisutil.IsPkg(initiatorPkg, testify.AssertPkgName, testify.AssertPkgPath)
|
||||
isRequire := analysisutil.IsPkg(initiatorPkg, testify.RequirePkgName, testify.RequirePkgPath)
|
||||
if !(isAssert || isRequire) {
|
||||
return nil
|
||||
}
|
||||
|
||||
funcObj, ok := typeutil.Callee(pass.TypesInfo, ce).(*types.Func)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &CallMeta{
|
||||
Call: ce,
|
||||
Range: ce,
|
||||
IsPkg: isPkgCall,
|
||||
IsAssert: isAssert,
|
||||
Selector: se,
|
||||
SelectorXStr: analysisutil.NodeString(pass.Fset, se.X),
|
||||
Fn: FnMeta{
|
||||
Range: se.Sel,
|
||||
Name: fnName,
|
||||
NameFTrimmed: strings.TrimSuffix(fnName, "f"),
|
||||
IsFmt: strings.HasSuffix(fnName, "f"),
|
||||
Signature: funcObj.Type().(*types.Signature), // NOTE(a.telyshev): Func's Type() is always a *Signature.
|
||||
},
|
||||
Args: trimTArg(pass, ce.Args),
|
||||
ArgsRaw: ce.Args,
|
||||
}
|
||||
}
|
||||
|
||||
func trimTArg(pass *analysis.Pass, args []ast.Expr) []ast.Expr {
|
||||
if len(args) == 0 {
|
||||
return args
|
||||
}
|
||||
|
||||
if implementsTestingT(pass, args[0]) {
|
||||
return args[1:]
|
||||
}
|
||||
return args
|
||||
}
|
23
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/checker.go
generated
vendored
23
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/checker.go
generated
vendored
|
@ -1,23 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
// Checker describes named checker.
|
||||
type Checker interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
// RegularChecker check assertion call presented in CallMeta form.
|
||||
type RegularChecker interface {
|
||||
Checker
|
||||
Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic
|
||||
}
|
||||
|
||||
// AdvancedChecker implements complex Check logic different from trivial CallMeta check.
|
||||
type AdvancedChecker interface {
|
||||
Checker
|
||||
Check(pass *analysis.Pass, inspector *inspector.Inspector) []analysis.Diagnostic
|
||||
}
|
109
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go
generated
vendored
109
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go
generated
vendored
|
@ -1,109 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// registry stores checkers meta information in checkers' priority order.
|
||||
var registry = checkersRegistry{
|
||||
// Regular checkers.
|
||||
{factory: asCheckerFactory(NewFloatCompare), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewBoolCompare), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewEmpty), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewLen), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewNegativePositive), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewCompares), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewErrorNil), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewNilCompare), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewErrorIsAs), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewExpectedActual), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewSuiteExtraAssertCall), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewSuiteDontUsePkg), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewUselessAssert), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewFormatter), enabledByDefault: true},
|
||||
// Advanced checkers.
|
||||
{factory: asCheckerFactory(NewBlankImport), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewGoRequire), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewRequireError), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewSuiteBrokenParallel), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewSuiteSubtestRun), enabledByDefault: true},
|
||||
{factory: asCheckerFactory(NewSuiteTHelper), enabledByDefault: false},
|
||||
}
|
||||
|
||||
type checkersRegistry []checkerMeta
|
||||
|
||||
type checkerMeta struct {
|
||||
factory checkerFactory
|
||||
enabledByDefault bool
|
||||
}
|
||||
|
||||
type checkerFactory func() Checker
|
||||
|
||||
func asCheckerFactory[T Checker](fn func() T) checkerFactory {
|
||||
return func() Checker {
|
||||
return fn()
|
||||
}
|
||||
}
|
||||
|
||||
func (r checkersRegistry) get(name string) (m checkerMeta, priority int, found bool) {
|
||||
for i, meta := range r {
|
||||
if meta.factory().Name() == name {
|
||||
return meta, i, true
|
||||
}
|
||||
}
|
||||
return checkerMeta{}, 0, false
|
||||
}
|
||||
|
||||
// All returns all checkers names sorted by checker's priority.
|
||||
func All() []string {
|
||||
result := make([]string, 0, len(registry))
|
||||
for _, meta := range registry {
|
||||
result = append(result, meta.factory().Name())
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// EnabledByDefault returns checkers enabled by default sorted by checker's priority.
|
||||
func EnabledByDefault() []string {
|
||||
result := make([]string, 0, len(registry))
|
||||
for _, meta := range registry {
|
||||
if meta.enabledByDefault {
|
||||
result = append(result, meta.factory().Name())
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Get returns new checker instance by checker's name.
|
||||
func Get(name string) (Checker, bool) {
|
||||
meta, _, ok := registry.get(name)
|
||||
if ok {
|
||||
return meta.factory(), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// IsKnown checks if there is a checker with that name.
|
||||
func IsKnown(name string) bool {
|
||||
_, _, ok := registry.get(name)
|
||||
return ok
|
||||
}
|
||||
|
||||
// IsEnabledByDefault returns true if a checker is enabled by default.
|
||||
// Returns false if there is no such checker in the registry.
|
||||
// For pre-validation use Get or IsKnown.
|
||||
func IsEnabledByDefault(name string) bool {
|
||||
meta, _, ok := registry.get(name)
|
||||
return ok && meta.enabledByDefault
|
||||
}
|
||||
|
||||
// SortByPriority mutates the input checkers names by sorting them in checker priority order.
|
||||
// Ignores unknown checkers. For pre-validation use Get or IsKnown.
|
||||
func SortByPriority(checkers []string) {
|
||||
sort.Slice(checkers, func(i, j int) bool {
|
||||
lhs, rhs := checkers[i], checkers[j]
|
||||
_, lhsPriority, _ := registry.get(lhs)
|
||||
_, rhsPriority, _ := registry.get(rhs)
|
||||
return lhsPriority < rhsPriority
|
||||
})
|
||||
}
|
99
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go
generated
vendored
99
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go
generated
vendored
|
@ -1,99 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
// Compares detects situations like
|
||||
//
|
||||
// assert.True(t, a == b)
|
||||
// assert.True(t, a != b)
|
||||
// assert.True(t, a > b)
|
||||
// assert.True(t, a >= b)
|
||||
// assert.True(t, a < b)
|
||||
// assert.True(t, a <= b)
|
||||
// assert.False(t, a == b)
|
||||
// ...
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.Equal(t, a, b)
|
||||
// assert.NotEqual(t, a, b)
|
||||
// assert.Greater(t, a, b)
|
||||
// assert.GreaterOrEqual(t, a, b)
|
||||
// assert.Less(t, a, b)
|
||||
// assert.LessOrEqual(t, a, b)
|
||||
//
|
||||
// If `a` and `b` are pointers then `assert.Same`/`NotSame` is required instead,
|
||||
// due to the inappropriate recursive nature of `assert.Equal` (based on `reflect.DeepEqual`).
|
||||
type Compares struct{}
|
||||
|
||||
// NewCompares constructs Compares checker.
|
||||
func NewCompares() Compares { return Compares{} }
|
||||
func (Compares) Name() string { return "compares" }
|
||||
|
||||
func (checker Compares) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
if len(call.Args) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
be, ok := call.Args[0].(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tokenToProposedFn map[token.Token]string
|
||||
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "True":
|
||||
tokenToProposedFn = tokenToProposedFnInsteadOfTrue
|
||||
case "False":
|
||||
tokenToProposedFn = tokenToProposedFnInsteadOfFalse
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
proposedFn, ok := tokenToProposedFn[be.Op]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if isPointer(pass, be.X) && isPointer(pass, be.Y) {
|
||||
switch proposedFn {
|
||||
case "Equal":
|
||||
proposedFn = "Same"
|
||||
case "NotEqual":
|
||||
proposedFn = "NotSame"
|
||||
}
|
||||
}
|
||||
|
||||
a, b := be.X, be.Y
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
|
||||
newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
|
||||
Pos: be.X.Pos(),
|
||||
End: be.Y.End(),
|
||||
NewText: formatAsCallArgs(pass, a, b),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
var tokenToProposedFnInsteadOfTrue = map[token.Token]string{
|
||||
token.EQL: "Equal",
|
||||
token.NEQ: "NotEqual",
|
||||
token.GTR: "Greater",
|
||||
token.GEQ: "GreaterOrEqual",
|
||||
token.LSS: "Less",
|
||||
token.LEQ: "LessOrEqual",
|
||||
}
|
||||
|
||||
var tokenToProposedFnInsteadOfFalse = map[token.Token]string{
|
||||
token.EQL: "NotEqual",
|
||||
token.NEQ: "Equal",
|
||||
token.GTR: "LessOrEqual",
|
||||
token.GEQ: "Less",
|
||||
token.LSS: "GreaterOrEqual",
|
||||
token.LEQ: "Greater",
|
||||
}
|
169
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go
generated
vendored
169
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go
generated
vendored
|
@ -1,169 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
// Empty detects situations like
|
||||
//
|
||||
// assert.Len(t, arr, 0)
|
||||
// assert.Equal(t, 0, len(arr))
|
||||
// assert.EqualValues(t, 0, len(arr))
|
||||
// assert.Exactly(t, 0, len(arr))
|
||||
// assert.LessOrEqual(t, len(arr), 0)
|
||||
// assert.GreaterOrEqual(t, 0, len(arr))
|
||||
// assert.Less(t, len(arr), 0)
|
||||
// assert.Greater(t, 0, len(arr))
|
||||
// assert.Less(t, len(arr), 1)
|
||||
// assert.Greater(t, 1, len(arr))
|
||||
// assert.Zero(t, len(arr))
|
||||
// assert.Empty(t, len(arr))
|
||||
//
|
||||
// assert.NotEqual(t, 0, len(arr))
|
||||
// assert.NotEqualValues(t, 0, len(arr))
|
||||
// assert.Less(t, 0, len(arr))
|
||||
// assert.Greater(t, len(arr), 0)
|
||||
// assert.Positive(t, len(arr))
|
||||
// assert.NotZero(t, len(arr))
|
||||
// assert.NotEmpty(t, len(arr))
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.Empty(t, arr)
|
||||
// assert.NotEmpty(t, arr)
|
||||
type Empty struct{}
|
||||
|
||||
// NewEmpty constructs Empty checker.
|
||||
func NewEmpty() Empty { return Empty{} }
|
||||
func (Empty) Name() string { return "empty" }
|
||||
|
||||
func (checker Empty) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
if d := checker.checkEmpty(pass, call); d != nil {
|
||||
return d
|
||||
}
|
||||
return checker.checkNotEmpty(pass, call)
|
||||
}
|
||||
|
||||
func (checker Empty) checkEmpty(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic { //nolint:gocognit
|
||||
newUseEmptyDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic {
|
||||
const proposed = "Empty"
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
|
||||
newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
|
||||
Pos: replaceStart,
|
||||
End: replaceEnd,
|
||||
NewText: analysisutil.NodeBytes(pass.Fset, replaceWith),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
if len(call.Args) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := call.Args[0]
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Zero", "Empty":
|
||||
lenArg, ok := isBuiltinLenCall(pass, a)
|
||||
if ok {
|
||||
return newUseEmptyDiagnostic(a.Pos(), a.End(), lenArg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(call.Args) < 2 {
|
||||
return nil
|
||||
}
|
||||
b := call.Args[1]
|
||||
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Len":
|
||||
if isZero(b) {
|
||||
return newUseEmptyDiagnostic(a.Pos(), b.End(), a)
|
||||
}
|
||||
|
||||
case "Equal", "EqualValues", "Exactly":
|
||||
arg1, ok1 := isLenCallAndZero(pass, a, b)
|
||||
arg2, ok2 := isLenCallAndZero(pass, b, a)
|
||||
|
||||
if lenArg, ok := anyVal([]bool{ok1, ok2}, arg1, arg2); ok {
|
||||
return newUseEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
|
||||
case "LessOrEqual":
|
||||
if lenArg, ok := isBuiltinLenCall(pass, a); ok && isZero(b) {
|
||||
return newUseEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
|
||||
case "GreaterOrEqual":
|
||||
if lenArg, ok := isBuiltinLenCall(pass, b); ok && isZero(a) {
|
||||
return newUseEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
|
||||
case "Less":
|
||||
if lenArg, ok := isBuiltinLenCall(pass, a); ok && (isOne(b) || isZero(b)) {
|
||||
return newUseEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
|
||||
case "Greater":
|
||||
if lenArg, ok := isBuiltinLenCall(pass, b); ok && (isOne(a) || isZero(a)) {
|
||||
return newUseEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (checker Empty) checkNotEmpty(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic { //nolint:gocognit
|
||||
newUseNotEmptyDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic {
|
||||
const proposed = "NotEmpty"
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
|
||||
newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
|
||||
Pos: replaceStart,
|
||||
End: replaceEnd,
|
||||
NewText: analysisutil.NodeBytes(pass.Fset, replaceWith),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
if len(call.Args) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := call.Args[0]
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "NotZero", "NotEmpty", "Positive":
|
||||
lenArg, ok := isBuiltinLenCall(pass, a)
|
||||
if ok {
|
||||
return newUseNotEmptyDiagnostic(a.Pos(), a.End(), lenArg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(call.Args) < 2 {
|
||||
return nil
|
||||
}
|
||||
b := call.Args[1]
|
||||
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "NotEqual", "NotEqualValues":
|
||||
arg1, ok1 := isLenCallAndZero(pass, a, b)
|
||||
arg2, ok2 := isLenCallAndZero(pass, b, a)
|
||||
|
||||
if lenArg, ok := anyVal([]bool{ok1, ok2}, arg1, arg2); ok {
|
||||
return newUseNotEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
|
||||
case "Less":
|
||||
if lenArg, ok := isBuiltinLenCall(pass, b); ok && isZero(a) {
|
||||
return newUseNotEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
|
||||
case "Greater":
|
||||
if lenArg, ok := isBuiltinLenCall(pass, a); ok && isZero(b) {
|
||||
return newUseNotEmptyDiagnostic(a.Pos(), b.End(), lenArg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
142
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go
generated
vendored
142
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go
generated
vendored
|
@ -1,142 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
// ErrorIsAs detects situations like
|
||||
//
|
||||
// assert.Error(t, err, errSentinel)
|
||||
// assert.NoError(t, err, errSentinel)
|
||||
// assert.True(t, errors.Is(err, errSentinel))
|
||||
// assert.False(t, errors.Is(err, errSentinel))
|
||||
// assert.True(t, errors.As(err, &target))
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.ErrorIs(t, err, errSentinel)
|
||||
// assert.NotErrorIs(t, err, errSentinel)
|
||||
// assert.ErrorAs(t, err, &target)
|
||||
//
|
||||
// Also ErrorIsAs repeats go vet's "errorsas" check logic.
|
||||
type ErrorIsAs struct{}
|
||||
|
||||
// NewErrorIsAs constructs ErrorIsAs checker.
|
||||
func NewErrorIsAs() ErrorIsAs { return ErrorIsAs{} }
|
||||
func (ErrorIsAs) Name() string { return "error-is-as" }
|
||||
|
||||
func (checker ErrorIsAs) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Error":
|
||||
if len(call.Args) >= 2 && isError(pass, call.Args[1]) {
|
||||
const proposed = "ErrorIs"
|
||||
msg := fmt.Sprintf("invalid usage of %[1]s.Error, use %[1]s.%[2]s instead", call.SelectorXStr, proposed)
|
||||
return newDiagnostic(checker.Name(), call, msg, newSuggestedFuncReplacement(call, proposed))
|
||||
}
|
||||
|
||||
case "NoError":
|
||||
if len(call.Args) >= 2 && isError(pass, call.Args[1]) {
|
||||
const proposed = "NotErrorIs"
|
||||
msg := fmt.Sprintf("invalid usage of %[1]s.NoError, use %[1]s.%[2]s instead", call.SelectorXStr, proposed)
|
||||
return newDiagnostic(checker.Name(), call, msg, newSuggestedFuncReplacement(call, proposed))
|
||||
}
|
||||
|
||||
case "True":
|
||||
if len(call.Args) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ce, ok := call.Args[0].(*ast.CallExpr)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if len(ce.Args) != 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var proposed string
|
||||
switch {
|
||||
case isErrorsIsCall(pass, ce):
|
||||
proposed = "ErrorIs"
|
||||
case isErrorsAsCall(pass, ce):
|
||||
proposed = "ErrorAs"
|
||||
}
|
||||
if proposed != "" {
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
|
||||
newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
|
||||
Pos: ce.Pos(),
|
||||
End: ce.End(),
|
||||
NewText: formatAsCallArgs(pass, ce.Args[0], ce.Args[1]),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
case "False":
|
||||
if len(call.Args) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ce, ok := call.Args[0].(*ast.CallExpr)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if len(ce.Args) != 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if isErrorsIsCall(pass, ce) {
|
||||
const proposed = "NotErrorIs"
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
|
||||
newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
|
||||
Pos: ce.Pos(),
|
||||
End: ce.End(),
|
||||
NewText: formatAsCallArgs(pass, ce.Args[0], ce.Args[1]),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
case "ErrorAs":
|
||||
if len(call.Args) < 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE(a.telyshev): Logic below must be consistent with
|
||||
// https://cs.opensource.google/go/x/tools/+/master:go/analysis/passes/errorsas/errorsas.go
|
||||
|
||||
var (
|
||||
defaultReport = fmt.Sprintf("second argument to %s must be a non-nil pointer to either a type that implements error, or to any interface type", call) //nolint:lll
|
||||
errorPtrReport = fmt.Sprintf("second argument to %s should not be *error", call)
|
||||
)
|
||||
|
||||
target := call.Args[1]
|
||||
|
||||
if isEmptyInterface(pass, target) {
|
||||
// `any` interface case. It is always allowed, since it often indicates
|
||||
// a value forwarded from another source.
|
||||
return nil
|
||||
}
|
||||
|
||||
tv, ok := pass.TypesInfo.Types[target]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
pt, ok := tv.Type.Underlying().(*types.Pointer)
|
||||
if !ok {
|
||||
return newDiagnostic(checker.Name(), call, defaultReport, nil)
|
||||
}
|
||||
if pt.Elem() == errorType {
|
||||
return newDiagnostic(checker.Name(), call, errorPtrReport, nil)
|
||||
}
|
||||
|
||||
_, isInterface := pt.Elem().Underlying().(*types.Interface)
|
||||
if !isInterface && !types.Implements(pt.Elem(), errorIface) {
|
||||
return newDiagnostic(checker.Name(), call, defaultReport, nil)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
92
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go
generated
vendored
92
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go
generated
vendored
|
@ -1,92 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
// ErrorNil detects situations like
|
||||
//
|
||||
// assert.Nil(t, err)
|
||||
// assert.NotNil(t, err)
|
||||
// assert.Equal(t, nil, err)
|
||||
// assert.EqualValues(t, nil, err)
|
||||
// assert.Exactly(t, nil, err)
|
||||
// assert.ErrorIs(t, err, nil)
|
||||
//
|
||||
// assert.NotEqual(t, nil, err)
|
||||
// assert.NotEqualValues(t, nil, err)
|
||||
// assert.NotErrorIs(t, err, nil)
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.NoError(t, err)
|
||||
// assert.Error(t, err)
|
||||
type ErrorNil struct{}
|
||||
|
||||
// NewErrorNil constructs ErrorNil checker.
|
||||
func NewErrorNil() ErrorNil { return ErrorNil{} }
|
||||
func (ErrorNil) Name() string { return "error-nil" }
|
||||
|
||||
func (checker ErrorNil) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
const (
|
||||
errorFn = "Error"
|
||||
noErrorFn = "NoError"
|
||||
)
|
||||
|
||||
proposedFn, survivingArg, replacementEndPos := func() (string, ast.Expr, token.Pos) {
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Nil":
|
||||
if len(call.Args) >= 1 && isError(pass, call.Args[0]) {
|
||||
return noErrorFn, call.Args[0], call.Args[0].End()
|
||||
}
|
||||
|
||||
case "NotNil":
|
||||
if len(call.Args) >= 1 && isError(pass, call.Args[0]) {
|
||||
return errorFn, call.Args[0], call.Args[0].End()
|
||||
}
|
||||
|
||||
case "Equal", "EqualValues", "Exactly", "ErrorIs":
|
||||
if len(call.Args) < 2 {
|
||||
return "", nil, token.NoPos
|
||||
}
|
||||
a, b := call.Args[0], call.Args[1]
|
||||
|
||||
switch {
|
||||
case isError(pass, a) && isNil(b):
|
||||
return noErrorFn, a, b.End()
|
||||
case isNil(a) && isError(pass, b):
|
||||
return noErrorFn, b, b.End()
|
||||
}
|
||||
|
||||
case "NotEqual", "NotEqualValues", "NotErrorIs":
|
||||
if len(call.Args) < 2 {
|
||||
return "", nil, token.NoPos
|
||||
}
|
||||
a, b := call.Args[0], call.Args[1]
|
||||
|
||||
switch {
|
||||
case isError(pass, a) && isNil(b):
|
||||
return errorFn, a, b.End()
|
||||
case isNil(a) && isError(pass, b):
|
||||
return errorFn, b, b.End()
|
||||
}
|
||||
}
|
||||
return "", nil, token.NoPos
|
||||
}()
|
||||
|
||||
if proposedFn != "" {
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
|
||||
newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
|
||||
Pos: call.Args[0].Pos(),
|
||||
End: replacementEndPos,
|
||||
NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
|
||||
}),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
179
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go
generated
vendored
179
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go
generated
vendored
|
@ -1,179 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"regexp"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
// DefaultExpectedVarPattern matches variables with "expected" or "wanted" prefix or suffix in the name.
|
||||
var DefaultExpectedVarPattern = regexp.MustCompile(
|
||||
`(^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$)`)
|
||||
|
||||
// ExpectedActual detects situations like
|
||||
//
|
||||
// assert.Equal(t, result, expected)
|
||||
// assert.EqualExportedValues(t, resultObj, User{Name: "Anton"})
|
||||
// assert.EqualValues(t, result, 42)
|
||||
// assert.Exactly(t, result, int64(42))
|
||||
// assert.JSONEq(t, result, `{"version": 3}`)
|
||||
// assert.InDelta(t, result, 42.42, 1.0)
|
||||
// assert.InDeltaMapValues(t, result, map[string]float64{"score": 0.99}, 1.0)
|
||||
// assert.InDeltaSlice(t, result, []float64{0.98, 0.99}, 1.0)
|
||||
// assert.InEpsilon(t, result, 42.42, 0.0001)
|
||||
// assert.InEpsilonSlice(t, result, []float64{0.9801, 0.9902}, 0.0001)
|
||||
// assert.IsType(t, result, (*User)(nil))
|
||||
// assert.NotEqual(t, result, "expected")
|
||||
// assert.NotEqualValues(t, result, "expected")
|
||||
// assert.NotSame(t, resultPtr, &value)
|
||||
// assert.Same(t, resultPtr, &value)
|
||||
// assert.WithinDuration(t, resultTime, time.Date(2023, 01, 12, 11, 46, 33, 0, nil), time.Second)
|
||||
// assert.YAMLEq(t, result, "version: '3'")
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.Equal(t, expected, result)
|
||||
// assert.EqualExportedValues(t, User{Name: "Anton"}, resultObj)
|
||||
// assert.EqualValues(t, 42, result)
|
||||
// ...
|
||||
type ExpectedActual struct {
|
||||
expVarPattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewExpectedActual constructs ExpectedActual checker using DefaultExpectedVarPattern.
|
||||
func NewExpectedActual() *ExpectedActual {
|
||||
return &ExpectedActual{expVarPattern: DefaultExpectedVarPattern}
|
||||
}
|
||||
|
||||
func (ExpectedActual) Name() string { return "expected-actual" }
|
||||
|
||||
func (checker *ExpectedActual) SetExpVarPattern(p *regexp.Regexp) *ExpectedActual {
|
||||
if p != nil {
|
||||
checker.expVarPattern = p
|
||||
}
|
||||
return checker
|
||||
}
|
||||
|
||||
func (checker ExpectedActual) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Equal",
|
||||
"EqualExportedValues",
|
||||
"EqualValues",
|
||||
"Exactly",
|
||||
"InDelta",
|
||||
"InDeltaMapValues",
|
||||
"InDeltaSlice",
|
||||
"InEpsilon",
|
||||
"InEpsilonSlice",
|
||||
"IsType",
|
||||
"JSONEq",
|
||||
"NotEqual",
|
||||
"NotEqualValues",
|
||||
"NotSame",
|
||||
"Same",
|
||||
"WithinDuration",
|
||||
"YAMLEq":
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(call.Args) < 2 {
|
||||
return nil
|
||||
}
|
||||
first, second := call.Args[0], call.Args[1]
|
||||
|
||||
if checker.isWrongExpectedActualOrder(pass, first, second) {
|
||||
return newDiagnostic(checker.Name(), call, "need to reverse actual and expected values", &analysis.SuggestedFix{
|
||||
Message: "Reverse actual and expected values",
|
||||
TextEdits: []analysis.TextEdit{
|
||||
{
|
||||
Pos: first.Pos(),
|
||||
End: second.End(),
|
||||
NewText: formatAsCallArgs(pass, second, first),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (checker ExpectedActual) isWrongExpectedActualOrder(pass *analysis.Pass, first, second ast.Expr) bool {
|
||||
leftIsCandidate := checker.isExpectedValueCandidate(pass, first)
|
||||
rightIsCandidate := checker.isExpectedValueCandidate(pass, second)
|
||||
return rightIsCandidate && !leftIsCandidate
|
||||
}
|
||||
|
||||
func (checker ExpectedActual) isExpectedValueCandidate(pass *analysis.Pass, expr ast.Expr) bool {
|
||||
switch v := expr.(type) {
|
||||
case *ast.ParenExpr:
|
||||
return checker.isExpectedValueCandidate(pass, v.X)
|
||||
|
||||
case *ast.StarExpr: // *value
|
||||
return checker.isExpectedValueCandidate(pass, v.X)
|
||||
|
||||
case *ast.UnaryExpr:
|
||||
return (v.Op == token.AND) && checker.isExpectedValueCandidate(pass, v.X) // &value
|
||||
|
||||
case *ast.CompositeLit:
|
||||
return true
|
||||
|
||||
case *ast.CallExpr:
|
||||
return isParenExpr(v) ||
|
||||
isCastedBasicLitOrExpectedValue(v, checker.expVarPattern) ||
|
||||
isExpectedValueFactory(pass, v, checker.expVarPattern)
|
||||
}
|
||||
|
||||
return isBasicLit(expr) ||
|
||||
isUntypedConst(pass, expr) ||
|
||||
isTypedConst(pass, expr) ||
|
||||
isIdentNamedAfterPattern(checker.expVarPattern, expr) ||
|
||||
isStructVarNamedAfterPattern(checker.expVarPattern, expr) ||
|
||||
isStructFieldNamedAfterPattern(checker.expVarPattern, expr)
|
||||
}
|
||||
|
||||
func isParenExpr(ce *ast.CallExpr) bool {
|
||||
_, ok := ce.Fun.(*ast.ParenExpr)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isCastedBasicLitOrExpectedValue(ce *ast.CallExpr, pattern *regexp.Regexp) bool {
|
||||
if len(ce.Args) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
fn, ok := ce.Fun.(*ast.Ident)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
switch fn.Name {
|
||||
case "complex64", "complex128":
|
||||
return true
|
||||
|
||||
case "uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"float32", "float64",
|
||||
"rune", "string":
|
||||
return isBasicLit(ce.Args[0]) || isIdentNamedAfterPattern(pattern, ce.Args[0])
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isExpectedValueFactory(pass *analysis.Pass, ce *ast.CallExpr, pattern *regexp.Regexp) bool {
|
||||
switch fn := ce.Fun.(type) {
|
||||
case *ast.Ident:
|
||||
return pattern.MatchString(fn.Name)
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
timeDateFn := analysisutil.ObjectOf(pass.Pkg, "time", "Date")
|
||||
if timeDateFn != nil && analysisutil.IsObj(pass.TypesInfo, fn.Sel, timeDateFn) {
|
||||
return true
|
||||
}
|
||||
return pattern.MatchString(fn.Sel.Name)
|
||||
}
|
||||
return false
|
||||
}
|
50
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go
generated
vendored
50
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go
generated
vendored
|
@ -1,50 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
// FloatCompare detects situations like
|
||||
//
|
||||
// assert.Equal(t, 42.42, result)
|
||||
// assert.EqualValues(t, 42.42, result)
|
||||
// assert.Exactly(t, 42.42, result)
|
||||
// assert.True(t, result == 42.42)
|
||||
// assert.False(t, result != 42.42)
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.InEpsilon(t, 42.42, result, 0.0001) // Or assert.InDelta
|
||||
type FloatCompare struct{}
|
||||
|
||||
// NewFloatCompare constructs FloatCompare checker.
|
||||
func NewFloatCompare() FloatCompare { return FloatCompare{} }
|
||||
func (FloatCompare) Name() string { return "float-compare" }
|
||||
|
||||
func (checker FloatCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
invalid := func() bool {
|
||||
switch call.Fn.NameFTrimmed {
|
||||
case "Equal", "EqualValues", "Exactly":
|
||||
return len(call.Args) > 1 && (isFloat(pass, call.Args[0]) || isFloat(pass, call.Args[1]))
|
||||
|
||||
case "True":
|
||||
return len(call.Args) > 0 && isComparisonWithFloat(pass, call.Args[0], token.EQL)
|
||||
|
||||
case "False":
|
||||
return len(call.Args) > 0 && isComparisonWithFloat(pass, call.Args[0], token.NEQ)
|
||||
}
|
||||
return false
|
||||
}()
|
||||
|
||||
if invalid {
|
||||
format := "use %s.InEpsilon (or InDelta)"
|
||||
if call.Fn.IsFmt {
|
||||
format = "use %s.InEpsilonf (or InDeltaf)"
|
||||
}
|
||||
return newDiagnostic(checker.Name(), call, fmt.Sprintf(format, call.SelectorXStr), nil)
|
||||
}
|
||||
return nil
|
||||
}
|
187
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go
generated
vendored
187
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go
generated
vendored
|
@ -1,187 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
"github.com/Antonboom/testifylint/internal/checkers/printf"
|
||||
"github.com/Antonboom/testifylint/internal/testify"
|
||||
)
|
||||
|
||||
// Formatter detects situations like
|
||||
//
|
||||
// assert.ElementsMatch(t, certConfig.Org, csr.Subject.Org, "organizations not equal")
|
||||
// assert.Error(t, err, fmt.Sprintf("Profile %s should not be valid", test.profile))
|
||||
// assert.Errorf(t, err, fmt.Sprintf("test %s", test.testName))
|
||||
// assert.Truef(t, targetTs.Equal(ts), "the timestamp should be as expected (%s) but was %s", targetTs)
|
||||
// ...
|
||||
//
|
||||
// and requires
|
||||
//
|
||||
// assert.ElementsMatchf(t, certConfig.Org, csr.Subject.Org, "organizations not equal")
|
||||
// assert.Errorf(t, err, "Profile %s should not be valid", test.profile)
|
||||
// assert.Errorf(t, err, "test %s", test.testName)
|
||||
// assert.Truef(t, targetTs.Equal(ts), "the timestamp should be as expected (%s) but was %s", targetTs, ts)
|
||||
type Formatter struct {
|
||||
checkFormatString bool
|
||||
requireFFuncs bool
|
||||
}
|
||||
|
||||
// NewFormatter constructs Formatter checker.
|
||||
func NewFormatter() *Formatter {
|
||||
return &Formatter{
|
||||
checkFormatString: true,
|
||||
requireFFuncs: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (Formatter) Name() string { return "formatter" }
|
||||
|
||||
func (checker *Formatter) SetCheckFormatString(v bool) *Formatter {
|
||||
checker.checkFormatString = v
|
||||
return checker
|
||||
}
|
||||
|
||||
func (checker *Formatter) SetRequireFFuncs(v bool) *Formatter {
|
||||
checker.requireFFuncs = v
|
||||
return checker
|
||||
}
|
||||
|
||||
func (checker Formatter) Check(pass *analysis.Pass, call *CallMeta) (result *analysis.Diagnostic) {
|
||||
if call.Fn.IsFmt {
|
||||
return checker.checkFmtAssertion(pass, call)
|
||||
}
|
||||
return checker.checkNotFmtAssertion(pass, call)
|
||||
}
|
||||
|
||||
func (checker Formatter) checkNotFmtAssertion(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
|
||||
msgAndArgsPos, ok := isPrintfLikeCall(pass, call, call.Fn.Signature)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
fFunc := call.Fn.Name + "f"
|
||||
|
||||
if msgAndArgsPos == len(call.ArgsRaw)-1 {
|
||||
msgAndArgs := call.ArgsRaw[msgAndArgsPos]
|
||||
if args, ok := isFmtSprintfCall(pass, msgAndArgs); ok {
|
||||
if checker.requireFFuncs {
|
||||
msg := fmt.Sprintf("remove unnecessary fmt.Sprintf and use %s.%s", call.SelectorXStr, fFunc)
|
||||
return newDiagnostic(checker.Name(), call, msg,
|
||||
newSuggestedFuncReplacement(call, fFunc, analysis.TextEdit{
|
||||
Pos: msgAndArgs.Pos(),
|
||||
End: msgAndArgs.End(),
|
||||
NewText: formatAsCallArgs(pass, args...),
|
||||
}),
|
||||
)
|
||||
}
|
||||
return newRemoveSprintfDiagnostic(pass, checker.Name(), call, msgAndArgs, args)
|
||||
}
|
||||
}
|
||||
|
||||
if checker.requireFFuncs {
|
||||
return newUseFunctionDiagnostic(checker.Name(), call, fFunc, newSuggestedFuncReplacement(call, fFunc))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (checker Formatter) checkFmtAssertion(pass *analysis.Pass, call *CallMeta) (result *analysis.Diagnostic) {
|
||||
formatPos := getMsgPosition(call.Fn.Signature)
|
||||
if formatPos < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
msg := call.ArgsRaw[formatPos]
|
||||
|
||||
if formatPos == len(call.ArgsRaw)-1 {
|
||||
if args, ok := isFmtSprintfCall(pass, msg); ok {
|
||||
return newRemoveSprintfDiagnostic(pass, checker.Name(), call, msg, args)
|
||||
}
|
||||
}
|
||||
|
||||
if checker.checkFormatString {
|
||||
report := pass.Report
|
||||
defer func() { pass.Report = report }()
|
||||
|
||||
pass.Report = func(d analysis.Diagnostic) {
|
||||
result = newDiagnostic(checker.Name(), call, d.Message, nil)
|
||||
}
|
||||
|
||||
format, err := strconv.Unquote(analysisutil.NodeString(pass.Fset, msg))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
printf.CheckPrintf(pass, call.Call, call.String(), format, formatPos)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func isPrintfLikeCall(pass *analysis.Pass, call *CallMeta, sig *types.Signature) (int, bool) {
|
||||
msgAndArgsPos := getMsgAndArgsPosition(sig)
|
||||
if msgAndArgsPos < 0 {
|
||||
return -1, false
|
||||
}
|
||||
|
||||
fmtFn := analysisutil.ObjectOf(pass.Pkg, testify.AssertPkgPath, call.Fn.Name+"f")
|
||||
if fmtFn == nil {
|
||||
// NOTE(a.telyshev): No formatted analogue of assertion.
|
||||
return -1, false
|
||||
}
|
||||
|
||||
return msgAndArgsPos, len(call.ArgsRaw) > msgAndArgsPos
|
||||
}
|
||||
|
||||
func getMsgAndArgsPosition(sig *types.Signature) int {
|
||||
params := sig.Params()
|
||||
if params.Len() < 1 {
|
||||
return -1
|
||||
}
|
||||
|
||||
lastIdx := params.Len() - 1
|
||||
lastParam := params.At(lastIdx)
|
||||
|
||||
_, isSlice := lastParam.Type().(*types.Slice)
|
||||
if lastParam.Name() == "msgAndArgs" && isSlice {
|
||||
return lastIdx
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func getMsgPosition(sig *types.Signature) int {
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
param := sig.Params().At(i)
|
||||
|
||||
if b, ok := param.Type().(*types.Basic); ok && b.Kind() == types.String && param.Name() == "msg" {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func isFmtSprintfCall(pass *analysis.Pass, expr ast.Expr) ([]ast.Expr, bool) {
|
||||
ce, ok := expr.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
se, ok := ce.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
sprintfObj := analysisutil.ObjectOf(pass.Pkg, "fmt", "Sprintf")
|
||||
if sprintfObj == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if !analysisutil.IsObj(pass.TypesInfo, se.Sel, sprintfObj) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return ce.Args, true
|
||||
}
|
345
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go
generated
vendored
345
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go
generated
vendored
|
@ -1,345 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
const (
|
||||
goRequireFnReportFormat = "%s contains assertions that must only be used in the goroutine running the test function"
|
||||
goRequireCallReportFormat = "%s must only be used in the goroutine running the test function"
|
||||
goRequireHTTPHandlerReportFormat = "do not use %s in http handlers"
|
||||
)
|
||||
|
||||
// GoRequire takes idea from go vet's "testinggoroutine" check
|
||||
// and detects usage of require package's functions or assert.FailNow in the non-test goroutines
|
||||
//
|
||||
// go func() {
|
||||
// conn, err = lis.Accept()
|
||||
// require.NoError(t, err)
|
||||
//
|
||||
// if assert.Error(err) {
|
||||
// assert.FailNow(t, msg)
|
||||
// }
|
||||
// }()
|
||||
type GoRequire struct {
|
||||
ignoreHTTPHandlers bool
|
||||
}
|
||||
|
||||
// NewGoRequire constructs GoRequire checker.
|
||||
func NewGoRequire() *GoRequire { return new(GoRequire) }
|
||||
func (GoRequire) Name() string { return "go-require" }
|
||||
|
||||
func (checker *GoRequire) SetIgnoreHTTPHandlers(v bool) *GoRequire {
|
||||
checker.ignoreHTTPHandlers = v
|
||||
return checker
|
||||
}
|
||||
|
||||
// Check should be consistent with
|
||||
// https://cs.opensource.google/go/x/tools/+/master:go/analysis/passes/testinggoroutine/testinggoroutine.go
|
||||
//
|
||||
// But due to the fact that the Check covers cases missed by go vet,
|
||||
// the implementation turned out to be terribly complicated.
|
||||
//
|
||||
// In simple words, the algorithm is as follows:
|
||||
// - we walk along the call tree and store the status, whether we are in the test goroutine or not;
|
||||
// - if we are in a test goroutine, then require is allowed, otherwise not;
|
||||
// - when we encounter the launch of a subtest or `go` statement, the status changes;
|
||||
// - in order to correctly handle the return to the correct status when exiting the current function,
|
||||
// we have to store a stack of statuses (inGoroutineRunningTestFunc).
|
||||
//
|
||||
// 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) {
|
||||
testsDecls := make(funcDeclarations)
|
||||
inspector.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) {
|
||||
fd := node.(*ast.FuncDecl)
|
||||
|
||||
if isTestingFuncOrMethod(pass, fd) {
|
||||
if tf, ok := pass.TypesInfo.ObjectOf(fd.Name).(*types.Func); ok {
|
||||
testsDecls[tf] = fd
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var inGoroutineRunningTestFunc boolStack
|
||||
processedFuncs := make(map[*ast.FuncDecl]goRequireVerdict)
|
||||
|
||||
nodesFilter := []ast.Node{
|
||||
(*ast.FuncDecl)(nil),
|
||||
(*ast.FuncType)(nil),
|
||||
(*ast.GoStmt)(nil),
|
||||
(*ast.CallExpr)(nil),
|
||||
}
|
||||
inspector.Nodes(nodesFilter, func(node ast.Node, push bool) bool {
|
||||
if fd, ok := node.(*ast.FuncDecl); ok {
|
||||
if !isTestingFuncOrMethod(pass, fd) {
|
||||
return false
|
||||
}
|
||||
|
||||
if push {
|
||||
inGoroutineRunningTestFunc.Push(true)
|
||||
} else {
|
||||
inGoroutineRunningTestFunc.Pop()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if ft, ok := node.(*ast.FuncType); ok {
|
||||
if !isTestingAnonymousFunc(pass, ft) {
|
||||
return false
|
||||
}
|
||||
|
||||
if push {
|
||||
inGoroutineRunningTestFunc.Push(true)
|
||||
} else {
|
||||
inGoroutineRunningTestFunc.Pop()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if _, ok := node.(*ast.GoStmt); ok {
|
||||
if push {
|
||||
inGoroutineRunningTestFunc.Push(false)
|
||||
} else {
|
||||
inGoroutineRunningTestFunc.Pop()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
ce := node.(*ast.CallExpr)
|
||||
if isSubTestRun(pass, ce) {
|
||||
if push {
|
||||
// t.Run spawns the new testing goroutine and declines
|
||||
// possible warnings from previous "simple" goroutine.
|
||||
inGoroutineRunningTestFunc.Push(true)
|
||||
} else {
|
||||
inGoroutineRunningTestFunc.Pop()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if !push {
|
||||
return false
|
||||
}
|
||||
if inGoroutineRunningTestFunc.Len() == 0 {
|
||||
// Insufficient info.
|
||||
return true
|
||||
}
|
||||
if inGoroutineRunningTestFunc.Last() {
|
||||
// We are in testing goroutine and can skip any assertion checks.
|
||||
return true
|
||||
}
|
||||
|
||||
testifyCall := NewCallMeta(pass, ce)
|
||||
if testifyCall != nil {
|
||||
switch checker.checkCall(testifyCall) {
|
||||
case goRequireVerdictRequire:
|
||||
d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireCallReportFormat, "require"), nil)
|
||||
diagnostics = append(diagnostics, *d)
|
||||
|
||||
case goRequireVerdictAssertFailNow:
|
||||
d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireCallReportFormat, testifyCall), nil)
|
||||
diagnostics = append(diagnostics, *d)
|
||||
|
||||
case goRequireVerdictNoExit:
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Case of nested function call.
|
||||
{
|
||||
calledFd := testsDecls.Get(pass, ce)
|
||||
if calledFd == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if v := checker.checkFunc(pass, calledFd, testsDecls, processedFuncs); v != goRequireVerdictNoExit {
|
||||
caller := analysisutil.NodeString(pass.Fset, ce.Fun)
|
||||
d := newDiagnostic(checker.Name(), ce, fmt.Sprintf(goRequireFnReportFormat, caller), nil)
|
||||
diagnostics = append(diagnostics, *d)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if !checker.ignoreHTTPHandlers {
|
||||
diagnostics = append(diagnostics, checker.checkHTTPHandlers(pass, inspector)...)
|
||||
}
|
||||
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
func (checker GoRequire) checkHTTPHandlers(pass *analysis.Pass, insp *inspector.Inspector) (diagnostics []analysis.Diagnostic) {
|
||||
insp.WithStack([]ast.Node{(*ast.CallExpr)(nil)}, func(node ast.Node, push bool, stack []ast.Node) bool {
|
||||
if !push {
|
||||
return false
|
||||
}
|
||||
if len(stack) < 3 {
|
||||
return true
|
||||
}
|
||||
|
||||
fID := findSurroundingFunc(pass, stack)
|
||||
if fID == nil || !fID.meta.isHTTPHandler {
|
||||
return true
|
||||
}
|
||||
|
||||
testifyCall := NewCallMeta(pass, node.(*ast.CallExpr))
|
||||
if testifyCall == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
switch checker.checkCall(testifyCall) {
|
||||
case goRequireVerdictRequire:
|
||||
d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireHTTPHandlerReportFormat, "require"), nil)
|
||||
diagnostics = append(diagnostics, *d)
|
||||
|
||||
case goRequireVerdictAssertFailNow:
|
||||
d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireHTTPHandlerReportFormat, testifyCall), nil)
|
||||
diagnostics = append(diagnostics, *d)
|
||||
|
||||
case goRequireVerdictNoExit:
|
||||
}
|
||||
return false
|
||||
})
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
func (checker GoRequire) checkFunc(
|
||||
pass *analysis.Pass,
|
||||
fd *ast.FuncDecl,
|
||||
testsDecls funcDeclarations,
|
||||
processedFuncs map[*ast.FuncDecl]goRequireVerdict,
|
||||
) (result goRequireVerdict) {
|
||||
if v, ok := processedFuncs[fd]; ok {
|
||||
return v
|
||||
}
|
||||
|
||||
ast.Inspect(fd, func(node ast.Node) bool {
|
||||
if result != goRequireVerdictNoExit {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, ok := node.(*ast.GoStmt); ok {
|
||||
return false
|
||||
}
|
||||
|
||||
ce, ok := node.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
testifyCall := NewCallMeta(pass, ce)
|
||||
if testifyCall != nil {
|
||||
if v := checker.checkCall(testifyCall); v != goRequireVerdictNoExit {
|
||||
result, processedFuncs[fd] = v, v
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Case of nested function call.
|
||||
{
|
||||
calledFd := testsDecls.Get(pass, ce)
|
||||
if calledFd == nil {
|
||||
return true
|
||||
}
|
||||
if calledFd == fd {
|
||||
// Recursion.
|
||||
return true
|
||||
}
|
||||
|
||||
if v := checker.checkFunc(pass, calledFd, testsDecls, processedFuncs); v != goRequireVerdictNoExit {
|
||||
result = v
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
type goRequireVerdict int
|
||||
|
||||
const (
|
||||
goRequireVerdictNoExit goRequireVerdict = iota
|
||||
goRequireVerdictRequire
|
||||
goRequireVerdictAssertFailNow
|
||||
)
|
||||
|
||||
func (checker GoRequire) checkCall(call *CallMeta) goRequireVerdict {
|
||||
if !call.IsAssert {
|
||||
return goRequireVerdictRequire
|
||||
}
|
||||
if call.Fn.NameFTrimmed == "FailNow" {
|
||||
return goRequireVerdictAssertFailNow
|
||||
}
|
||||
return goRequireVerdictNoExit
|
||||
}
|
||||
|
||||
type funcDeclarations map[*types.Func]*ast.FuncDecl
|
||||
|
||||
// Get returns the declaration of a called function or method.
|
||||
// Currently, only static calls within the same package are supported, otherwise returns nil.
|
||||
func (fd funcDeclarations) Get(pass *analysis.Pass, ce *ast.CallExpr) *ast.FuncDecl {
|
||||
var obj types.Object
|
||||
|
||||
switch fun := ce.Fun.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
obj = pass.TypesInfo.ObjectOf(fun.Sel)
|
||||
|
||||
case *ast.Ident:
|
||||
obj = pass.TypesInfo.ObjectOf(fun)
|
||||
|
||||
case *ast.IndexExpr:
|
||||
if id, ok := fun.X.(*ast.Ident); ok {
|
||||
obj = pass.TypesInfo.ObjectOf(id)
|
||||
}
|
||||
|
||||
case *ast.IndexListExpr:
|
||||
if id, ok := fun.X.(*ast.Ident); ok {
|
||||
obj = pass.TypesInfo.ObjectOf(id)
|
||||
}
|
||||
}
|
||||
|
||||
if tf, ok := obj.(*types.Func); ok {
|
||||
return fd[tf]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type boolStack []bool
|
||||
|
||||
func (s boolStack) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s *boolStack) Push(v bool) {
|
||||
*s = append(*s, v)
|
||||
}
|
||||
|
||||
func (s *boolStack) Pop() bool {
|
||||
n := len(*s)
|
||||
if n == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
last := (*s)[n-1]
|
||||
*s = (*s)[:n-1]
|
||||
return last
|
||||
}
|
||||
|
||||
func (s boolStack) Last() bool {
|
||||
n := len(s)
|
||||
if n == 0 {
|
||||
return false
|
||||
}
|
||||
return s[n-1]
|
||||
}
|
43
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers.go
generated
vendored
43
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers.go
generated
vendored
|
@ -1,43 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func xor(a, b bool) bool {
|
||||
return a != b
|
||||
}
|
||||
|
||||
// anyVal returns the first value[i] for which bools[i] is true.
|
||||
func anyVal[T any](bools []bool, vals ...T) (T, bool) {
|
||||
if len(bools) != len(vals) {
|
||||
panic("inconsistent usage of valOr") //nolint:forbidigo // Does not depend on the code being analyzed.
|
||||
}
|
||||
|
||||
for i, b := range bools {
|
||||
if b {
|
||||
return vals[i], true
|
||||
}
|
||||
}
|
||||
|
||||
var _default T
|
||||
return _default, false
|
||||
}
|
||||
|
||||
func anyCondSatisfaction(pass *analysis.Pass, p predicate, vals ...ast.Expr) bool {
|
||||
for _, v := range vals {
|
||||
if p(pass, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// p transforms simple is-function in a predicate.
|
||||
func p(fn func(e ast.Expr) bool) predicate {
|
||||
return func(_ *analysis.Pass, e ast.Expr) bool {
|
||||
return fn(e)
|
||||
}
|
||||
}
|
113
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go
generated
vendored
113
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go
generated
vendored
|
@ -1,113 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func isZero(e ast.Expr) bool { return isIntNumber(e, 0) }
|
||||
|
||||
func isOne(e ast.Expr) bool { return isIntNumber(e, 1) }
|
||||
|
||||
func isAnyZero(e ast.Expr) bool {
|
||||
return isIntNumber(e, 0) || isTypedSignedIntNumber(e, 0) || isTypedUnsignedIntNumber(e, 0)
|
||||
}
|
||||
|
||||
func isNotAnyZero(e ast.Expr) bool {
|
||||
return !isAnyZero(e)
|
||||
}
|
||||
|
||||
func isZeroOrSignedZero(e ast.Expr) bool {
|
||||
return isIntNumber(e, 0) || isTypedSignedIntNumber(e, 0)
|
||||
}
|
||||
|
||||
func isSignedNotZero(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return !isUnsigned(pass, e) && !isZeroOrSignedZero(e)
|
||||
}
|
||||
|
||||
func isTypedSignedIntNumber(e ast.Expr, v int) bool {
|
||||
return isTypedIntNumber(e, v, "int", "int8", "int16", "int32", "int64")
|
||||
}
|
||||
|
||||
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 {
|
||||
ce, ok := e.(*ast.CallExpr)
|
||||
if !ok || len(ce.Args) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
fn, ok := ce.Fun.(*ast.Ident)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, t := range types {
|
||||
if fn.Name == t {
|
||||
return isIntNumber(ce.Args[0], v)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isIntNumber(e ast.Expr, v int) bool {
|
||||
bl, ok := e.(*ast.BasicLit)
|
||||
return ok && bl.Kind == token.INT && bl.Value == fmt.Sprintf("%d", v)
|
||||
}
|
||||
|
||||
func isBasicLit(e ast.Expr) bool {
|
||||
_, ok := e.(*ast.BasicLit)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isIntBasicLit(e ast.Expr) bool {
|
||||
bl, ok := e.(*ast.BasicLit)
|
||||
return ok && bl.Kind == token.INT
|
||||
}
|
||||
|
||||
func isUntypedConst(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return isUnderlying(pass, e, types.IsUntyped)
|
||||
}
|
||||
|
||||
func isTypedConst(pass *analysis.Pass, e ast.Expr) bool {
|
||||
tt, ok := pass.TypesInfo.Types[e]
|
||||
return ok && tt.IsValue() && tt.Value != nil
|
||||
}
|
||||
|
||||
func isFloat(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return isUnderlying(pass, e, types.IsFloat)
|
||||
}
|
||||
|
||||
func isUnsigned(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return isUnderlying(pass, e, types.IsUnsigned)
|
||||
}
|
||||
|
||||
func isUnderlying(pass *analysis.Pass, e ast.Expr, flag types.BasicInfo) bool {
|
||||
t := pass.TypesInfo.TypeOf(e)
|
||||
if t == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
bt, ok := t.Underlying().(*types.Basic)
|
||||
return ok && (bt.Info()&flag > 0)
|
||||
}
|
||||
|
||||
func isPointer(pass *analysis.Pass, e ast.Expr) bool {
|
||||
_, ok := pass.TypesInfo.TypeOf(e).(*types.Pointer)
|
||||
return ok
|
||||
}
|
||||
|
||||
// untype returns v from type(v) expression or v itself if there is no type cast.
|
||||
func untype(e ast.Expr) ast.Expr {
|
||||
ce, ok := e.(*ast.CallExpr)
|
||||
if !ok || len(ce.Args) != 1 {
|
||||
return e
|
||||
}
|
||||
return ce.Args[0]
|
||||
}
|
33
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_bool.go
generated
vendored
33
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_bool.go
generated
vendored
|
@ -1,33 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
var (
|
||||
falseObj = types.Universe.Lookup("false")
|
||||
trueObj = types.Universe.Lookup("true")
|
||||
)
|
||||
|
||||
func isUntypedTrue(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return analysisutil.IsObj(pass.TypesInfo, e, trueObj)
|
||||
}
|
||||
|
||||
func isUntypedFalse(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return analysisutil.IsObj(pass.TypesInfo, e, falseObj)
|
||||
}
|
||||
|
||||
func isBuiltinBool(pass *analysis.Pass, e ast.Expr) bool {
|
||||
basicType, ok := pass.TypesInfo.TypeOf(e).(*types.Basic)
|
||||
return ok && basicType.Kind() == types.Bool
|
||||
}
|
||||
|
||||
func isBoolOverride(pass *analysis.Pass, e ast.Expr) bool {
|
||||
namedType, ok := pass.TypesInfo.TypeOf(e).(*types.Named)
|
||||
return ok && namedType.Obj().Name() == "bool"
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func isComparisonWithFloat(p *analysis.Pass, e ast.Expr, op token.Token) bool {
|
||||
be, ok := e.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return be.Op == op && (isFloat(p, be.X) || isFloat(p, be.Y))
|
||||
}
|
||||
|
||||
func isComparisonWithTrue(pass *analysis.Pass, e ast.Expr, op token.Token) (ast.Expr, bool) {
|
||||
return isComparisonWith(pass, e, isUntypedTrue, op)
|
||||
}
|
||||
|
||||
func isComparisonWithFalse(pass *analysis.Pass, e ast.Expr, op token.Token) (ast.Expr, bool) {
|
||||
return isComparisonWith(pass, e, isUntypedFalse, op)
|
||||
}
|
||||
|
||||
type predicate func(pass *analysis.Pass, e ast.Expr) bool
|
||||
|
||||
func isComparisonWith(
|
||||
pass *analysis.Pass,
|
||||
e ast.Expr,
|
||||
predicate predicate,
|
||||
op token.Token,
|
||||
) (ast.Expr, bool) {
|
||||
be, ok := e.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if be.Op != op {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
t1, t2 := predicate(pass, be.X), predicate(pass, be.Y)
|
||||
if xor(t1, t2) {
|
||||
if t1 {
|
||||
return be.Y, true
|
||||
}
|
||||
return be.X, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func isStrictComparisonWith(
|
||||
pass *analysis.Pass,
|
||||
e ast.Expr,
|
||||
lhs predicate,
|
||||
op token.Token,
|
||||
rhs predicate,
|
||||
) (ast.Expr, ast.Expr, bool) {
|
||||
be, ok := e.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
if be.Op == op && lhs(pass, be.X) && rhs(pass, be.Y) {
|
||||
return be.X, be.Y, true
|
||||
}
|
||||
return nil, nil, false
|
||||
}
|
126
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_context.go
generated
vendored
126
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_context.go
generated
vendored
|
@ -1,126 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
type funcID struct {
|
||||
pos token.Pos
|
||||
posStr string
|
||||
name string
|
||||
meta funcMeta
|
||||
}
|
||||
|
||||
type funcMeta struct {
|
||||
isTestCleanup bool
|
||||
isGoroutine bool
|
||||
isHTTPHandler bool
|
||||
}
|
||||
|
||||
func (id funcID) String() string {
|
||||
return fmt.Sprintf("%s at %s", id.name, id.posStr)
|
||||
}
|
||||
|
||||
func findSurroundingFunc(pass *analysis.Pass, stack []ast.Node) *funcID {
|
||||
for i := len(stack) - 2; i >= 0; i-- {
|
||||
var fType *ast.FuncType
|
||||
var fName string
|
||||
var isTestCleanup bool
|
||||
var isGoroutine bool
|
||||
var isHTTPHandler bool
|
||||
|
||||
switch fd := stack[i].(type) {
|
||||
case *ast.FuncDecl:
|
||||
fType, fName = fd.Type, fd.Name.Name
|
||||
|
||||
if isSuiteMethod(pass, fd) {
|
||||
if ident := fd.Name; ident != nil && isSuiteAfterTestMethod(ident.Name) {
|
||||
isTestCleanup = true
|
||||
}
|
||||
}
|
||||
|
||||
if mimicHTTPHandler(pass, fd.Type) {
|
||||
isHTTPHandler = true
|
||||
}
|
||||
|
||||
case *ast.FuncLit:
|
||||
fType, fName = fd.Type, "anonymous"
|
||||
|
||||
if mimicHTTPHandler(pass, fType) {
|
||||
isHTTPHandler = true
|
||||
}
|
||||
|
||||
if i >= 2 { //nolint:nestif
|
||||
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")
|
||||
}
|
||||
|
||||
if _, ok := stack[i-2].(*ast.GoStmt); ok {
|
||||
isGoroutine = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
return &funcID{
|
||||
pos: fType.Pos(),
|
||||
posStr: pass.Fset.Position(fType.Pos()).String(),
|
||||
name: fName,
|
||||
meta: funcMeta{
|
||||
isTestCleanup: isTestCleanup,
|
||||
isGoroutine: isGoroutine,
|
||||
isHTTPHandler: isHTTPHandler,
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findNearestNode[T ast.Node](stack []ast.Node) (v T) {
|
||||
v, _ = findNearestNodeWithIdx[T](stack)
|
||||
return
|
||||
}
|
||||
|
||||
func findNearestNodeWithIdx[T ast.Node](stack []ast.Node) (v T, index int) {
|
||||
for i := len(stack) - 2; i >= 0; i-- {
|
||||
if n, ok := stack[i].(T); ok {
|
||||
return n, i
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fnContainsAssertions(pass *analysis.Pass, fn *ast.FuncDecl) bool {
|
||||
if fn.Body == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, s := range fn.Body.List {
|
||||
if isAssertionStmt(pass, s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isAssertionStmt(pass *analysis.Pass, stmt ast.Stmt) bool {
|
||||
expr, ok := stmt.(*ast.ExprStmt)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
ce, ok := expr.X.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return NewCallMeta(pass, ce) != nil
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
func newUseFunctionDiagnostic(
|
||||
checker string,
|
||||
call *CallMeta,
|
||||
proposedFn string,
|
||||
fix *analysis.SuggestedFix,
|
||||
) *analysis.Diagnostic {
|
||||
f := proposedFn
|
||||
if call.Fn.IsFmt {
|
||||
f += "f"
|
||||
}
|
||||
msg := fmt.Sprintf("use %s.%s", call.SelectorXStr, f)
|
||||
|
||||
return newDiagnostic(checker, call, msg, fix)
|
||||
}
|
||||
|
||||
func newRemoveSprintfDiagnostic(
|
||||
pass *analysis.Pass,
|
||||
checker string,
|
||||
call *CallMeta,
|
||||
sprintfPos analysis.Range,
|
||||
sprintfArgs []ast.Expr,
|
||||
) *analysis.Diagnostic {
|
||||
return newDiagnostic(checker, call, "remove unnecessary fmt.Sprintf", &analysis.SuggestedFix{
|
||||
Message: "Remove `fmt.Sprintf`",
|
||||
TextEdits: []analysis.TextEdit{
|
||||
{
|
||||
Pos: sprintfPos.Pos(),
|
||||
End: sprintfPos.End(),
|
||||
NewText: formatAsCallArgs(pass, sprintfArgs...),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func newDiagnostic(
|
||||
checker string,
|
||||
rng analysis.Range,
|
||||
msg string,
|
||||
fix *analysis.SuggestedFix,
|
||||
) *analysis.Diagnostic {
|
||||
d := analysis.Diagnostic{
|
||||
Pos: rng.Pos(),
|
||||
End: rng.End(),
|
||||
Category: checker,
|
||||
Message: checker + ": " + msg,
|
||||
}
|
||||
if fix != nil {
|
||||
d.SuggestedFixes = []analysis.SuggestedFix{*fix}
|
||||
}
|
||||
return &d
|
||||
}
|
||||
|
||||
func newSuggestedFuncReplacement(
|
||||
call *CallMeta,
|
||||
proposedFn string,
|
||||
additionalEdits ...analysis.TextEdit,
|
||||
) *analysis.SuggestedFix {
|
||||
if call.Fn.IsFmt {
|
||||
proposedFn += "f"
|
||||
}
|
||||
return &analysis.SuggestedFix{
|
||||
Message: fmt.Sprintf("Replace `%s` with `%s`", call.Fn.Name, proposedFn),
|
||||
TextEdits: append([]analysis.TextEdit{
|
||||
{
|
||||
Pos: call.Fn.Pos(),
|
||||
End: call.Fn.End(),
|
||||
NewText: []byte(proposedFn),
|
||||
},
|
||||
}, additionalEdits...),
|
||||
}
|
||||
}
|
42
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go
generated
vendored
42
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
var (
|
||||
errorObj = types.Universe.Lookup("error")
|
||||
errorType = errorObj.Type()
|
||||
errorIface = errorType.Underlying().(*types.Interface)
|
||||
)
|
||||
|
||||
func isError(pass *analysis.Pass, expr ast.Expr) bool {
|
||||
return pass.TypesInfo.TypeOf(expr) == errorType
|
||||
}
|
||||
|
||||
func isErrorsIsCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
|
||||
return isErrorsPkgFnCall(pass, ce, "Is")
|
||||
}
|
||||
|
||||
func isErrorsAsCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
|
||||
return isErrorsPkgFnCall(pass, ce, "As")
|
||||
}
|
||||
|
||||
func isErrorsPkgFnCall(pass *analysis.Pass, ce *ast.CallExpr, fn string) bool {
|
||||
se, ok := ce.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
errorsIsObj := analysisutil.ObjectOf(pass.Pkg, "errors", fn)
|
||||
if errorsIsObj == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return analysisutil.IsObj(pass.TypesInfo, se.Sel, errorsIsObj)
|
||||
}
|
26
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go
generated
vendored
26
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go
generated
vendored
|
@ -1,26 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
// formatAsCallArgs joins a, b and c and returns bytes like `a, b, c`.
|
||||
func formatAsCallArgs(pass *analysis.Pass, args ...ast.Expr) []byte {
|
||||
if len(args) == 0 {
|
||||
return []byte("")
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
for i, arg := range args {
|
||||
buf.Write(analysisutil.NodeBytes(pass.Fset, arg))
|
||||
if i != len(args)-1 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
35
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_http.go
generated
vendored
35
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_http.go
generated
vendored
|
@ -1,35 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
func mimicHTTPHandler(pass *analysis.Pass, fType *ast.FuncType) bool {
|
||||
httpHandlerFuncObj := analysisutil.ObjectOf(pass.Pkg, "net/http", "HandlerFunc")
|
||||
if httpHandlerFuncObj == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
sig, ok := httpHandlerFuncObj.Type().Underlying().(*types.Signature)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(fType.Params.List) != sig.Params().Len() {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
lhs := sig.Params().At(i).Type()
|
||||
rhs := pass.TypesInfo.TypeOf(fType.Params.List[i].Type)
|
||||
if !types.Identical(lhs, rhs) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
"github.com/Antonboom/testifylint/internal/testify"
|
||||
)
|
||||
|
||||
func isEmptyInterface(pass *analysis.Pass, expr ast.Expr) bool {
|
||||
t, ok := pass.TypesInfo.Types[expr]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
iface, ok := t.Type.Underlying().(*types.Interface)
|
||||
return ok && iface.NumMethods() == 0
|
||||
}
|
||||
|
||||
func implementsTestifySuite(pass *analysis.Pass, e ast.Expr) bool {
|
||||
suiteIfaceObj := analysisutil.ObjectOf(pass.Pkg, testify.SuitePkgPath, "TestingSuite")
|
||||
return (suiteIfaceObj != nil) && implements(pass, e, suiteIfaceObj)
|
||||
}
|
||||
|
||||
func implementsTestingT(pass *analysis.Pass, e ast.Expr) bool {
|
||||
return implementsAssertTestingT(pass, e) || implementsRequireTestingT(pass, e)
|
||||
}
|
||||
|
||||
func implementsAssertTestingT(pass *analysis.Pass, e ast.Expr) bool {
|
||||
assertTestingTObj := analysisutil.ObjectOf(pass.Pkg, testify.AssertPkgPath, "TestingT")
|
||||
return (assertTestingTObj != nil) && implements(pass, e, assertTestingTObj)
|
||||
}
|
||||
|
||||
func implementsRequireTestingT(pass *analysis.Pass, e ast.Expr) bool {
|
||||
requireTestingTObj := analysisutil.ObjectOf(pass.Pkg, testify.RequirePkgPath, "TestingT")
|
||||
return (requireTestingTObj != nil) && implements(pass, e, requireTestingTObj)
|
||||
}
|
||||
|
||||
func implements(pass *analysis.Pass, e ast.Expr, ifaceObj types.Object) bool {
|
||||
t := pass.TypesInfo.TypeOf(e)
|
||||
if t == nil {
|
||||
return false
|
||||
}
|
||||
return types.Implements(t, ifaceObj.Type().Underlying().(*types.Interface))
|
||||
}
|
55
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_len.go
generated
vendored
55
tests/tools/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_len.go
generated
vendored
|
@ -1,55 +0,0 @@
|
|||
package checkers
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/Antonboom/testifylint/internal/analysisutil"
|
||||
)
|
||||
|
||||
var lenObj = types.Universe.Lookup("len")
|
||||
|
||||
func isLenEquality(pass *analysis.Pass, e ast.Expr) (ast.Expr, ast.Expr, bool) {
|
||||
be, ok := e.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
if be.Op != token.EQL {
|
||||
return nil, nil, false
|
||||
}
|
||||
return xorLenCall(pass, be.X, be.Y)
|
||||
}
|
||||
|
||||
func xorLenCall(pass *analysis.Pass, a, b ast.Expr) (lenArg ast.Expr, expectedLen ast.Expr, ok bool) {
|
||||
arg1, ok1 := isBuiltinLenCall(pass, a)
|
||||
arg2, ok2 := isBuiltinLenCall(pass, b)
|
||||
|
||||
if xor(ok1, ok2) {
|
||||
if ok1 {
|
||||
return arg1, b, true
|
||||
}
|
||||
return arg2, a, true
|
||||
}
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
func isLenCallAndZero(pass *analysis.Pass, a, b ast.Expr) (ast.Expr, bool) {
|
||||
lenArg, ok := isBuiltinLenCall(pass, a)
|
||||
return lenArg, ok && isZero(b)
|
||||
}
|
||||
|
||||
func isBuiltinLenCall(pass *analysis.Pass, e ast.Expr) (ast.Expr, bool) {
|
||||
ce, ok := e.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if analysisutil.IsObj(pass.TypesInfo, ce.Fun, lenObj) && len(ce.Args) == 1 {
|
||||
return ce.Args[0], true
|
||||
}
|
||||
return nil, false
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue